昨天刚下载了一个想要了很久的PS2光碟ISO文件,但是又没有PS2,听说Cube Media Player可以播放PS2光碟里面的video和audio,就上网顺手找了个1.04.0702版的CubeMedia Player.发现是要注册的,想想自己也N久没有解密了,就来试试手,如有不足,请高手指导.废话不多说了,开始吧.
使用工具:OD,32bit Calulator v1.7,W32DASM,Windows计算器
   CubeMedia Player无壳,用PEid查一下,是Visual C++ 7.0编写的,用OD反汇编.
它有机器码,所以我想它肯定与硬件有关的,一般来说硬盘序列号是很常见的,所以查GetVolumeInfomationA(),来到这里.

0043FA60  /$  51            push ecx
0043FA61  |.  8B4424 08     mov eax,dword ptr ss:[esp+8]
0043FA65  |.  53            push ebx
0043FA66  |.  56            push esi
0043FA67  |.  57            push edi
0043FA68  |.  A3 5C022E01   mov dword ptr ds:[12E025C],eax
0043FA6D  |.  FF15 DC724500 call dword ptr ds:[<&WINMM.timeGetTime>] ;  WINMM.timeGetTime
0043FA73  |.  50            push eax
0043FA74  |.  E8 D8DE0000   call CubeMedi.0044D951
0043FA79  |.  83C4 04       add esp,4
0043FA7C  |.  6A 00         push 0                                   ; /pFileSystemNameSize = NULL
0043FA7E  |.  6A 00         push 0                                   ; |pFileSystemNameBuffer = NULL
0043FA80  |.  8D4C24 1C     lea ecx,dword ptr ss:[esp+1C]            ; |
0043FA84  |.  51            push ecx                                 ; |pFileSystemFlags
0043FA85  |.  8BD1          mov edx,ecx                              ; |
0043FA87  |.  52            push edx                                 ; |pMaxFilenameLength
0043FA88  |.  68 B0B7D802   push CubeMedi.02D8B7B0                   ; |pVolumeSerialNumber = CubeMedi.02D8B7B0
0043FA8D  |.  6A 00         push 0                                   ; |MaxVolumeNameSize = 0
0043FA8F  |.  6A 00         push 0                                   ; |VolumeNameBuffer = NULL
0043FA91  |.  68 E09B4500   push CubeMedi.00459BE0                   ; |RootPathName = "C:\"
0043FA96  |.  FF15 30714500 call dword ptr ds:[<&KERNEL32.GetVolumeI>; \GetVolumeInformationA   得到C盘的序列号
0043FA9C  |.  33C0          xor eax,eax
0043FA9E  |.  A3 68415C02   mov dword ptr ds:[25C4168],eax           ;嗯,开始分配内存空间了
0043FAA3  |.  A3 6C415C02   mov dword ptr ds:[25C416C],eax
0043FAA8  |.  A3 70415C02   mov dword ptr ds:[25C4170],eax
0043FAAD  |.  A2 74415C02   mov byte ptr ds:[25C4174],al
0043FAB2  |.  33C0          xor eax,eax                              ;清理寄存器了
0043FAB4  |.  33DB          xor ebx,ebx
0043FAB6  |.  33C9          xor ecx,ecx
0043FAB8  |.  33D2          xor edx,edx
0043FABA  |.  0FA2          cpuid                                    ;哈哈,CPUID,得到CPU的参数,这是得到CPU的字符串
                                                                     ;AMD的CPU就是AuthenticAMD
                                                                     ;Intel的CPU就是GenuineIntel
0043FABC  |.  891D 68415C02 mov dword ptr ds:[25C4168],ebx           ;CPU字符串放入这些内存空间里面
0043FAC2  |.  8915 6C415C02 mov dword ptr ds:[25C416C],edx
0043FAC8  |.  890D 70415C02 mov dword ptr ds:[25C4170],ecx
0043FACE  |.  8B35 B0B7D802 mov esi,dword ptr ds:[2D8B7B0]           ;C盘序列号
0043FAD4  |.  33C9          xor ecx,ecx
0043FAD6  |.  890D 20598B01 mov dword ptr ds:[18B5920],ecx           ;又来分配内存了
0043FADC  |.  890D 24598B01 mov dword ptr ds:[18B5924],ecx
0043FAE2  |.  890D 28598B01 mov dword ptr ds:[18B5928],ecx
0043FAE8  |.  880D 2C598B01 mov byte ptr ds:[18B592C],cl
0043FAEE  |.  8BFF          mov edi,edi                              ;请教高手:这条是不是冗余指令啊? 当时的EDI是User32.LoadStringA
0043FAF0  |>  0FB681 68415C>/movzx eax,byte ptr ds:[ecx+25C4168]     ;CpuString每一个字符
0043FAF7  |.  33D2          |xor edx,edx
0043FAF9  |.  03C6          |add eax,esi                             ;与C盘序列号相加
0043FAFB  |.  BF 1A000000   |mov edi,1A
0043FB00  |.  F7F7          |div edi;EAX/0x1A
0043FB02  |.  80C2 41       |add dl,41                               ;余数+0x41
0043FB05  |.  8891 20598B01 |mov byte ptr ds:[ecx+18B5920],dl        ;生成机器码
0043FB0B  |.  41            |inc ecx
0043FB0C  |.  83F9 0C       |cmp ecx,0C
0043FB0F  |.^ 7C DF         \jl short CubeMedi.0043FAF0;loop
0043FB11  |.  E8 2AE5FCFF   call CubeMedi.0040E040                   ;关键,注册码生成过程  call进
0043FB16  |.  85C0          test eax,eax
0043FB18  |.  BF 01000000   mov edi,1
0043FB1D      74 0C         je short CubeMedi.0043FB2B
0043FB1F  |.  893D B4B7D802 mov dword ptr ds:[2D8B7B4],edi
0043FB25  |.  893D B8B7D802 mov dword ptr ds:[2D8B7B8],edi


Call进注册码的生成过程后:

0040E040   $  83EC 2C       sub esp,2C
0040E043   .  A1 C4DD4500   mov eax,dword ptr ds:[45DDC4]
0040E048   .  53            push ebx
0040E049   .  56            push esi
0040E04A   .  57            push edi
0040E04B   .  894424 34     mov dword ptr ss:[esp+34],eax
0040E04F   .  33C0          xor eax,eax
0040E051   .  B9 40000000   mov ecx,40
0040E056   .  BF 80E84500   mov edi,CubeMedi.0045E880
0040E05B   .  F3:AB         rep stos dword ptr es:[edi]
0040E05D   .  8D4424 10     lea eax,dword ptr ss:[esp+10]
0040E061   .  50            push eax                                 ; /pHandle
0040E062   .  68 3F000F00   push 0F003F                              ; |Access = KEY_ALL_ACCESS
0040E067   .  6A 00         push 0                                   ; |Reserved = 0
0040E069   .  68 7C754500   push CubeMedi.0045757C                   ; |Subkey = "Software\CubeMediaPlayer"
0040E06E   .  68 01000080   push 80000001                            ; |hKey = HKEY_CURRENT_USER
0040E073   .  C74424 20 040>mov dword ptr ss:[esp+20],4              ; |
0040E07B   .  FF15 10704500 call dword ptr ds:[<&ADVAPI32.RegOpenKey>; \RegOpenKeyExA
0040E081   .  85C0          test eax,eax
0040E083   .  75 4C         jnz short CubeMedi.0040E0D1
0040E08B   .  8D4C24 0C     lea ecx,dword ptr ss:[esp+C]
0040E08F   .  51            push ecx                                 ; /pBufSize
0040E090   .  68 80E84500   push CubeMedi.0045E880                   ; |Buffer = CubeMedi.0045E880
0040E095   .  8D5424 1C     lea edx,dword ptr ss:[esp+1C]            ; |
0040E099   .  52            push edx                                 ; |pvalueType
0040E09A   .  50            push eax                                 ; |Reserved
0040E09B   .  8B4424 20     mov eax,dword ptr ss:[esp+20]            ; |
0040E09F   .  68 70754500   push CubeMedi.00457570                   ; |valueName = "User Name" //读注册表里面的用户名
0040E0A4   .  BF 00010000   mov edi,100                              ; |
0040E0A9   .  50            push eax                                 ; |hKey
0040E0AA   .  897C24 24     mov dword ptr ss:[esp+24],edi            ; |
0040E0AE   .  FFD6          call esi                                 ; \RegQueryvalueExA
0040E0B0   .  8B4424 10     mov eax,dword ptr ss:[esp+10]
0040E0B4   .  8D4C24 0C     lea ecx,dword ptr ss:[esp+C]
0040E0B8   .  51            push ecx                                 ; /pBufSize
0040E0B9   .  68 68BB9001   push CubeMedi.0190BB68                   ; |Buffer = CubeMedi.0190BB68
0040E0BE   .  8D5424 1C     lea edx,dword ptr ss:[esp+1C]            ; |
0040E0C2   .  52            push edx                                 ; |pvalueType
0040E0C3   .  6A 00         push 0                                   ; |Reserved = NULL
0040E0C5   .  68 60754500   push CubeMedi.00457560                   ; |valueName = "Register Code" //读注册表里面的注册码
0040E0CA   .  50            push eax                                 ; |hKey
0040E0CB   .  897C24 24     mov dword ptr ss:[esp+24],edi            ; |
0040E0CF   .  FFD6          call esi                                 ; \RegQueryvalueExA
0040E0D1   >  33C9          xor ecx,ecx
0040E0D3   .  894C24 18     mov dword ptr ss:[esp+18],ecx            ;开始分配内存空间,可能是像C++的new()操作符
0040E0D7   .  894C24 1C     mov dword ptr ss:[esp+1C],ecx
0040E0DB   .  894C24 20     mov dword ptr ss:[esp+20],ecx
0040E0DF   .  894C24 24     mov dword ptr ss:[esp+24],ecx
0040E0E3   .  894C24 28     mov dword ptr ss:[esp+28],ecx
0040E0E7   .  894C24 2C     mov dword ptr ss:[esp+2C],ecx
0040E0EB   .  B8 80E84500   mov eax,CubeMedi.0045E880                ;  ASCII "Pr0Zel"
0040E0F0   .  33F6          xor esi,esi
0040E0F2   .  884C24 30     mov byte ptr ss:[esp+30],cl
0040E0F6   .  33D2          xor edx,edx
0040E0F8   .  8D78 01       lea edi,dword ptr ds:[eax+1]
0040E0FB   .  EB 03         jmp short CubeMedi.0040E100
0040E0FD      8D49 00       lea ecx,dword ptr ds:[ecx]
0040E100   >  8A08          mov cl,byte ptr ds:[eax]
0040E102   .  40            inc eax                                 ;计算Username的ASCII码个数
0040E103   .  84C9          test cl,cl
0040E105   .^ 75 F9         jnz short CubeMedi.0040E100
0040E107   .  2BC7          sub eax,edi                             ;ASCII码个数放入EAX,这里EAX永远为0 是mov eax,edi的变形
0040E109   .  894424 14     mov dword ptr ss:[esp+14],eax
0040E10D   .  74 20         je short CubeMedi.0040E12F
0040E10F   .  90            nop
0040E110   >  0FBE82 80E845>movsx eax,byte ptr ds:[edx+45E880]
0040E117   .  03F0          add esi,eax                             ;esi是ascii码累加值
0040E119   .  B8 80E84500   mov eax,CubeMedi.0045E880               ;  ASCII "Pr0Zel"
0040E11E   .  42            inc edx
0040E11F   .  8D78 01       lea edi,dword ptr ds:[eax+1]
0040E122   >  8A08          mov cl,byte ptr ds:[eax]
0040E124   .  40            inc eax
0040E125   .  84C9          test cl,cl
0040E127   .^ 75 F9         jnz short CubeMedi.0040E122
0040E129   .  2BC7          sub eax,edi
0040E12B   .  3BD0          cmp edx,eax
0040E12D   .^ 72 E1         jb short CubeMedi.0040E110
0040E12F   >  33C9          xor ecx,ecx
0040E131   >  0FB681 20598B>movzx eax,byte ptr ds:[ecx+18B5920]     ;第1位机器码
0040E138   .  0FB6B9 21598B>movzx edi,byte ptr ds:[ecx+18B5921]     ;第2位机器码
0040E13F   .  0FAFC6        imul eax,esi                            ;第1位机器码*0x1AA
0040E142   .  03C7          add eax,edi                             ;再加上第2位机器码
0040E144   .  33D2          xor edx,edx
0040E146   .  BB 1A000000   mov ebx,1A
0040E14B   .  F7F3          div ebx                                 ;eax为商,edx为余数 Eax/EBX  /1A
0040E14D   .  0FB699 22598B>movzx ebx,byte ptr ds:[ecx+18B5922]     ;第3位机器码
0040E154   .  8BC7          mov eax,edi                             ;edi->第2位的机器码
0040E156   .  0FAFC6        imul eax,esi                             ;第2位机器码*0x1AA
0040E159   .  03C3          add eax,ebx                             ;ebx->第3位机器码
0040E15B   .  BF 1A000000   mov edi,1A
0040E160   .  83C1 06       add ecx,6                               ;ECX+6
0040E163   .  80C2 41       add dl,41                               ;dl->40e14b的余数
0040E166   .  88540C 12     mov byte ptr ss:[esp+ecx+12],dl         ;dl+0x41放入内存里
0040E16A   .  33D2          xor edx,edx
0040E16C   .  F7F7          div edi                                 ;eax/edi  商:eax, 余数:edx  /1A
0040E16E   .  0FB6B9 1D598B>movzx edi,byte ptr ds:[ecx+18B591D]     ;第4位机器码
0040E175   .  8BC3          mov eax,ebx                               ;ebx->第3位机器码
0040E177   .  0FAFC6        imul eax,esi                            ;ESI=0
0040E17A   .  03C7          add eax,edi                             ;第4位机器码+EAX
0040E17C   .  BB 1A000000   mov ebx,1A
0040E181   .  80C2 41       add dl,41                               ;dl->40e16c的余数
0040E184   .  88540C 13     mov byte ptr ss:[esp+ecx+13],dl
0040E188   .  33D2          xor edx,edx
0040E18A   .  F7F3          div ebx
0040E18C   .  0FB699 1E598B>movzx ebx,byte ptr ds:[ecx+18B591E]
0040E193   .  8BC7          mov eax,edi
0040E195   .  0FAFC6        imul eax,esi
0040E198   .  03C3          add eax,ebx
0040E19A   .  BF 1A000000   mov edi,1A
0040E19F   .  80C2 41       add dl,41
0040E1A2   .  88540C 14     mov byte ptr ss:[esp+ecx+14],dl
0040E1A6   .  33D2          xor edx,edx
0040E1A8   .  F7F7          div edi
0040E1AA   .  0FB6B9 1F598B>movzx edi,byte ptr ds:[ecx+18B591F]
0040E1B1   .  8BC3          mov eax,ebx
0040E1B3   .  0FAFC6        imul eax,esi
0040E1B6   .  03C7          add eax,edi
0040E1B8   .  BB 1A000000   mov ebx,1A
0040E1BD   .  80C2 41       add dl,41
0040E1C0   .  88540C 15     mov byte ptr ss:[esp+ecx+15],dl
0040E1C4   .  33D2          xor edx,edx
0040E1C6   .  F7F3          div ebx
0040E1C8   .  8BC7          mov eax,edi
0040E1CA   .  0FAFC6        imul eax,esi
0040E1CD   .  8BFB          mov edi,ebx
0040E1CF   .  80C2 41       add dl,41
0040E1D2   .  88540C 16     mov byte ptr ss:[esp+ecx+16],dl
0040E1D6   .  0FB691 20598B>movzx edx,byte ptr ds:[ecx+18B5920]
0040E1DD   .  03C2          add eax,edx
0040E1DF   .  33D2          xor edx,edx
0040E1E1   .  F7F7          div edi
0040E1E3   .  80C2 41       add dl,41
0040E1E6   .  83F9 0C       cmp ecx,0C
0040E1E9   .  88540C 17     mov byte ptr ss:[esp+ecx+17],dl
0040E1ED   .^ 0F8C 3EFFFFFF jl CubeMedi.0040E131                    //loop
0040E1F3   .  46            inc esi                                 ;ESI+1  //ESI是Username的ASCII码累加值
0040E1F4   .  33C9          xor ecx,ecx
0040E1F6   .  BF 0C000000   mov edi,0C                              ;作下面循环的计数器,循环0xC次,即12次
0040E1FB   .  EB 03         jmp short CubeMedi.0040E200
0040E1FD      8D49 00       lea ecx,dword ptr ds:[ecx]
0040E200   >  0FB681 20598B>movzx eax,byte ptr ds:[ecx+18B5920]     ;第1位机器码
0040E207   .  0FAFC6        imul eax,esi                            ;第1位机器码*ESI
0040E20A   .  33D2          xor edx,edx
0040E20C   .  BB 1A000000   mov ebx,1A
0040E211   .  F7F3          div ebx                                 ;又是取余
0040E213   .  80C2 41       add dl,41                               ;取余后+0x41
0040E216   .  88540C 24     mov byte ptr ss:[esp+ecx+24],dl         ;加在以前面生成的注册码后
0040E21A   .  41            inc ecx
0040E21B   .  4F            dec edi                                 ;计数器-1
0040E21C   .^ 75 E2         jnz short CubeMedi.0040E200
0040E21E   .  5F            pop edi
0040E21F   .  5E            pop esi
0040E220   .  33C0          xor eax,eax
0040E222   .  5B            pop ebx
0040E223   .  EB 0B         jmp short CubeMedi.0040E230
0040E225   .  8DA424 000000>lea esp,dword ptr ss:[esp]
0040E22C   .  8D6424 00     lea esp,dword ptr ss:[esp]
0040E230   >  0FBE88 68BB90>movsx ecx,byte ptr ds:[eax+190BB68]
0040E237   .  0FB65404 0C   movzx edx,byte ptr ss:[esp+eax+C]
0040E23C   .  3BD1          cmp edx,ecx
0040E23E   .  75 18         jnz short CubeMedi.0040E258
0040E240   .  40            inc eax
0040E241   .  83F8 19       cmp eax,19
0040E244   .^ 7C EA         jl short CubeMedi.0040E230
0040E246   .  B8 01000000   mov eax,1
0040E24B   .  8B4C24 28     mov ecx,dword ptr ss:[esp+28]
0040E24F   .  E8 9EF20300   call CubeMedi.0044D4F2
0040E254   .  83C4 2C       add esp,2C
0040E257   .  C3            retn
0040E258   >  8B4C24 28     mov ecx,dword ptr ss:[esp+28]
0040E25C   .  33C0          xor eax,eax
0040E25E   .  E8 8FF20300   call CubeMedi.0044D4F2
0040E263   .  83C4 2C       add esp,2C
0040E266   .  C3            retn

现在明白了,它的序列号是这样算成的:
前12位的注册码是: (( (机器码(N)*用户名ASCII码累加值)+机器码(N+1))%0x1A)
后12位的注册码是: ((机器码(N)*(用户名ASCII码累加值+1))%0x1A+0x41)
而它的机器码的生成方式则是:
(硬盘序列号+CPU字符串(N))%0x1A+0x41 //N是0-11

明白了算法后,开始写注册机:

CString CKeyGun::MakeMachineCode() //Make MachineCode
{
CString MachineCode;
DWORD Disk_Vol;
char CPUStr[12];
int i;
GetVolumeInformation("C:\\",NULL,12,&Disk_Vol,NULL,NULL,NULL,10);

_asm{
mov eax,0
cpuid
mov DWORD ptr CPUStr   , ebx
mov DWORD ptr CPUStr+4 , edx
mov DWORD ptr CPUStr+8 , ecx
}
for(i=0;i<12;i++)
{
MachineCode+=char((Disk_Vol+int(CPUStr[i]))%0x1A+0x41);
}
return MachineCode;
}

CString CKeyGun::MakeKey(CString MaCode,CString Username) //Make Reg key
{
int i,Usr;
Usr=0;
for(i=0;i<Username.GetLength();i++)
{
Usr+=int(Username.GetAt(i));
}
CString Key;
for(i=0;i<11;i++)
{
Key+=char(((MaCode.GetAt(i)*Usr)+MaCode.GetAt(i+1))%0x1A+0x41);
}
Key+=char((MaCode.GetAt(i)*Usr)%0x1A+0x41);
for(i=0;i<12;i++)
{
Key+=char((MaCode.GetAt(i)*(Usr+1))%0x1A+0x41);
}
return Key;
}

  • 标 题: 答复
  • 作 者:Pr0Zel
  • 时 间:2005-03-02 00:19

注释一下,在注册机的代码中出现的这一行代码:
Key+=char((MaCode.GetAt(i)*Usr)%0x1A+0x41);
原因是那时i已经到了12了,所以MaCode.GetAt(i+1)已经是越出了字符串了,所以不能放在for()语句里面