AntiOd IsDebuggerPresent + CRC 验证 + 对明文字符串的处理

转自看雪原文连接:http://bbs.pediy.com/showthread.php?t=159883

[KFC]fish’s CrackMe  破文

用OD载入程序,按F9运行,程序显示了窗口就退出了,初步分析有anti代码.打开OD的插件IsDebuggerPresent plugin v1.4后再运行程序,这样就没问题了,说明此程序是用IsDebuggerPresent()这个函数来anti debugger的,但是用W32Dasm或C32ASM又找不出相应的字符串,说明了程序有可能是动态生成了字符串.大约的浏览一下程序的反汇编代码,发现有点地方是与平常不同的,如:

00401670  |.  B3 73         mov bl,73

00401672  |.  884C24 22     mov byte ptr ss:[esp+22],cl

00401676  |.  884C24 23     mov byte ptr ss:[esp+23],cl

0040167A  |.  56            push esi

0040167B  |.  8D4C24 0C     lea ecx,dword ptr ss:[esp+C]

0040167F  |.  C64424 10 4B  mov byte ptr ss:[esp+10],4B

00401684  |.  884424 11     mov byte ptr ss:[esp+11],al

00401688  |.  885424 12     mov byte ptr ss:[esp+12],dl

0040168C  |.  C64424 13 6E  mov byte ptr ss:[esp+13],6E

00401691  |.  884424 14     mov byte ptr ss:[esp+14],al

00401695  |.  C64424 16 33  mov byte ptr ss:[esp+16],33

0040169A  |.  C64424 17 32  mov byte ptr ss:[esp+17],32

0040169F  |.  C64424 18 2E  mov byte ptr ss:[esp+18],2E

004016A4  |.  C64424 19 64  mov byte ptr ss:[esp+19],64

004016A9  |.  C64424 1C 00  mov byte ptr ss:[esp+1C],0

004016AE  |.  C64424 20 49  mov byte ptr ss:[esp+20],49

004016B3  |.  885C24 21     mov byte ptr ss:[esp+21],bl

004016B7  |.  C64424 22 44  mov byte ptr ss:[esp+22],44

004016BC  |.  884424 23     mov byte ptr ss:[esp+23],al

004016C0  |.  C64424 24 62  mov byte ptr ss:[esp+24],62

004016C5  |.  C64424 25 75  mov byte ptr ss:[esp+25],75

004016CA  |.  884424 28     mov byte ptr ss:[esp+28],al

 

还有

0040145E   .  8D4C24 10     lea ecx,dword ptr ss:[esp+10]

00401462   .  33FF          xor edi,edi

00401464   .  E8 7F080000   call <jmp.&MFC42.#540_CString::CString>

00401469   .  B0 41         mov al,41

0040146B   .  B1 62         mov cl,62

0040146D   .  884424 1D     mov byte ptr ss:[esp+1D],al

00401471   .  884424 29     mov byte ptr ss:[esp+29],al

00401475   .  884424 31     mov byte ptr ss:[esp+31],al

00401479   .  884424 35     mov byte ptr ss:[esp+35],al

0040147D   .  884C24 20     mov byte ptr ss:[esp+20],cl

00401481   .  884C24 34     mov byte ptr ss:[esp+34],cl

00401485   .  B0 11         mov al,11

00401487   .  B1 69         mov cl,69

00401489   .  884424 38     mov byte ptr ss:[esp+38],al

0040148D   .  884424 3C     mov byte ptr ss:[esp+3C],al

00401491   .  B3 4B         mov bl,4B

00401493   .  B2 68         mov dl,68

00401495   .  884C24 37     mov byte ptr ss:[esp+37],cl

00401499   .  884C24 3A     mov byte ptr ss:[esp+3A],cl

0040149D   .  B0 CF         mov al,0CF

0040149F   .  6A 01         push 1

004014A1   .  8BCE          mov ecx,esi

004014A3   .  897C24 54     mov dword ptr ss:[esp+54],edi

004014A7   .  C64424 1C 7D  mov byte ptr ss:[esp+1C],7D

004014AC   .  C64424 1D 08  mov byte ptr ss:[esp+1D],8

004014B1   .  C64424 1E 18  mov byte ptr ss:[esp+1E],18

