• 标 题:豪杰大眼睛(II)注册码分析(算法与XXXX3000英雄版基本一样,哈哈) (15千字)
  • 作 者:hoto
  • 时 间:2003-1-25 12:53:25
  • 链 接:http://bbs.pediy.com

这几天比较无聊,找了个豪杰大眼睛II,发现它的注册的算法基本与豪杰II3000英雄版的算法很相似,第一组的注册码是一样的,从第二组开始的变化稍有不同,以下是它的算法的分析过程。

* Reference To: USER32.GetWindowTextA, Ord:015Eh
                                  |
:00401CCA 8B35F8604000            mov esi, dword ptr [004060F8]
:00401CD0 8D442404                lea eax, dword ptr [esp+04]
:00401CD4 6A08                    push 00000008
:00401CD6 50                      push eax
:00401CD7 51                      push ecx
:00401CD8 FFD6                    call esi
:00401CDA A128984000              mov eax, dword ptr [00409828]
:00401CDF 8D542409                lea edx, dword ptr [esp+09]
:00401CE3 6A08                    push 00000008
:00401CE5 52                      push edx
:00401CE6 50                      push eax
:00401CE7 FFD6                    call esi
:00401CE9 8B1534984000            mov edx, dword ptr [00409834]
:00401CEF 8D4C240E                lea ecx, dword ptr [esp+0E]
:00401CF3 6A08                    push 00000008
:00401CF5 51                      push ecx
:00401CF6 52                      push edx
:00401CF7 FFD6                    call esi
:00401CF9 8B0D30984000            mov ecx, dword ptr [00409830]
:00401CFF 8D442413                lea eax, dword ptr [esp+13]
:00401D03 6A08                    push 00000008
:00401D05 50                      push eax
:00401D06 51                      push ecx
:00401D07 FFD6                    call esi
:00401D09 8B1524984000            mov edx, dword ptr [00409824]
:00401D0F 6800010000              push 00000100
:00401D14 B02D                    mov al, 2D
:00401D16 6860994000              push 00409960
:00401D1B 52                      push edx
:00401D1C 8844241E                mov byte ptr [esp+1E], al
:00401D20 88442419                mov byte ptr [esp+19], al
:00401D24 88442414                mov byte ptr [esp+14], al
:00401D28 C644242300              mov [esp+23], 00
:00401D2D FFD6                    call esi
:00401D2F 8D442404                lea eax, dword ptr [esp+04]
:00401D33 50                      push eax
:00401D34 6860994000              push 00409960 <----经过动态跟踪,发现409960处存放的是输入的用户名
:00401D39 E842090000              call 00402680 <----进行注册码比较的关键CALL,要用F8跟入
:00401D3E F7D8                    neg eax <---- 如果返回值为0,则注册失败
:00401D40 1BC0                    sbb eax, eax
:00401D42 8D4C2404                lea ecx, dword ptr [esp+04]
:00401D46 F7D8                    neg eax
:00401D48 51                      push ecx
:00401D49 6860994000              push 00409960
:00401D4E A3689A4000              mov dword ptr [00409A68], eax<----将EAX的值写入[409A68]
:00401D53 E838000000              call 00401D90 <----此CALL将用户名与注册码写入注册表
:00401D58 8B442450                mov eax, dword ptr [esp+50]
:00401D5C 8B0D44994000            mov ecx, dword ptr [00409944]
:00401D62 83C408                  add esp, 00000008
:00401D65 8D542404                lea edx, dword ptr [esp+04]
:00401D69 52                      push edx
:00401D6A 68201C4000              push 00401C20
:00401D6F 50                      push eax

* Possible Reference to Dialog: DialogID_0069
                                  |
:00401D70 6A69                    push 00000069
:00401D72 51                      push ecx

* Reference To: USER32.DialogBoxParamA, Ord:0093h
                                  |
:00401D73 FF15E8604000            Call dword ptr [004060E8]<----如果[409A68]为0,显示注册失败,为1时显示注册成功
:00401D79 A1689A4000              mov eax, dword ptr [00409A68]
:00401D7E 5E                      pop esi
:00401D7F 83C440                  add esp, 00000040
:00401D82 C3                      ret


