zoukankan      html  css  js  c++  java
  • 【转】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

    本人新博客网址为:http://www.hizds.com
    本博客注有“转”字样的为转载文章,其余为本人原创文章,转载请务必注明出处或保存此段。c++/lua/windows逆向交流群:69148232
  • 相关阅读:
    maven项目诡异的问题
    13) Developing Java Plugins
    15) maven dependency scope
    Bootstrap学习记录
    电力
    MongoDB学习记录
    Java基础知识
    旅游
    人生感悟
    【转】25岁到55岁:如何规划人生最重要的三个十年
  • 原文地址:https://www.cnblogs.com/zhangdongsheng/p/2820175.html
Copyright © 2011-2022 走看看