B-Puzzle拼图游戏算法分析(2)

B-Puzzle拼图游戏算法分析(2)

2004/10/15 0:55:00来源:本站整理作者:蓝点我要评论(0)
B-Puzzle拼图游戏算法分析(2)
进入关键CALL,我们来到:
:004027C4 55                      push ebp
:004027C5 8BEC                    mov ebp, esp
:004027C7 83C4F8                  add esp, FFFFFFF8
:004027CA 53                      push ebx
:004027CB 56                      push esi
:004027CC 57                      push edi
:004027CD FF7508                  push [ebp+08]
:004027D0 E83F190500              call 00454114
:004027D5 59                      pop ecx
:004027D6 83F808                  cmp eax, 00000008
:004027D9 7710                    ja 004027EB

* Possible StringData Ref from Data Obj ->"        "
                                 |
:004027DB 68E7254600              push 004625E7
:004027E0 FF7508                  push [ebp+08]
:004027E3 E820180500              call 00454008
:004027E8 83C408                  add esp, 00000008

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004027D9(C)
|
:004027EB 33FF                    xor edi, edi
:004027ED 33F6                    xor esi, esi
:004027EF 8B450C                  mov eax, dword ptr [ebp+0C]
:004027F2 8D1C38                  lea ebx, dword ptr [eax+edi]
:004027F5 8B4508                  mov eax, dword ptr [ebp+08]
:004027F8 8BD0                    mov edx, eax
:004027FA 8955F8                  mov dword ptr [ebp-08], edx==》用户名移到ebp-08

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00402854(C)
SN1算法开始的地方:
也许你要问如何判断算法的开始,其实我的判断的依据就是:
1.它的注册码是动态的,也就是根据用户名的不同而变的。
2.所以,跟踪算法的时候,时刻注意各个寄存器中是否出现了你的用户名的16进制,和循环
3.看看在算法CALL中,哪里是出现真SN,它们进行反推,向上走。
4.一般,算法都会出现在关键CALL的最后。
:004027FD FF3590234600            push dword ptr [00462390]
:00402803 E80C190500              call 00454114
:00402808 59                      pop ecx
:00402809 50                      push eax
:0040280A 8BC6                    mov eax, esi
:0040280C 5A                      pop edx
:0040280D 8BCA                    mov ecx, edx
:0040280F 33D2                    xor edx, edx
:00402811 F7F1                    div ecx
:00402813 A190234600              mov eax, dword ptr [00462390]==》00462390值移到EAX,00462390为"PUZZLEVERO"
:00402818 8A0410                  mov al, byte ptr [eax+edx]==》取EAX第一位到AL
:0040281B 8B55F8                  mov edx, dword ptr [ebp-08]==》取用户名第一位移到EDX
:0040281E 3202                    xor al, byte ptr [edx]==》AL与EAX的值取异或,结果在AL
:00402820 0FBEC0                  movsx eax, al==》16位寄存器扩展,目的是为了与32位寄存器间数据传送,异或后的值传入EDX
:00402823 6A0A                    push 0000000A
:00402825 8D55FC                  lea edx, dword ptr [ebp-04]==》EDX的值送入ebp-04
:00402828 52                      push edx
:00402829 50                      push eax
:0040282A E8F1940500              call 0045BD20==》寻其对应的DEC(十进制值)数值
:0040282F 83C40C                  add esp, 0000000C
:00402832 807DFD00                cmp byte ptr [ebp-03], 00==》比较ebp-03的值是否为零
:00402836 7504                    jne 0040283C==》不等就跳
:00402838 B131                    mov cl, 31
:0040283A EB03                    jmp 0040283F
(说明:我第一次得到的ESP-04的值是40,那么ESP-03=ESP-04+01的值就是0,明白了吗?)
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00402836(C)
|
:0040283C 8A4DFD                  mov cl, byte ptr [ebp-03]==》把ebp-03的值移到CL中

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0040283A(U)
|
:0040283F 880B                    mov byte ptr [ebx], cl再由CL传入EBX
:00402841 43                      inc ebx==》EBX加一
:00402842 8A45FC                  mov al, byte ptr [ebp-04]==》算好的值(40)的第一位又送到AL
:00402845 47                      inc edi
:00402846 47                      inc edi==》EDI连续加1,2次
:00402847 8803                    mov byte ptr [ebx], al==》AL的值再送入加一后的EBX容器,那么她的值就,以我为例变为04
所以,00402832~00402847的作用就是把用户名第一位与定值“PUZZLEVERO"的第一位"P"取异或后的值,取前两位,并且进行位置互换。
:00402849 43                      inc ebx==》EBX又加一
:0040284A 83C602                  add esi, 00000002
:0040284D 8345F802                add dword ptr [ebp-08], 00000002==》EBP-08地址加2,即:用户名跳过一位,比如,我的用户名xx-fish第一次经过这一步之后变成-fish,明白吗?
:00402851 83FE08                  cmp esi, 00000008==》比较ESI是否为8,来判断是否循环,也就是说这SN1的计算只有4次循环。
:00402854 7CA7                    jl 004027FD==》小于则转移,继续循环。
:00402856 8B550C                  mov edx, dword ptr [ebp+0C]
:00402859 C6043A00                mov byte ptr [edx+edi], 00
:0040285D FF750C                  push [ebp+0C]
:00402860 E887920500              call 0045BAEC==》获取SN1的值到EAX是十六进制哦
:00402865 59                      pop ecx
:00402866 8BF8                    mov edi, eax==》sn1移到EDI,下面SN2的计算会用到
:00402868 33DB                    xor ebx, ebx==》清零
:0040286A 8B4508                  mov eax, dword ptr [ebp+08]
:0040286D 8BF0                    mov esi, eax                 ==》用户名转到esi寄存器
:0040286F EB09                    jmp 0040287A

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
==》SN2算法真正的开始了
|:00402885(C)
|
:00402871 0FBE06                  movsx eax, byte ptr [esi]==》ESI是你的用户名,依次取你的用户名
:00402874 F7EB                    imul ebx==》EAX与EBX相乘,(EBX起始值为0,是技术器)
:00402876 03F8                    add edi, eax==》EAX与EDI固定值相加,存取EDI
:00402878 43                      inc ebx==》计数器EBX加一
:00402879 46                      inc esi==》ESI加一,取用于取用户名第二位

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0040286F(U)
|
:0040287A FF7508                  push [ebp+08]
:0040287D E892180500              call 00454114==》EAX赋值F(循环次数)
:00402882 59                      pop ecx
:00402883 3BD8                    cmp ebx, eax==》比较循环是否该结束
:00402885 7CEA                    jl 00402871==》不等就跳
:00402887 6A0A                    push 0000000A
:00402889 FF750C                  push [ebp+0C]             循环结束后,EDI的值,就是注册码的16
:0040288C 57                      push edi                  进制。
:0040288D E8B2AB0500              call 0045D444  
:00402892 83C40C                  add esp, 0000000C
:00402895 8B450C                  mov eax, dword ptr [ebp+0C]
:00402898 5F                      pop edi
:00402899 5E                      pop esi
:0040289A 5B                      pop ebx
:0040289B 59                      pop ecx
:0040289C 59                      pop ecx
:0040289D 5D                      pop ebp
:0040289E C3                      ret