---------------------按F8进入注册码比较的关键CALL----------------------
:00402680 83EC20                  sub esp, 00000020
:00402683 56                      push esi
:00402684 57                      push edi
:00402685 B908000000              mov ecx, 00000008
:0040268A 33C0                    xor eax, eax
:0040268C 8D7C2408                lea edi, dword ptr [esp+08]<----存放第一组注册码的地址,以下记为reg1
:00402690 F3                      repz
:00402691 AB                      stosd
:00402692 8B44242C                mov eax, dword ptr [esp+2C]
:00402696 50                      push eax<----将用户名作为参数,压栈。
:00402697 E8A4010000              call 00402840 <----此CALL将用户名进入变换后,变为一个DWORD类型,从EAX中返回,它内部的算法与XXXX3000英雄版完全相同,这里不再详细说明,可以参考XXXX3000英雄版的分析
:0040269C 83C404                  add esp, 00000004
:0040269F 89442408                mov dword ptr [esp+08], eax 将返回值存入reg1
:004026A3 33F6                    xor esi, esi

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004026C8(C)
|
:004026A5 0FBE443408              movsx eax, byte ptr [esp+esi+08] 取出reg1中的一个字节。(共4字节)
:004026AA 83F841                  cmp eax, 00000041
:004026AD 7C08                    jl 004026B7
:004026AF 83F85A                  cmp eax, 0000005A
:004026B2 7F03                    jg 004026B7
:004026B4 83C020                  add eax, 00000020 <----这里是将大写的变为小写

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:004026AD(C), :004026B2(C)
|
:004026B7 50                      push eax
:004026B8 E853020000              call 00402910 <----此CALL将取出的值转换为一个字符。
:004026BD 83C404                  add esp, 00000004
:004026C0 88443408                mov byte ptr [esp+esi+08], al <----将变换后的值再存入。
:004026C4 46                      inc esi
:004026C5 83FE04                  cmp esi, 00000004 <---四个字节是否处理完
:004026C8 7CDB                    jl 004026A5
:004026CA 8B7C2430                mov edi, dword ptr [esp+30]
:004026CE 8D4C2408                lea ecx, dword ptr [esp+08]
:004026D2 8BF7                    mov esi, edi
:004026D4 33D2                    xor edx, edx
:004026D6 2BF1                    sub esi, ecx

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004026FC(C)
|
:004026D8 8D4C1408                lea ecx, dword ptr [esp+edx+08]
:004026DC 0FBE040E                movsx eax, byte ptr [esi+ecx]<----取出我们输入的第一组注册码的1个字节。
:004026E0 83F841                  cmp eax, 00000041
:004026E3 7C08                    jl 004026ED
:004026E5 83F85A                  cmp eax, 0000005A
:004026E8 7F03                    jg 004026ED
:004026EA 83C020                  add eax, 00000020  <----如果是大写则转为小写

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:004026E3(C), :004026E8(C)
|
:004026ED 0FBE09                  movsx ecx, byte ptr [ecx]<----取出真正注册码的1位
:004026F0 3BC1                    cmp eax, ecx <----比较
:004026F2 0F8514010000            jne 0040280C
:004026F8 42                      inc edx
:004026F9 83FA04                  cmp edx, 00000004 <----第一组注册码共4位是否比较完毕。
:004026FC 7CDA                    jl 004026D8
:004026FE 8B442408                mov eax, dword ptr [esp+08]
:00402702 8D5008                  lea edx, dword ptr [eax+08] 将reg1的值加上8后,作为第2组注册码
:00402705 0FAFD0                  imul edx, eax
:00402708 8954240C                mov dword ptr [esp+0C], edx<----此地址记为reg2 = (reg1+8)*reg1
:0040270C 33F6                    xor esi, esi

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0040272F(C)
|
:0040270E 8A44340C                mov al, byte ptr [esp+esi+0C]<----取出第2组中的一个字节
:00402712 50                      push eax
:00402713 56                      push esi
:00402714 E807010000              call 00402820<----先进行一次变换
:00402719 25FF000000              and eax, 000000FF
:0040271E 50                      push eax
:0040271F E8EC010000              call 00402910 <----将变换后的值再转变为字符形式
:00402724 83C40C                  add esp, 0000000C
:00402727 8844340C                mov byte ptr [esp+esi+0C], al
:0040272B 46                      inc esi
:0040272C 83FE04                  cmp esi, 00000004 <----是否处理完4个字符
:0040272F 7CDD                    jl 0040270E
:00402731 33C9                    xor ecx, ecx

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00402756(C)
|
:00402733 0FBE440F05              movsx eax, byte ptr [edi+ecx+05]<----这里开始取出第2组进行比较
:00402738 83F841                  cmp eax, 00000041
:0040273B 7C08                    jl 00402745
:0040273D 83F85A                  cmp eax, 0000005A
:00402740 7F03                    jg 00402745
:00402742 83C020                  add eax, 00000020

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:0040273B(C), :00402740(C)
|
:00402745 0FBE540C0C              movsx edx, byte ptr [esp+ecx+0C]
:0040274A 3BC2                    cmp eax, edx<----比较注册码
:0040274C 0F85BA000000            jne 0040280C
:00402752 41                      inc ecx
:00402753 83F904                  cmp ecx, 00000004
:00402756 7CDB                    jl 00402733
:00402758 8B44240C                mov eax, dword ptr [esp+0C]
:0040275C 8B4C2408                mov ecx, dword ptr [esp+08]
:00402760 8BD0                    mov edx, eax
:00402762 33D1                    xor edx, ecx
:00402764 42                      inc edx
:00402765 0FAFD1                  imul edx, ecx
:00402768 03D0                    add edx, eax
:0040276A 33F6                    xor esi, esi
:0040276C 89542410                mov dword ptr [esp+10], edx<----第三组注册码 reg3 = reg2 +((reg1 ^ reg2)+1)*reg1

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00402786(C)
|
:00402770 0FBE443410              movsx eax, byte ptr [esp+esi+10]
:00402775 50                      push eax
:00402776 E895010000              call 00402910<----将第三组转变为字符形式的注册码
:0040277B 83C404                  add esp, 00000004
:0040277E 88443410                mov byte ptr [esp+esi+10], al
:00402782 46                      inc esi
:00402783 83FE04                  cmp esi, 00000004<---4个字节是否都完成了
:00402786 7CE8                    jl 00402770
:00402788 33C9                    xor ecx, ecx

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004027A9(C)
|
:0040278A 0FBE440F0A              movsx eax, byte ptr [edi+ecx+0A]<----这里开始比较第3组注册码
:0040278F 83F841                  cmp eax, 00000041
:00402792 7C08                    jl 0040279C
:00402794 83F85A                  cmp eax, 0000005A
:00402797 7F03                    jg 0040279C
:00402799 83C020                  add eax, 00000020

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:00402792(C), :00402797(C)
|
:0040279C 0FBE540C10              movsx edx, byte ptr [esp+ecx+10]
:004027A1 3BC2                    cmp eax, edx<----比较注册码
:004027A3 7567                    jne 0040280C
:004027A5 41                      inc ecx
:004027A6 83F904                  cmp ecx, 00000004
:004027A9 7CDF                    jl 0040278A
:004027AB 8B4C240C                mov ecx, dword ptr [esp+0C]
:004027AF 8B442408                mov eax, dword ptr [esp+08]
:004027B3 0FAFC8                  imul ecx, eax
:004027B6 41                      inc ecx
:004027B7 0FAF4C2410              imul ecx, dword ptr [esp+10]
:004027BC 03C8                    add ecx, eax
:004027BE 33F6                    xor esi, esi
:004027C0 894C2414                mov dword ptr [esp+14], ecx<----第四组注册码reg4 = reg1 +((reg2 * reg1)+1)*reg3

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004027DA(C)
|
:004027C4 0FBE543414              movsx edx, byte ptr [esp+esi+14]
:004027C9 52                      push edx
:004027CA E841010000              call 00402910<----将第4组转变化字符形式的注册码
:004027CF 83C404                  add esp, 00000004
:004027D2 88443414                mov byte ptr [esp+esi+14], al
:004027D6 46                      inc esi
:004027D7 83FE04                  cmp esi, 00000004
:004027DA 7CE8                    jl 004027C4
:004027DC 33C9                    xor ecx, ecx

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004027FD(C)
|
:004027DE 0FBE440F0F              movsx eax, byte ptr [edi+ecx+0F]<----这里开始比较第4组注册码
:004027E3 83F841                  cmp eax, 00000041
:004027E6 7C08                    jl 004027F0
:004027E8 83F85A                  cmp eax, 0000005A
:004027EB 7F03                    jg 004027F0
:004027ED 83C020                  add eax, 00000020

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:004027E6(C), :004027EB(C)
|
:004027F0 0FBE540C14              movsx edx, byte ptr [esp+ecx+14]
:004027F5 3BC2                    cmp eax, edx<----比较注册码
:004027F7 7513                    jne 0040280C
:004027F9 41                      inc ecx
:004027FA 83F904                  cmp ecx, 00000004
:004027FD 7CDF                    jl 004027DE
:004027FF 5F                      pop edi

