在软件版权保护的时候可以用CPU的序列号来保证只在一台机上运行,有哪一位师兄可以告诉我如何才能获得CPU的序列号,或者有什么更好的保护软件的办法。谢谢!

解决方案 »

  1.   

    用汇编 cpuid 指令,
    我有个纯vb代码的实现,可惜是公司的不能给你
      

  2.   

    http://www.csdn.net/cnshare/soft/7/7899.shtm
      

  3.   

    http://www.csdn.net/cnshare/soft/9/9091.shtm
      

  4.   

    可以写汇编代码,字节流,用byte数组实现,然后API CallWindowProc去执行他
    你到csdn上搜索下,可以找到,不过他的程序有个bug,需要修改下
      

  5.   

    API中提供的有关硬件的函数比较少。你可以使用GetSystemInfo获得大致的CPU类型,参考微软的Knowledge Base的文章:“Q147886 ow VB Can Get Windows Status Information via API Calls”。而象CPU序列号等信息只能使用汇编指令获得,所以VB无法获得。硬盘的厂商序列号也无法在VB中获得,只能获得操作系统格式化时产生的序列号(QA000894 "如何调用GetVolumeInformation获得磁盘序列号")。某些硬件资料可以在注册表中的HKEY_LOCAL_MACHINE底下得到。http://www.china-askpro.com/msg14/qa61.shtml
      

  6.   

    用vb获得我已经实现了, 参考c的代码修改的, 花了一个晚上
    大体上是准备machinecode, 然后调用API CallWindowProc,传递你要传递变量的地址,让他执行,然后用eax做返回值
    提供一个函数给你, 可以获取cpu serial的一部分,不过用来加密cpu是没有问题的了Public MachineCode() As Byte
    Public Sub InitMachineCode_CpuType() 'code for get CPU type
        '//==B==head
                                    ReDim Preserve MachineCode(0) As Byte
        MachineCode(UBound(MachineCode)) = &H55  'push ebp
                                    ReDim Preserve MachineCode(UBound(MachineCode) + 1) As Byte
        MachineCode(UBound(MachineCode)) = &H8B  'move ebp, esp
                                    ReDim Preserve MachineCode(UBound(MachineCode) + 1) As Byte
        MachineCode(UBound(MachineCode)) = &HEC
                                    ReDim Preserve MachineCode(UBound(MachineCode) + 1) As Byte
        MachineCode(UBound(MachineCode)) = &H57  'push edi
                                    ReDim Preserve MachineCode(UBound(MachineCode) + 1) As Byte
        MachineCode(UBound(MachineCode)) = &H52  'push edx
                                    ReDim Preserve MachineCode(UBound(MachineCode) + 1) As Byte
        MachineCode(UBound(MachineCode)) = &H51  'push ecx
                                    ReDim Preserve MachineCode(UBound(MachineCode) + 1) As Byte
        MachineCode(UBound(MachineCode)) = &H53  'push ebx
        '//==E===head
        
        '// 注意这个时候践中的分配 eax可以不push,因为vb vc编译器不用他做长保留,为返回值,调用函数前编译器也不push eax why?
        '// ----lower memory----    ebp = esp(mov ebp,esp}    push order   val
        '// old ebp 'push ebp                                      6       [ebp]
        '// eip     'CallWindowProc function will call[asm call]   5       [ebp+4]
        '// param 1 'CallWindowProc function will push param1      4       [ebp+8]
        '// param 2 'CallWindowProc function will push param4      3       [ebp+12]
        '// param 3 'CallWindowProc function will push param4      2       [ebp+16]
        '// param 4 'CallWindowProc function will push param5      1       [ebp+20]
        '// ---higher  memory---
        
                                    ReDim Preserve MachineCode(UBound(MachineCode) + 1) As Byte
        MachineCode(UBound(MachineCode)) = &H8B  'mov eax, dword ptr [ebp+8]    eax = param1
                                    ReDim Preserve MachineCode(UBound(MachineCode) + 1) As Byte
        MachineCode(UBound(MachineCode)) = &H45
                                    ReDim Preserve MachineCode(UBound(MachineCode) + 1) As Byte
        MachineCode(UBound(MachineCode)) = &H8
        
                                    ReDim Preserve MachineCode(UBound(MachineCode) + 1) As Byte
        MachineCode(UBound(MachineCode)) = &HF  'cpuid
                                    ReDim Preserve MachineCode(UBound(MachineCode) + 1) As Byte
        MachineCode(UBound(MachineCode)) = &HA2
        
        '//b debug
       '                             ReDim Preserve MachineCode(UBound(MachineCode) + 1) As Byte
       ' MachineCode(UBound(MachineCode)) = &H8B  'mov ebx, eax
       '                             ReDim Preserve MachineCode(UBound(MachineCode) + 1) As Byte
       ' MachineCode(UBound(MachineCode)) = &HD8
        '//e debug
        
                                    ReDim Preserve MachineCode(UBound(MachineCode) + 1) As Byte
        MachineCode(UBound(MachineCode)) = &H8B 'mov edi, dword ptr [ebp+12]  *param2 = ebx
                                    ReDim Preserve MachineCode(UBound(MachineCode) + 1) As Byte
        MachineCode(UBound(MachineCode)) = &H7D
                                    ReDim Preserve MachineCode(UBound(MachineCode) + 1) As Byte
        MachineCode(UBound(MachineCode)) = &HC
                                    ReDim Preserve MachineCode(UBound(MachineCode) + 1) As Byte
        MachineCode(UBound(MachineCode)) = &H89 'mov dword ptr [edi],ebx
                                    ReDim Preserve MachineCode(UBound(MachineCode) + 1) As Byte
        MachineCode(UBound(MachineCode)) = &H1F
        
                                    ReDim Preserve MachineCode(UBound(MachineCode) + 1) As Byte
        MachineCode(UBound(MachineCode)) = &H8B 'mov edi, dword ptr [ebp+16]  *param3 = edx
                                    ReDim Preserve MachineCode(UBound(MachineCode) + 1) As Byte
        MachineCode(UBound(MachineCode)) = &H7D
                                    ReDim Preserve MachineCode(UBound(MachineCode) + 1) As Byte
        MachineCode(UBound(MachineCode)) = &H10
                                    ReDim Preserve MachineCode(UBound(MachineCode) + 1) As Byte
        MachineCode(UBound(MachineCode)) = &H89 'mov dword ptr [edi], edx
                                    ReDim Preserve MachineCode(UBound(MachineCode) + 1) As Byte
        MachineCode(UBound(MachineCode)) = &H17
        
        
                                    ReDim Preserve MachineCode(UBound(MachineCode) + 1) As Byte
        MachineCode(UBound(MachineCode)) = &H8B 'mov edi, dword ptr [ebp+20]  *param4 = ecx
                                    ReDim Preserve MachineCode(UBound(MachineCode) + 1) As Byte
        MachineCode(UBound(MachineCode)) = &H7D
                                    ReDim Preserve MachineCode(UBound(MachineCode) + 1) As Byte
        MachineCode(UBound(MachineCode)) = &H14
                                    ReDim Preserve MachineCode(UBound(MachineCode) + 1) As Byte
        MachineCode(UBound(MachineCode)) = &H89 'mov dword ptr [edi], ecx
                                    ReDim Preserve MachineCode(UBound(MachineCode) + 1) As Byte
        MachineCode(UBound(MachineCode)) = &HF
        
        
        '//==B==tail
                                    ReDim Preserve MachineCode(UBound(MachineCode) + 1) As Byte
        MachineCode(UBound(MachineCode)) = &H53 'pop ebx
                                    ReDim Preserve MachineCode(UBound(MachineCode) + 1) As Byte
        MachineCode(UBound(MachineCode)) = &H59 'pop ecx
                                    ReDim Preserve MachineCode(UBound(MachineCode) + 1) As Byte
        MachineCode(UBound(MachineCode)) = &H5A 'pop edx
                                    ReDim Preserve MachineCode(UBound(MachineCode) + 1) As Byte
        MachineCode(UBound(MachineCode)) = &H55 'pop edi
        
                                    ReDim Preserve MachineCode(UBound(MachineCode) + 1) As Byte
        MachineCode(UBound(MachineCode)) = &H8B 'mov esp ebp
                                    ReDim Preserve MachineCode(UBound(MachineCode) + 1) As Byte
        MachineCode(UBound(MachineCode)) = &HE5
                                    ReDim Preserve MachineCode(UBound(MachineCode) + 1) As Byte
        MachineCode(UBound(MachineCode)) = &H5D 'pop ebp
    '                                ReDim Preserve MachineCode(UBound(MachineCode) + 1) As Byte
    '    MachineCode(UBound(MachineCode)) = &HC3 'ret
                                    ReDim Preserve MachineCode(UBound(MachineCode) + 1) As Byte
        MachineCode(UBound(MachineCode)) = &HC2 'ret 10h
                                    ReDim Preserve MachineCode(UBound(MachineCode) + 1) As Byte
        MachineCode(UBound(MachineCode)) = &H10
                                    ReDim Preserve MachineCode(UBound(MachineCode) + 1) As Byte
        MachineCode(UBound(MachineCode)) = &H0
        '其实上面直接ret &HC3也行,调用这个call的函数在asm级会判断 方法如下
        '在push参数之前首先push &HDCBAABCD 和 push esi
        '如果ret10h, 这样 cmp[esp+4],&HDCBAABCD相等,不等证明是ret,这样 会进行 add esp, 10h的操作
        '当然后面会 add esp,8h  修正&HDCBAABCD 和 esi的push
        '//==E==tail
        
    End Sub
      

  7.   

    http://www.applevb.com/sourcecode/cpuinfo.zip
      

  8.   

    然后
    dim vendor_id(11) as byte
    dim lngCpuID as long call InitMachineCode_CpuType
    lngCpuID = CallWindowProc(VarPtr(MachineCode.MachineCode(0)), 1, VarPtr(vendor_id(0)), VarPtr(vendor_id(4)), VarPtr(vendor_id(8)))
    可以了
      

  9.   

    楼上的,请问MachineCode()里的值是什么意思呢?
      

  10.   

    怎样加载API CallWindowProc??
      

  11.   

    程序运行时提示CallWindowProc没有定义?怎么回事呀
      

  12.   

    在一个模块中申明
    Public Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hwnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
      

  13.   

    MachineCode.MachineCode(0)在这个地方出现无效限定字符,为什么
      

  14.   

    to :  ChrisCai(星光灿烂) ( ) 
    machinecode.machinecode(0) 因为我的machinecode是在machindecode.bas模块中定义的,忘了说,你去掉machinecode. 就可以了
      

  15.   

    lngCpuID = CallWindowProc(VarPtr(MachineCode(0)), 1, VarPtr(vendor_id(0)), VarPtr(vendor_id(4)), VarPtr(vendor_id(8)))在这个地方出现"DLL调用约定错误"
      

  16.   

    不会的都是long型, byval传递怎么可能, 把 1 修改成 1& 试试
      

  17.   

    得到硬盘物理序列号或BIOS信息的你要么?
      

  18.   

    程序运行没有错误,可是没有显示结果,lngCpuID为空,怎么回事??
      

  19.   

    另外 vendor_id(0-3)为ebx, vendor_id(4-7)为edx vendor_id(8-11)为ecx
    返回值为eax
    可以调用 1 功能,然后判断edx 即 vendor_id(4-7) 注意是内存排列
    edx 的 第18位为1表示支持psn 
    如果支持psn:
    这个时候eax即返回值为 psn的64-93位
    然后调用 3 功能
    edx 即 vendor_id(4,7)为psn的32-63位
    ecx 即 vendor_id(8-11)为psn的0-31位连接起来就是个完整的psn
      

  20.   

    SYSTEM_INFO 类型定义 
    Type SYSTEM_INFO ' 36 Bytes 
    dwOemID As Long
    dwPageSize As Long
    lpMinimumApplicationAddress As Long
    lpMaximumApplicationAddress As Long
    dwActiveProcessorMask As Long
    dwNumberOrfProcessors As Long
    dwProcessorType As Long
    dwAllocationGranularity As Long
    wProcessorLevel As Integer
    wProcessorRevision As Integer
    End Type 
    说明 
    This structure contains information regarding the current computer system.
     
     
    dwOemID Long,System processor used. In Windows 95, this value is always set to zero (PROCESSOR_ARCHITECTURE_INTEL). In Windows NT, this value may be one of the following : PROCESSOR_ARCHITECTURE_INTEL, PROCESSOR_ARCHITECTURE_MIPS, PROCESSOR_ARCHITECTURE_ALPHA, PROCESSOR_ARCHITECTURE_PPC 
    dwPageSize Long,Page size used. Also specifies the granularity of page protection and commitment. 
    lpMinimumApplicationAddress Long,Contains the lowest memory address that applications and dynamic link libraries (DLLs) can access. 
    lpMaximumApplicationAddress Long,Contains the highest memory address that applications and DLLs can access. 
    dwActiveProcessorMask Long,Contains a mask representing the set of processors available on the system. Processor zero is indicated by bit zero being set. 
    dwNumberOrfProcessors Long,The number of processors in this system. 
    dwProcessorType Long,Obsolete, but maintained for backward compatibility. Can be one of the following values: PROCESSOR_INTEL_386, PROCESSOR_INTEL_486, PROCESSOR_INTEL_PENTIUM. The following are valid on Windows NT systems only: PROCESSOR_MIPS_R4000, PROCESSOR_ALPHA_21046 
    dwAllocationGranularity Long,Contains the allocation granularity used to allocate memory. This value is usually set to 64K. 
    wProcessorLevel Integer,Specifies the processor level. This value depends on the PROCESSOR_ARCHITECTURE_* value in the dwOemID field. For PROCESSOR_ARCHITECTURE_INTEL, the valid values are currently: 3 for a 386 CPU, 4 for a 486 CPU, and 5 for a Pentium. 
    wProcessorRevision Integer,Specifies the processor revision. This value depends on the PROCESSOR_ARCHITECTURE_* value in the dwOemID field. 
      

  21.   

    老是出现"DLL调用约定错误",气死我了
      

  22.   

    http://expert.csdn.net/Expert/topic/1880/1880880.xml?temp=.325741
    http://expert.csdn.net/Expert/topic/1972/1972386.xml?temp=.3529016
    http://expert.csdn.net/Expert/topic/1969/1969640.xml?temp=.2918817
    http://expert.csdn.net/Expert/topic/1880/1880883.xml?temp=.9266626
    http://expert.csdn.net/Expert/topic/1838/1838722.xml?temp=.7783167
    http://expert.csdn.net/Expert/topic/1680/1680715.xml?temp=.3237268http://expert.csdn.net/Expert/topic/1328/1328644.xml?temp=.9751093
      

  23.   

    下面的例子完全用VB进行ASM编程的示例,本例获得CPU ID.
    工程文件分为一个form1.frm 和一个模块module1.bas----------------------form1.frm的源文件---------------------VERSION 5.00
    Begin VB.Form Form1 
       Caption         =   "Form1"
       ClientHeight    =   1965
       ClientLeft      =   60
       ClientTop       =   345
       ClientWidth     =   3105
       LinkTopic       =   "Form1"
       ScaleHeight     =   1965
       ScaleWidth      =   3105
       StartUpPosition =   2  'Bildschirmmitte
       Begin VB.CommandButton Command1 
          Caption         =   "Get CPU Name"
          Height          =   495
          Left            =   840
          TabIndex        =   0
          Top             =   315
          Width           =   1425
       End
       Begin VB.Label Label2 
          Alignment       =   2  'Zentriert
          AutoSize        =   -1  'True
          BeginProperty Font 
             Name            =   "MS Sans Serif"
             Size            =   9.75
             Charset         =   0
             Weight          =   400
             Underline       =   0   'False
             Italic          =   0   'False
             Strikethrough   =   0   'False
          EndProperty
          Height          =   240
          Left            =   1515
          TabIndex        =   2
          Top             =   1065
          Width           =   60
       End
       Begin VB.Label Label1 
          Alignment       =   2  'Zentriert
          AutoSize        =   -1  'True
          BeginProperty Font 
             Name            =   "Arial"
             Size            =   12
             Charset         =   0
             Weight          =   700
             Underline       =   0   'False
             Italic          =   0   'False
             Strikethrough   =   0   'False
          EndProperty
          Height          =   285
          Left            =   1515
          TabIndex        =   1
          Top             =   1350
          Width           =   75
       End
    End
    Attribute VB_Name = "Form1"
    Attribute VB_GlobalNameSpace = False
    Attribute VB_Creatable = False
    Attribute VB_PredeclaredId = True
    Attribute VB_Exposed = False
    Option ExplicitPrivate Sub Command1_MouseDown(Button As Integer, Shift As Integer, x As Single, Y As Single)    Label1 = ""
        Label2 = ""End SubPrivate Sub Command1_Click()
        
        Label1 = GetCpuName() & " CPU"
        Label2 = "You have a" & IIf(InStr("AEIOU", Left$(Label1, 1)), "n", "")End Sub
    ------------------------------end---------------------------------下面是modu1e.bas的源代码----------------------module1.bas的源文件--------------------------
    Option Explicit
    '
    'This shows how to incorporate machine code into VB
    '''''''''''''''''''''''''''''''''''''''''''''''''''
    'The example fills the array with a few machine instructions and then copies
    'them to a procedure address. The modified procedure is then called thru
    'CallWindowProc. The result of this specific machine code is your CPU Vendor Name.
    '
    '##########################################################################
    'Apparently it gets a Stack Pointer Error, but I don't know why; if anybody
    'can fix that please let me know...                          [email protected]
    'The Error is not present in the native compiled version; so I think it got
    'something to do with the P-Code Calling Convention (strange though)...
    '##########################################################################
    '
    'Sub Dummy serves to reserve some space to copy the machine instructions into.
    '
    '
    'Tested on Intel and AMD CPU's (uncompiled and compiled)
    '
    '
    Private Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hWnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
    Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (lpvDest As Any, lpvSource As Any, ByVal cbCopy As Long)
    Private x As LongPublic Function GetCpuName() As String
      
      Dim MachineCode(0 To 35)  As Byte
      Dim VarAddr               As Long
      Dim FunctAddr             As Long
      Dim EAX                   As Long
      Dim CPUName(1 To 12)      As Byte
      
      'set up machine code
        
        MachineCode(0) = &H55    'push ebp
        
        MachineCode(1) = &H8B    'move ebp,esp
        MachineCode(2) = &HEC
        
        MachineCode(3) = &H57    'push edi
        
        MachineCode(4) = &H52    'push edx
        
        MachineCode(5) = &H51    'push ecx
        
        MachineCode(6) = &H53    'push ebx
        
        MachineCode(7) = &H8B    'move eax,dword ptr [ebp+8]
        MachineCode(8) = &H45
        MachineCode(9) = &H8
        
        MachineCode(10) = &HF    'cpuid
        MachineCode(11) = &HA2
        
        MachineCode(12) = &H8B   'mov edi,dword ptr [ebp+12]
        MachineCode(13) = &H7D
        MachineCode(14) = &HC
        
        MachineCode(15) = &H89   'move dword ptr [edi],ebx
        MachineCode(16) = &H1F
        
        MachineCode(17) = &H8B   'mov edi,dword ptr [ebp+16]
        MachineCode(18) = &H7D
        MachineCode(19) = &H10
        
        MachineCode(20) = &H89   'move dword ptr [edi],ecx
        MachineCode(21) = &HF
        
        MachineCode(22) = &H8B   'mov edi,dword ptr [ebp+20]
        MachineCode(23) = &H7D
        MachineCode(24) = &H14
        
        MachineCode(25) = &H89   'move dword ptr [edi],edx
        MachineCode(26) = &H17
        
        MachineCode(27) = &H58   'pop ebx    MachineCode(28) = &H59   'pop ecx    MachineCode(29) = &H5A   'pop edx    MachineCode(30) = &H55   'pop edi
        
        MachineCode(31) = &HC9   'leave    MachineCode(32) = &HC2   'ret 16     I tried everything from 0 to 24
        MachineCode(33) = &H10   '           but all produce the stack error
        MachineCode(34) = &H0
        
        'tell cpuid what we want
        EAX = 0
        
        'get address of Machine Code
        VarAddr = VarPtr(MachineCode(0))
        
        'get address of Sub Dummy
        FunctAddr = GetAddress(AddressOf Dummy)
        
        'copy the Machine Code to where it can be called
        CopyMemory ByVal FunctAddr, ByVal VarAddr, 35 '35 bytes machine code
        
        'call it
        On Error Resume Next 'apparently it gets a stack pointer error when in P-Code but i dont know why
          CallWindowProc FunctAddr, EAX, VarPtr(CPUName(1)), VarPtr(CPUName(9)), VarPtr(CPUName(5))
          'Debug.Print Err; Err.Description
          'MsgBox Err & Err.Description
        On Error GoTo 0
        
        GetCpuName = StrConv(CPUName(), vbUnicode) 'UnicodeName
        
    End FunctionPrivate Function GetAddress(Address As Long) As Long    GetAddress = AddressEnd FunctionPrivate Sub Dummy()  'the code below just reserves some space to copy the machine code into
      'it is never executed    x = 0
        x = 1
        x = 2
        x = 3
        x = 4
        x = 5
        x = 6
        x = 7
        x = 8
        x = 9
        x = 10
        x = 0
        x = 1
        x = 2
        x = 3
        x = 4
        x = 5
        x = 6
        x = 7
        x = 8
        x = 9
        x = 10
       
    End Sub
    ------------------------------end--------------------------------------
      

  24.   

    很多CPU没有序列号,如是为了给软件加权限注册码之类的用途,还是用磁盘序列号吧
      

  25.   

    '取得CPU序列号Private Type OSVERSIONINFO
            dwOSVersionInfoSize As Long
            dwMajorVersion As Long
            dwMinorVersion As Long
            dwBuildNumber As Long
            dwPlatformId As Long
            szCSDVersion As String * 128      '  Maintenance string for PSS usage
    End Type
    Private Declare Function GetVersionEx Lib "kernel32" Alias "GetVersionExA" (lpVersionInformation As OSVERSIONINFO) As Long
    Private Declare Function GetComputerName Lib "kernel32" Alias "GetComputerNameA" (ByVal lpBuffer As String, nSize As Long) As Long
    Private Const VER_PLATFORM_WIN32_NT = 2
    Private Const VER_PLATFORM_WIN32_WINDOWS = 1
    Private Const VER_PLATFORM_WIN32s = 0
    Private Sub Command1_Click()
        Dim len5 As Long, aa As Long
        Dim cmprName As String
        Dim osver As OSVERSIONINFO
        '取得Computer Name
        cmprName = String(255, 0)
        len5 = 256
        aa = GetComputerName(cmprName, len5)
        cmprName = Left(cmprName, InStr(1, cmprName, Chr(0)) - 1)
        Computer = cmprName        '取得CPU端口号
        Set CPUs = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & Computer & "\root\cimv2").ExecQuery("select * from Win32_Processor")
        For Each mycpu In CPUs
          Text1.Text = mycpu.ProcessorId
        Next
    End Sub
    0383FBFF0000068A就是我的cpu号码共4X4=16个字符
    窗体上放一个按钮一个text就可以,大家收藏吧,这个程序对保护自己知识产权很有用的!