注册码算法总结:
算法分两段:
1.SN1的计算是,用户名的1,3,5,7位与“PUZZLEVERO"的1,3,5,7位取异或。结果取前两位,并且位置互换。用户名位数不够用空格20代替。这个值作为下一段SN2的计算的基数。
2.用户名的第一位与计数器EBX(其实值为0)相乘,再与SN1相加,作为新的基数,如此循环16次,用户名位数不够用空格代替。


以我的用户名xx-fish为例(&符号后面代表的是所表示的进制):
sn1
1.x xor P=40&D 取前两位40再变成04
3.- xor Z=119&D 取前两位11再变成11
5.i xor L=37&D取前两位37再变成73
7.h xor V=62&D取前两位62再变成26
所以SN1就是04117326,再转换成16进制就是3ED34E&H

sn2
x imul 0=0,0 ADD SN1=3ED34E&H
x imul 1=78&H,78&H ADD 3ED34E&H=3ED3C6&H
- IMUL 2=5A&H,5A&H ADD 3ED3C6&H=3ED420&H
f IMUL 3=132&H,132&H ADD 3ED420&H=3ED552&H
i IMUL 4=1A4&H,1A4&H ADD 3ED552&H=3ED6F6&H
s IMUL 5=23f&H,23F&H ADD 3ED6F6&H=3ED935&H
h IMUL 6=270&H,270&H ADD 3ED935&H=3EDBA5&H
空格 IMUL 7=E0&H,E0H ADD 3EDBA5&H=3EDC85&H
空格 IMUL 8=100&H,100H ADD 3EDC85&H=3EDD85&H


    
    
     
    
    

阅读本文后您有什么感想? 已有 人给出评价!

  • 0 囧
      囧
  • 0 恶心
      恶心
  • 0 期待
      期待
  • 0
      难过
  • 0 不错
      不错
  • 0 关注
      关注
  • 最新评论
  • 热门评论
共有评论(0)条 查看全部评论
高兴 可 汗 我不要 害羞 好 下下下 送花 屎 亲亲

注:您的评论需要经过审核才会显示出来