* Possible Reference to String Resource ID=00001: "Register Success"
                                  |
:00402800 B801000000              mov eax, 00000001
:00402805 5E                      pop esi
:00402806 83C420                  add esp, 00000020
:00402809 C20800                  ret 0008




----------------此CALL是将EAX的值转化为一个字符形式--------------
* Referenced by a CALL at Addresses:
|:004026B8  , :0040271F  , :00402776  , :004027CA 
|
:00402910 8B442404                mov eax, dword ptr [esp+04]

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:00402932(U), :00402943(U), :0040295E(U)
|
:00402914 83E07F                  and eax, 0000007F<---取低7位的值
:00402917 83F841                  cmp eax, 00000041
:0040291A 7C07                    jl 00402923
:0040291C 83F85A                  cmp eax, 0000005A
:0040291F 7F02                    jg 00402923
:00402921 0C20                    or al, 20<----如果是大写字母,则转为小写

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:0040291A(C), :0040291F(C)
|
:00402923 83F86F                  cmp eax, 0000006F<----如果是字母'o',不要它
:00402926 750C                    jne 00402934
:00402928 B890000000              mov eax, 00000090
:0040292D 83F00E                  xor eax, 0000000E
:00402930 0C31                    or al, 31
:00402932 EBE0                    jmp 00402914

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00402926(C)
|
:00402934 83F830                  cmp eax, 00000030<----如果是字母'0',也不要它
:00402937 750C                    jne 00402945
:00402939 B8CF000000              mov eax, 000000CF
:0040293E 83F00E                  xor eax, 0000000E
:00402941 0C31                    or al, 31
:00402943 EBCF                    jmp 00402914

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00402937(C)
|
:00402945 83F861                  cmp eax, 00000061 <----如果已经是小写字母了,则返回
:00402948 7C05                    jl 0040294F
:0040294A 83F87A                  cmp eax, 0000007A
:0040294D 7E11                    jle 00402960

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00402948(C)
|
:0040294F 83F831                  cmp eax, 00000031<---如果已经是数学了,则返回
:00402952 7C05                    jl 00402959
:00402954 83F839                  cmp eax, 00000039
:00402957 7E07                    jle 00402960

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00402952(C)
|
:00402959 83F00E                  xor eax, 0000000E<----继续变化
:0040295C 0C31                    or al, 31
:0040295E EBB4                    jmp 00402914

-----------------------------------------------------------
注册机的代码与XXXX3000英雄版基本相同,只需要修改以下几处即可:
reg2 = (reg1+8)*reg1
reg3 = reg2 +((reg1 ^ reg2)+1)*reg1
reg4 = reg1 +((reg2 * reg1)+1)*reg3