004014B6   .  885C24 1F     mov byte ptr ss:[esp+1F],bl

 

这两处好像是初始化字符串的地方,在这两个地方设了断点,运行程序,注意要打开IsDebuggerPresent plugin,输入了UserName和Regkey以后点OK.跟着程序又退出了,这样说明了程序除了IsDebuggerPresent的Anti代码外还有其它的Anti代码.两次都是退出程序,一般VC退出程序来说PostQuitMessage()用得很多,那就用OD来查一查PostQuitMessage()函数,发现两处:

0040172E  |.  8BF8          mov edi,eax

00401730  |.  E8 AD050000   call <jmp.&MFC42.#860_CString::operator=>

00401735  |.  8B1D 00324000 mov ebx,dword ptr ds:[<&USER32.PostQuitM>;  USER32.PostQuitMessage

0040173B  |.  85FF          test edi,edi

 

还有一处就是

00401A18   .  85C0          test eax,eax

00401A1A   .  75 07         jnz short CrackMe.00401A23

00401A1C   .  50            push eax                                 ; /ExitCode

00401A1D   .  FF15 00324000 call dword ptr ds:[<&USER32.PostQuitMess>; \PostQuitMessage

00401A23   >  8BCE          mov ecx,esi

00401A25   .  E8 16000000   call CrackMe.00401A40

00401A2A   .  8BCE          mov ecx,esi

 

在这两处下断点,再次运行程序,第一次断在这里

 

004016FB  |.  C74424 3C 000>mov dword ptr ss:[esp+3C],0

00401703  |.  33F6          xor esi,esi

00401705  |>  8A4434 10     /mov al,byte ptr ss:[esp+esi+10]   ;字母解码开始,注意12FE4C处的内存,解码完毕后是Kernel32.dll 字符串

00401709  |.  8D4C24 0C     |lea ecx,dword ptr ss:[esp+C]

0040170D  |.  50            |push eax

0040170E  |.  E8 05060000   |call <jmp.&MFC42.#940_CString::operator+=>

00401713  |.  46            |inc esi

00401714  |.  83FE 0C       |cmp esi,0C

00401717  |.^ 7C EC         \jl short CrackMe.00401705

00401719  |.  8B4C24 0C     mov ecx,dword ptr ss:[esp+C]  ;解码完毕后的字符串送到ECX寄存器里面

0040171D  |.  57            push edi

0040171E  |.  51            push ecx                                     ; /FileName

0040171F  |.  FF15 04304000 call dword ptr ds:[<&KERNEL32.LoadLibraryA>] ; \LoadLibraryA  这个函数的用法查查MSDN就知道了

00401725  |.  68 EC404000   push CrackMe.004040EC

0040172A  |.  8D4C24 14     lea ecx,dword ptr ss:[esp+14]

0040172E  |.  8BF8          mov edi,eax

00401730  |.  E8 AD050000   call <jmp.&MFC42.#860_CString::operator=>

00401735  |.  8B1D 00324000 mov ebx,dword ptr ds:[<&USER32.PostQuitMessa>;  USER32.PostQuitMessage  这个只是把PostQuitMessage的地址送到EBX里面,不执行

0040173B  |.  85FF          test edi,edi  看看LoadLibraryA函数是否执行成功,不成功就跳走

0040173D  |.  74 2C         je short CrackMe.0040176B

0040173F  |.  33F6          xor esi,esi

00401741  |>  8A5434 24     /mov dl,byte ptr ss:[esp+esi+24] ;又开始解码字符串了,注意12FE4C内存处(堆栈里面) 解码完毕以后是IsDebuggerPresent字符串

00401745  |.  8D4C24 10     |lea ecx,dword ptr ss:[esp+10]

00401749  |.  52            |push edx

0040174A  |.  E8 C9050000   |call <jmp.&MFC42.#940_CString::operator+=>

0040174F  |.  46            |inc esi

00401750  |.  83FE 11       |cmp esi,11

00401753  |.^ 7C EC         \jl short CrackMe.00401741

00401755  |.  8B4424 10     mov eax,dword ptr ss:[esp+10]

00401759  |.  50            push eax                                     ; 这时候要注意字符串是什么,

0040175A  |.  57            push edi                                     ; |hModule

0040175B  |.  FF15 00304000 call dword ptr ds:[<&KERNEL32.GetProcAddress>; \GetProcAddress  这个函数的用法也可以查MSDN,这是得到函数的地址,成功后在EAX处返回函数的地址

00401761  |.  FFD0          call eax  ;执行IsDebuggerPresent(),留意EAX处的值

00401763  |.  85C0          test eax,eax

00401765  |.  74 04         je short CrackMe.0040176B ;如果没有发现Debugger就跳下去

00401767  |.  6A 00         push 0

00401769  |.  FFD3          call ebx  ; 这个是PostQuitMessage函数

0040176B  |>  8BCD          mov ecx,ebp

0040176D  |.  E8 2E000000   call CrackMe.004017A0 ;不知是什么 按F7 CALL进去看看

00401772  |.  85C0          test eax,eax

00401774  |.  5F            pop edi

00401775  |.  75 03         jnz short CrackMe.0040177A  上面那个CALL是文件的CRC32检验的,如果CRC32检验与原来的CRC值不同,就不会跳了

00401777  |.  50            push eax

00401778  |.  FFD3          call ebx

0040177A  |>  8D4C24 0C     lea ecx,dword ptr ss:[esp+C]

0040177E  |.  C74424 3C FFF>mov dword ptr ss:[esp+3C],-1

 

 

004017A0  /$  81EC 0C010000 sub esp,10C

004017A6  |.  8D4424 08     lea eax,dword ptr ss:[esp+8]

004017AA  |.  53            push ebx

004017AB  |.  55            push ebp

004017AC  |.  56            push esi

004017AD  |.  68 04010000   push 104                                     ; /BufSize = 104 (260.)

004017B2  |.  50            push eax                                     ; |PathBuffer

004017B3  |.  8BE9          mov ebp,ecx                                  ; |

004017B5  |.  6A 00         push 0                                       ; |hModule = NULL

004017B7  |.  FF15 18304000 call dword ptr ds:[<&KERNEL32.GetModuleFileN>; \GetModuleFileNameA   得到文件进程的文件名

004017BD  |.  6A 00         push 0                                       ; /hTemplateFile = NULL

004017BF  |.  68 80000000   push 80                                      ; |Attributes = NORMAL

004017C4  |.  6A 03         push 3                                       ; |Mode = OPEN_EXISTING

004017C6  |.  6A 00         push 0                                       ; |pSecurity = NULL

004017C8  |.  6A 01         push 1                                       ; |ShareMode = FILE_SHARE_READ

004017CA  |.  8D4C24 28     lea ecx,dword ptr ss:[esp+28]                ; |

004017CE  |.  68 00000080   push 80000000                                ; |Access = GENERIC_READ

004017D3  |.  51            push ecx                                     ; |FileName

004017D4  |.  FF15 14304000 call dword ptr ds:[<&KERNEL32.CreateFileA>]  ; \CreateFileA   打开文件,

004017DA  |.  8BD8          mov ebx,eax

004017DC  |.  83FB FF       cmp ebx,-1

004017DF  |.  75 0C         jnz short CrackMe.004017ED

004017E1  |.  5E            pop esi

004017E2  |.  5D            pop ebp

004017E3  |.  33C0          xor eax,eax

004017E5  |.  5B            pop ebx

004017E6  |.  81C4 0C010000 add esp,10C

004017EC  |.  C3            retn

004017ED  |>  6A 00         push 0                                       ; /pFileSizeHigh = NULL

004017EF  |.  53            push ebx                                     ; |hFile

004017F0  |.  FF15 10304000 call dword ptr ds:[<&KERNEL32.GetFileSize>]  ; \GetFileSize  ;得到文件的SIZE

004017F6  |.  8BF0          mov esi,eax

004017F8  |.  83FE FF       cmp esi,-1

004017FB  |.  75 0C         jnz short CrackMe.00401809

004017FD  |.  5E            pop esi

004017FE  |.  5D            pop ebp

004017FF  |.  33C0          xor eax,eax

00401801  |.  5B            pop ebx

00401802  |.  81C4 0C010000 add esp,10C

00401808  |.  C3            retn

00401809  |>  57            push edi

0040180A  |.  56            push esi

0040180B  |.  E8 1A050000   call <jmp.&MFC42.#823_operator new>  ;分配内存

00401810  |.  83C4 04       add esp,4

00401813  |.  8D5424 14     lea edx,dword ptr ss:[esp+14]

00401817  |.  8BF8          mov edi,eax

00401819  |.  6A 00         push 0                                       ; /pOverlapped = NULL

0040181B  |.  52            push edx                                     ; |pBytesRead

0040181C  |.  56            push esi                                     ; |BytesToRead

0040181D  |.  57            push edi                                     ; |Buffer

0040181E  |.  53            push ebx                                     ; |hFile

0040181F  |.  FF15 0C304000 call dword ptr ds:[<&KERNEL32.ReadFile>]     ; \ReadFile   ;读文件,把自己映射到内存里面

00401825  |.  53            push ebx                                     ; /hObject

00401826  |.  FF15 08304000 call dword ptr ds:[<&KERNEL32.CloseHandle>]  ; \CloseHandle  ;关闭文件句柄

0040182C  |.  8A47 3C       mov al,byte ptr ds:[edi+3C]

0040182F  |.  884424 10     mov byte ptr ss:[esp+10],al

00401833  |.  8B4424 10     mov eax,dword ptr ss:[esp+10]

00401837  |.  25 FF000000   and eax,0FF

0040183C  |.  2BF0          sub esi,eax

0040183E  |.  8D0C38        lea ecx,dword ptr ds:[eax+edi]

00401841  |.  56            push esi                                     ; /Arg2

00401842  |.  51            push ecx                                     ; |Arg1

00401843  |.  8B79 FC       mov edi,dword ptr ds:[ecx-4]                 ; |

00401846  |.  8BCD          mov ecx,ebp                                  ; |

00401848  |.  E8 23000000   call CrackMe.00401870                        ; \CrackMe.00401870  要CALL进去,注意看看堆栈

0040184D  |.  33C9          xor ecx,ecx

 

 

00401870  /$  81EC 00040000 sub esp,400   ;平衡堆栈

00401876  |.  33C9          xor ecx,ecx

00401878  |.  8D5424 00     lea edx,dword ptr ss:[esp]

0040187C  |.  56            push esi

0040187D  |>  8BC1          /mov eax,ecx  ;聪明人一眼就看出了,这是生成CRC32的表

0040187F  |.  BE 08000000   |mov esi,8

00401884  |>  A8 01         |/test al,1

00401886  |.  74 09         ||je short CrackMe.00401891

00401888  |.  D1E8          ||shr eax,1

0040188A  |.  35 2083B8ED   ||xor eax,EDB88320   ;0xEDB88320是CRC32出现的常数

0040188F  |.  EB 02         ||jmp short CrackMe.00401893

00401891  |>  D1E8          ||shr eax,1

00401893  |>  4E            ||dec esi

00401894  |.^ 75 EE         |\jnz short CrackMe.00401884

00401896  |.  8902          |mov dword ptr ds:[edx],eax

00401898  |.  41            |inc ecx

00401899  |.  83C2 04       |add edx,4

0040189C  |.  81F9 00010000 |cmp ecx,100

004018A2  |.^ 7C D9         \jl short CrackMe.0040187D

004018A4  |.  8B8C24 0C0400>mov ecx,dword ptr ss:[esp+40C]

004018AB  |.  83C8 FF       or eax,FFFFFFFF

004018AE  |.  8BD1          mov edx,ecx

004018B0  |.  49            dec ecx

004018B1  |.  85D2          test edx,edx

004018B3  |.  74 27         je short CrackMe.004018DC

004018B5  |.  8D71 01       lea esi,dword ptr ds:[ecx+1]

004018B8  |.  8B8C24 080400>mov ecx,dword ptr ss:[esp+408]

004018BF  |.  53            push ebx

004018C0  |>  8BD0          /mov edx,eax  ;这个循环是计算文件CRC32值的

004018C2  |.  33DB          |xor ebx,ebx

004018C4  |.  8A19          |mov bl,byte ptr ds:[ecx]

004018C6  |.  81E2 FF000000 |and edx,0FF

004018CC  |.  33D3          |xor edx,ebx

004018CE  |.  C1E8 08       |shr eax,8

004018D1  |.  8B5494 08     |mov edx,dword ptr ss:[esp+edx*4+8]

004018D5  |.  33C2          |xor eax,edx

004018D7  |.  41            |inc ecx

004018D8  |.  4E            |dec esi

004018D9  |.^ 75 E5         \jnz short CrackMe.004018C0

004018DB  |.  5B            pop ebx   ;这时候EDI寄存器就是文件的CRC32值

004018DC  |>  F7D0          not eax

004018DE  |.  5E            pop esi

004018DF  |.  81C4 00040000 add esp,400

004018E5  \.  C2 0800       retn 8

 

 

第一层文件CRC文件攻破了,一直按F8不久,程序又会中断下来了,看这里:

00401A10   .  56            push esi

00401A11   .  8BF1          mov esi,ecx

00401A13   .  E8 28000000   call CrackMe.00401A40  按F7 CALL进去

00401A18   .  85C0          test eax,eax

00401A1A   .  75 07         jnz short CrackMe.00401A23

00401A1C   .  50            push eax                                     ; /ExitCode

00401A1D   .  FF15 00324000 call dword ptr ds:[<&USER32.PostQuitMessage>>; \PostQuitMessage  又一个PostQuitMessage()

 

 

CALL进去以后的代码,与上面的CRC代码相似,只是检查的是程序在内存中的.text区块的代码的CRC值,原程序的CRC32值放在程序的最尾处,可以用UltraEdit打开来看看.

进一步跟踪可以发现是每一个Timer消息就检查一次,也就是0.5秒就检查一次CRC值,发现CRC值不同的话就直接退出程序

00401A40  /$  81EC 08010000 sub esp,108

00401A46  |.  8D4424 04     lea eax,dword ptr ss:[esp+4]

00401A4A  |.  53            push ebx

00401A4B  |.  55            push ebp

00401A4C  |.  57            push edi

00401A4D  |.  68 04010000   push 104                                     ; /BufSize = 104 (260.)

00401A52  |.  50            push eax                                     ; |PathBuffer

00401A53  |.  8BE9          mov ebp,ecx                                  ; |

00401A55  |.  6A 00         push 0                                       ; |hModule = NULL

00401A57  |.  FF15 18304000 call dword ptr ds:[<&KERNEL32.GetModuleFileN>; \GetModuleFileNameA

00401A5D  |.  6A 00         push 0                                       ; /hTemplateFile = NULL

00401A5F  |.  68 80000000   push 80                                      ; |Attributes = NORMAL

00401A64  |.  6A 03         push 3                                       ; |Mode = OPEN_EXISTING

00401A66  |.  6A 00         push 0                                       ; |pSecurity = NULL

00401A68  |.  6A 01         push 1                                       ; |ShareMode = FILE_SHARE_READ

00401A6A  |.  8D4C24 24     lea ecx,dword ptr ss:[esp+24]                ; |

00401A6E  |.  68 00000080   push 80000000                                ; |Access = GENERIC_READ

00401A73  |.  51            push ecx                                     ; |FileName

00401A74  |.  FF15 14304000 call dword ptr ds:[<&KERNEL32.CreateFileA>]  ; \CreateFileA

00401A7A  |.  8BF8          mov edi,eax

00401A7C  |.  83FF FF       cmp edi,-1

00401A7F  |.  74 67         je short CrackMe.00401AE8

00401A81  |.  6A 00         push 0                                       ; /pFileSizeHigh = NULL

00401A83  |.  57            push edi                                     ; |hFile

00401A84  |.  FF15 10304000 call dword ptr ds:[<&KERNEL32.GetFileSize>]  ; \GetFileSize

00401A8A  |.  8BD8          mov ebx,eax

00401A8C  |.  83FB FF       cmp ebx,-1

00401A8F  |.  74 57         je short CrackMe.00401AE8

00401A91  |.  56            push esi

00401A92  |.  53            push ebx

00401A93  |.  E8 92020000   call <jmp.&MFC42.#823_operator new>

00401A98  |.  83C4 04       add esp,4

00401A9B  |.  8D5424 10     lea edx,dword ptr ss:[esp+10]

00401A9F  |.  8BF0          mov esi,eax

00401AA1  |.  6A 00         push 0                                       ; /pOverlapped = NULL

00401AA3  |.  52            push edx                                     ; |pBytesRead

00401AA4  |.  53            push ebx                                     ; |BytesToRead

00401AA5  |.  56            push esi                                     ; |Buffer

00401AA6  |.  57            push edi                                     ; |hFile

00401AA7  |.  FF15 0C304000 call dword ptr ds:[<&KERNEL32.ReadFile>]     ; \ReadFile

00401AAD  |.  57            push edi                                     ; /hObject

00401AAE  |.  FF15 08304000 call dword ptr ds:[<&KERNEL32.CloseHandle>]  ; \CloseHandle

00401AB4  |.  8BBE 00600000 mov edi,dword ptr ds:[esi+6000]

00401ABA  |.  56            push esi

00401ABB  |.  E8 38010000   call <jmp.&MFC42.#825_operator delete>

00401AC0  |.  83C4 04       add esp,4

00401AC3  |.  8BCD          mov ecx,ebp

00401AC5  |.  68 42100000   push 1042                                    ; /Arg2 = 00001042

00401ACA  |.  68 00104000   push CrackMe.00401000                        ; |Arg1 = 00401000

00401ACF  |.  E8 9CFDFFFF   call CrackMe.00401870                        ; \CrackMe.00401870   ;这是检查CRC32值

00401AD4  |.  33C9          xor ecx,ecx

00401AD6  |.  3BF8          cmp edi,eax

00401AD8  |.  5E            pop esi

00401AD9  |.  5F            pop edi

 

爆破了这两个CRC处以后,程序就可以运行了,下面就是来想想注册码的算法了

查MessageBox()处,发现以下处

 

00401546   .  E8 D9070000   call <jmp.&MFC42.#6334_CWnd::UpdateData>

0040154B   .  8B46 64       mov eax,dword ptr ds:[esi+64]

0040154E   .  8B2D D4314000 mov ebp,dword ptr ds:[<&MSVCRT._mbscmp>]     ;  MSVCRT._mbscmp

00401554   .  68 EC404000   push CrackMe.004040EC                        ; /s2 = ""

00401559   .  50            push eax                                     ; |s1

0040155A   .  FFD5          call ebp                                     ; \_mbscmp  ;看RegKey是否为空

0040155C   .  83C4 08       add esp,8

0040155F   .  85C0          test eax,eax

00401561   .  74 7A         je short CrackMe.004015DD  ;RegKey为空就跳走

00401563   .  8B46 60       mov eax,dword ptr ds:[esi+60]  ;注意:用户名

00401566   .  8D5E 60       lea ebx,dword ptr ds:[esi+60]

00401569   .  68 EC404000   push CrackMe.004040EC

0040156E   .  50            push eax

0040156F   .  FFD5          call ebp  ;看用户名是否为空

00401571   .  83C4 08       add esp,8

00401574   .  85C0          test eax,eax

00401576   .  74 65         je short CrackMe.004015DD  ;用户名为空就跳走

00401578   .  8B4E 64       mov ecx,dword ptr ds:[esi+64]

0040157B   .  33C0          xor eax,eax

0040157D   >  0FBE1401      movsx edx,byte ptr ds:[ecx+eax]  ;密码的每一个字符

00401581   .  81F2 AA000000 xor edx,0AA  ;与0xAA或异

00401587   .  03FA          add edi,edx  ;相加

00401589   .  40            inc eax

0040158A   .  83F8 09       cmp eax,9  ;循环9次

0040158D   .^ 7C EE         jl short CrackMe.0040157D  ;loop  这个用C来写就是 a=int(RegKey.GetAt(i)^0xAA); i=1~9

0040158F   .  57            push edi

00401590   .  51            push ecx

00401591   .  8BCC          mov ecx,esp

00401593   .  896424 1C     mov dword ptr ss:[esp+1C],esp

00401597   .  53            push ebx

00401598   .  E8 81070000   call <jmp.&MFC42.#535_CString::CString>

0040159D   .  8BCE          mov ecx,esi                                  ; |

0040159F   .  E8 8C030000   call CrackMe.00401930                        ; \CrackMe.00401930  ;重要,算法CALL 按F7进去

004015A4   .  85C0          test eax,eax

004015A6   .  74 1A         je short CrackMe.004015C2  ;跳下去就over了

004015A8   .  33FF          xor edi,edi

004015AA   >  8A443C 18     mov al,byte ptr ss:[esp+edi+18]  ;字符又开始解码了

004015AE   .  8D4C24 10     lea ecx,dword ptr ss:[esp+10]

004015B2   .  34 AA         xor al,0AA

004015B4   .  50            push eax

004015B5   .  E8 5E070000   call <jmp.&MFC42.#940_CString::operator+=>

004015BA   .  47            inc edi

004015BB   .  83FF 0A       cmp edi,0A

004015BE   .^ 7C EA         jl short CrackMe.004015AA

004015C0   .  EB 34         jmp short CrackMe.004015F6

004015C2   >  33FF          xor edi,edi

004015C4   >  8A4C3C 24     mov cl,byte ptr ss:[esp+edi+24]

004015C8   .  80F1 AA       xor cl,0AA

004015CB   .  51            push ecx

004015CC   .  8D4C24 14     lea ecx,dword ptr ss:[esp+14]

004015D0   .  E8 43070000   call <jmp.&MFC42.#940_CString::operator+=>

004015D5   .  47            inc edi

004015D6   .  83FF 0A       cmp edi,0A

004015D9   .^ 7C E9         jl short CrackMe.004015C4

004015DB   .  EB 19         jmp short CrackMe.004015F6

004015DD   >  33FF          xor edi,edi

004015DF   >  8A543C 30     mov dl,byte ptr ss:[esp+edi+30]

004015E3   .  8D4C24 10     lea ecx,dword ptr ss:[esp+10]

004015E7   .  80F2 AA       xor dl,0AA

004015EA   .  52            push edx

004015EB   .  E8 28070000   call <jmp.&MFC42.#940_CString::operator+=>

004015F0   .  47            inc edi

004015F1   .  83FF 14       cmp edi,14

004015F4   .^ 7C E9         jl short CrackMe.004015DF

004015F6   >  8B4424 10     mov eax,dword ptr ss:[esp+10]

004015FA   .  6A 00         push 0

004015FC   .  6A 00         push 0

004015FE   .  50            push eax

004015FF   .  8BCE          mov ecx,esi

00401601   .  E8 0C070000   call <jmp.&MFC42.#4224_CWnd::MessageBoxA> ;提示信息

 

 

算法CALL

00401930  /$  6A FF         push -1

00401932  |.  68 38204000   push CrackMe.00402038                        ;  SE handler installation

00401937  |.  64:A1 0000000>mov eax,dword ptr fs:[0]

0040193D  |.  50            push eax

0040193E  |.  64:8925 00000>mov dword ptr fs:[0],esp

00401945  |.  83EC 0C       sub esp,0C

00401948  |.  53            push ebx

00401949  |.  56            push esi

0040194A  |.  57            push edi

0040194B  |.  8B5424 28     mov edx,dword ptr ss:[esp+28]

0040194F  |.  B0 4B         mov al,4B

00401951  |.  884424 0C     mov byte ptr ss:[esp+C],al

00401955  |.  884424 10     mov byte ptr ss:[esp+10],al

00401959  |.  8B4A F8       mov ecx,dword ptr ds:[edx-8]

0040195C  |.  B0 4E         mov al,4E

0040195E  |.  884424 12     mov byte ptr ss:[esp+12],al

00401962  |.  884424 14     mov byte ptr ss:[esp+14],al

00401966  |.  33FF          xor edi,edi

00401968  |.  33F6          xor esi,esi

0040196A  |.  33C0          xor eax,eax

0040196C  |.  C64424 0D 45  mov byte ptr ss:[esp+D],45  ;初始化字符表

00401971  |.  85C9          test ecx,ecx

00401973  |.  C64424 0E 59  mov byte ptr ss:[esp+E],59

00401978  |.  C64424 0F 2D  mov byte ptr ss:[esp+F],2D

0040197D  |.  C64424 11 41  mov byte ptr ss:[esp+11],41

00401982  |.  C64424 13 4F  mov byte ptr ss:[esp+13],4F  ;字符表初始化完成,是”KEY-KANON”这个字符 (ps:本人是Key游戏的fans,觉得AIR这个名字太短了,就用KANON了 :))

00401987  |.  7E 0B         jle short CrackMe.00401994

00401989  |>  0FBE1C10      /movsx ebx,byte ptr ds:[eax+edx]  ;用户名的每一位

0040198D  |.  03F3          |add esi,ebx  ;前一位的ASCII码+后一位的ASCII码

0040198F  |.  40            |inc eax

00401990  |.  3BC1          |cmp eax,ecx

00401992  |.^ 7C F5         \jl short CrackMe.00401989 ;loop

00401994  |>  33C9          xor ecx,ecx

00401996  |>  0FBE440C 0C   /movsx eax,byte ptr ss:[esp+ecx+C] 字符表的每一位

0040199B  |.  0FAFC6        |imul eax,esi  与用户名的ASCII码累加值相乘

0040199E  |.  99            |cdq  ;把扩展数位为64位,防止溢出,不用管它

0040199F  |.  BB 1A000000   |mov ebx,1A

004019A4  |.  F7FB          |idiv ebx   ;EAX除以0x1A

004019A6  |.  83C2 61       |add edx,61  ;上面除法以后的余数+0x61

004019A9  |.  81F2 AA000000 |xor edx,0AA  ;与0xAA或异 

004019AF  |.  03FA          |add edi,edx  ;相加

004019B1  |.  41            |inc ecx  ;ECX+1 这是做计数器

004019B2  |.  83F9 09       |cmp ecx,9  ;循环9次

004019B5  |.^ 7C DF         \jl short CrackMe.00401996

004019B7  |.  8B4424 2C     mov eax,dword ptr ss:[esp+2C]  ;这是RegKey或异了0xAA以后的累加值

004019BB  |.  C74424 20 FFF>mov dword ptr ss:[esp+20],-1

004019C3  |.  3BF8          cmp edi,eax  ;比较了,爆破点就在附近了

004019C5  |.  5F            pop edi

004019C6  |.  5E            pop esi

004019C7  |.  5B            pop ebx

004019C8  |.  8D4C24 1C     lea ecx,dword ptr ss:[esp+1C]

004019CC  |.  75 1B         jnz short CrackMe.004019E9 ;爆破点,改为不跳就OK了

004019CE  |.  E8 37020000   call <jmp.&MFC42.#800_CString::~CString>

004019D3  |.  B8 01000000   mov eax,1

004019D8  |.  8B4C24 0C     mov ecx,dword ptr ss:[esp+C]

004019DC  |.  64:890D 00000>mov dword ptr fs:[0],ecx

004019E3  |.  83C4 18       add esp,18

004019E6  |.  C2 0800       retn 8

004019E9  |>  E8 1C020000   call <jmp.&MFC42.#800_CString::~CString>

004019EE  |.  8B4C24 0C     mov ecx,dword ptr ss:[esp+C]

004019F2  |.  33C0          xor eax,eax

004019F4  |.  64:890D 00000>mov dword ptr fs:[0],ecx

004019FB  |.  83C4 18       add esp,18

004019FE  \.  C2 0800       retn 8

 

 

算法总结:

(“KEY-KANON”的每一位的ASCII码值之和)%0x21 +0x61

但是它用了间接比较,把(RegKey的每一位)^0xAA 的int值与

((“KEY-KANON”的每一位的ASCII码值之和)%0x21 +0x61)^0xAA的int值对比,对就认为注册码正确;

注册机:

 

       CString ori="KEY-KANON";

       int usr=0;

       for(int i=0;i<UserName.GetLength();i++)

       {

              usr+=int(UserName.GetAt(i));

       }

       for(i=0;i<9;i++)

       {

              RegKey+=char((ori.GetAt(i)*usr)%0x1A+0x61);

       }

 

ps:第一次写CrackMe然后自己写对应的破文 :D

  永远支持AIR和Kanon, 被AIR动画感动得流了N次泪了 :~(

 

                                                              [KFC]fish (Pr0Zel)

 

 

下载:

破文.rar

CreakeMe.rar

你可能感兴趣的:(debugger)