首页
社区
课程
招聘
略解一个KeyGenMe(SHA-1)
发表于: 2006-6-22 18:56 7947

略解一个KeyGenMe(SHA-1)

2006-6-22 18:56
7947

原程序下载地址:http://www.crackmes.de/users/ox87k/keygenme1_gas/
使用工具:PEid,OllyDbg,ResHacker

  根据作者的简介,程序中使用了密码学保护方法,用PEid看了一下,发现SHA-1
字样。然后用OllyDbg加载。程序中有抗调试代码(主要是IsDebuggerPresent方
法),直接运行会立即终止。用隐藏插件尽量隐藏OD后重新载入方可运行。

  随便输入用户名和序列号,点击Check按钮,没有任何反应。查找程序中的有用
字串,找到一个:

   ASCII "Very good! Now make ur keygen and tutorial!"

但这次关键跳转并没有如预期的那样出现在引用这个字串前不远处,实际上在此之前
的代码有很多处都直接跳向失败,很难说其中的某一个是关键跳转。将代码向上翻
页,在地址408204处有一段代码:

=========================
00408204   .  8D4424 10     lea     eax, [esp+10]
00408208   .  50            push    eax
00408209   .  68 F3030000   push    3F3
0040820E   .  E8 030B0000   call    <jmp.&MFC42.#3097_CWnd::GetDlgIt>;  取序列号
=========================

先暂时把40820E设置为断点。3F3这个古怪的数字应该是控件ID,有必要弄清它代表
的是哪一个控件,于是求助于Resource Hacker,发现它是序列号输入框的ID。在这
句函数调用之前不远处又找到一句模样差不多的调用,经过与资源脚本的比对知道那
是在取用户名字串。整段代码如下:

//////////  以下是代码  ///////////

00407FFA   .  50            push    eax
00407FFB   .  68 F1030000   push    3F1
00408000   .  E8 110D0000   call    <jmp.&MFC42.#3097_CWnd::GetDlgIt>;  取用户名
00408005   .  8B5424 18     mov     edx, [esp+18]
00408009   .  83C9 FF       or      ecx, FFFFFFFF
0040800C   .  8BFA          mov     edi, edx
0040800E   .  33C0          xor     eax, eax
00408010   .  F2:AE         repne   scas byte ptr es:[edi]
00408012   .  F7D1          not     ecx
00408014   .  2BF9          sub     edi, ecx
00408016   .  8DAC24 940200>lea     ebp, [esp+294]                   ;  堆栈地址=0012EAAC
0040801D   .  8BC1          mov     eax, ecx
0040801F   .  8BF7          mov     esi, edi
00408021   .  8BFD          mov     edi, ebp
00408023   .  C1E9 02       shr     ecx, 2
00408026   .  F3:A5         rep     movs dword ptr es:[edi], dword p>
00408028   .  8BC8          mov     ecx, eax
0040802A   .  33C0          xor     eax, eax
0040802C   .  83E1 03       and     ecx, 3
0040802F   .  F3:A4         rep     movs byte ptr es:[edi], byte ptr>;  在上述地址中存入用户名
00408031   .  8BFA          mov     edi, edx
00408033   .  83C9 FF       or      ecx, FFFFFFFF
00408036   .  F2:AE         repne   scas byte ptr es:[edi]
00408038   .  F7D1          not     ecx
0040803A   .  49            dec     ecx
0040803B   .  8BE9          mov     ebp, ecx
0040803D      83FD 03       cmp     ebp, 3                           ;  用户名必须不少于3个字符
00408040   .  7D 0A         jge     short 0040804C
00408042   .  68 D8534100   push    004153D8                         ;  ASCII "Please insert between 4 and 32 chars..."
00408047   .  E9 A6030000   jmp     004083F2
0040804C   >  6A 01         push    1
0040804E   .  8D8C24 480200>lea     ecx, [esp+248]                   ;  堆栈地址=0012EA5C
00408055   .  55            push    ebp
00408056   .  8D9424 000100>lea     edx, [esp+100]                   ;  堆栈地址=0012E910(Hash串指针?)
0040805D   .  51            push    ecx
0040805E   .  8D8424 A00200>lea     eax, [esp+2A0]                   ;  堆栈地址=0012EAAC(用户名)
00408065   .  52            push    edx
00408066   .  50            push    eax
00408067   .  81EC C4000000 sub     esp, 0C4
0040806D   .  B9 31000000   mov     ecx, 31
00408072   .  8DB424 500600>lea     esi, [esp+650]                   ;  堆栈地址=0012ED90
00408079   .  8BFC          mov     edi, esp
0040807B   .  F3:A5         rep     movs dword ptr es:[edi], dword p>;  MD5加法常数表?
0040807D   .  E8 3E040000   call    004084C0
00408082   .  81C4 D8000000 add     esp, 0D8
00408088   .  8D8C24 300200>lea     ecx, [esp+230]
0040808F   .  8D9424 900000>lea     edx, [esp+90]
00408096   .  8D8424 F80000>lea     eax, [esp+F8]                    ;  堆栈地址=0012E910
0040809D   .  6A 02         push    2
0040809F   .  55            push    ebp
004080A0   .  51            push    ecx
004080A1   .  52            push    edx
004080A2   .  50            push    eax
004080A3   .  B9 31000000   mov     ecx, 31
004080A8   .  81EC C4000000 sub     esp, 0C4
004080AE   .  8DB424 C80400>lea     esi, [esp+4C8]
004080B5   .  8BFC          mov     edi, esp
004080B7   .  F3:A5         rep     movs dword ptr es:[edi], dword p>
004080B9   .  E8 02040000   call    004084C0
004080BE   .  81C4 D8000000 add     esp, 0D8
004080C4   .  8D8C24 6C0200>lea     ecx, [esp+26C]
004080CB   .  8D5424 28     lea     edx, [esp+28]
004080CF   .  8D8424 900000>lea     eax, [esp+90]
004080D6   .  6A 04         push    4
004080D8   .  55            push    ebp
004080D9   .  51            push    ecx
004080DA   .  52            push    edx
004080DB   .  50            push    eax
004080DC   .  B9 31000000   mov     ecx, 31
004080E1   .  81EC C4000000 sub     esp, 0C4
004080E7   .  8DB424 040400>lea     esi, [esp+404]                   ;  堆栈地址=0012EB44
004080EE   .  8BFC          mov     edi, esp
004080F0   .  F3:A5         rep     movs dword ptr es:[edi], dword p>
004080F2   .  E8 C9030000   call    004084C0
004080F7   .  81C4 D8000000 add     esp, 0D8
004080FD   .  8D8C24 800200>lea     ecx, [esp+280]
00408104   .  8D5424 5C     lea     edx, [esp+5C]
00408108   .  8D4424 28     lea     eax, [esp+28]
0040810C   .  6A 08         push    8
0040810E   .  55            push    ebp
0040810F   .  51            push    ecx
00408110   .  52            push    edx
00408111   .  50            push    eax
00408112   .  B9 31000000   mov     ecx, 31
00408117   .  81EC C4000000 sub     esp, 0C4
0040811D   .  8DB424 8C0500>lea     esi, [esp+58C]
00408124   .  8BFC          mov     edi, esp
00408126   .  F3:A5         rep     movs dword ptr es:[edi], dword p>
00408128   .  E8 93030000   call    004084C0
0040812D   .  81C4 D8000000 add     esp, 0D8
00408133   .  8D8C24 580200>lea     ecx, [esp+258]
0040813A   .  8D9424 C40000>lea     edx, [esp+C4]
00408141   .  8D4424 5C     lea     eax, [esp+5C]
00408145   .  6A 10         push    10
00408147   .  55            push    ebp
00408148   .  51            push    ecx
00408149   .  52            push    edx
0040814A   .  50            push    eax
0040814B   .  B9 31000000   mov     ecx, 31
00408150   .  81EC C4000000 sub     esp, 0C4
00408156   .  8DB424 140700>lea     esi, [esp+714]
0040815D   .  8BFC          mov     edi, esp
0040815F   .  F3:A5         rep     movs dword ptr es:[edi], dword p>
00408161   .  E8 5A030000   call    004084C0
00408166   .  81C4 D8000000 add     esp, 0D8
0040816C   .  33C0          xor     eax, eax
0040816E   .  889C24 000100>mov     [esp+100], bl                    ; 填0(截断字符串)
00408175   .  33C9          xor     ecx, ecx
00408177   >  8A9404 980000>mov     dl, [esp+eax+98]                 ; 这里是把要取来组合成序列号的子串移到Hash串首
0040817E   .  889404 900000>mov     [esp+eax+90], dl                 ; 当然这同时覆盖了原Hash串首的字符
00408185   .  8A540C 38     mov     dl, [esp+ecx+38]                 ; 注意这里的处理,递增eax而递减ecx
00408189   .  885404 28     mov     [esp+eax+28], dl                 ; 因此所复制的子串也是逆序的
0040818D   .  8A5404 74     mov     dl, [esp+eax+74]
00408191   .  885404 5C     mov     [esp+eax+5C], dl
00408195   .  8A940C E40000>mov     dl, [esp+ecx+E4]
0040819C   .  889404 C40000>mov     [esp+eax+C4], dl
004081A3   .  40            inc     eax
004081A4   .  49            dec     ecx
004081A5   .  83F9 F8       cmp     ecx, -8
004081A8   .^ 7F CD         jg      short 00408177
004081AA   .  A3 60554100   mov     [415560], eax
004081AF   .  8D8424 C40000>lea     eax, [esp+C4]
004081B6   .  8D4C24 5C     lea     ecx, [esp+5C]
004081BA   .  50            push    eax                              ; /<%s>
004081BB   .  8D5424 2C     lea     edx, [esp+2C]                    ; |
004081BF   .  51            push    ecx                              ; |<%s>
004081C0   .  8D8424 980000>lea     eax, [esp+98]                    ; |
004081C7   .  52            push    edx                              ; |<%s>
004081C8   .  8D8C24 040100>lea     ecx, [esp+104]                   ; |
004081CF   .  50            push    eax                              ; |<%s>
004081D0   .  51            push    ecx                              ; |<%s>
004081D1   .  8D9424 DC0200>lea     edx, [esp+2DC]                   ; |
004081D8   .  68 C8534100   push    004153C8                         ; |format = "%s-%s-%s-%s-%s"
004081DD   .  52            push    edx                              ; |根据分析结果,这里应该是存放真码的缓冲区
004081DE   .  889C24 B40000>mov     [esp+B4], bl                     ; |填0(截断字符串,下同)
004081E5   .  885C24 4C     mov     [esp+4C], bl                     ; |
004081E9   .  889C24 800000>mov     [esp+80], bl                     ; |
004081F0   .  889C24 E80000>mov     [esp+E8], bl                     ; |
004081F7   .  FF15 74A24000 call    [<&MSVCRT.sprintf>]              ; \sprintf
004081FD   .  8B4C24 30     mov     ecx, [esp+30]
00408201   .  83C4 1C       add     esp, 1C
00408204   .  8D4424 10     lea     eax, [esp+10]
00408208   .  50            push    eax
00408209   .  68 F3030000   push    3F3
0040820E   .  E8 030B0000   call    <jmp.&MFC42.#3097_CWnd::GetDlgIt>;  取序列号
00408213   .  8B5424 10     mov     edx, [esp+10]                    ;  序列号指针
00408217   .  33C0          xor     eax, eax
00408219   .  A3 64554100   mov     [415564], eax
0040821E   >  8A0C10        mov     cl, [eax+edx]
00408221   .  888C04 940100>mov     [esp+eax+194], cl                ;  首地址12E9AC
00408228   .  8A4C02 09     mov     cl, [edx+eax+9]
0040822C   .  888C04 FC0100>mov     [esp+eax+1FC], cl                ;  首地址12EA14
00408233   .  8A4C02 12     mov     cl, [edx+eax+12]
00408237   .  888C04 C80100>mov     [esp+eax+1C8], cl                ;  首地址12E9E0
0040823E   .  8A4C02 1B     mov     cl, [edx+eax+1B]
00408242   .  888C04 600100>mov     [esp+eax+160], cl                ;  首地址12E978
00408249   .  8A4C02 24     mov     cl, [edx+eax+24]
0040824D   .  888C04 2C0100>mov     [esp+eax+12C], cl                ;  首地址12E944
00408254   .  40            inc     eax
00408255   .  83F8 08       cmp     eax, 8
00408258   .  A3 64554100   mov     [415564], eax
0040825D   .^ 7C BF         jl      short 0040821E
0040825F   .  8BFA          mov     edi, edx
00408261   .  83C9 FF       or      ecx, FFFFFFFF
00408264   .  33C0          xor     eax, eax
00408266   .  889C24 9C0100>mov     [esp+19C], bl
0040826D   .  F2:AE         repne   scas byte ptr es:[edi]
0040826F   .  F7D1          not     ecx
00408271   .  49            dec     ecx
00408272   .  889C24 040200>mov     [esp+204], bl
00408279   .  83F9 2C       cmp     ecx, 2C                          ;  序列号长度必须为2Ch
0040827C   .  889C24 D00100>mov     [esp+1D0], bl
00408283   .  889C24 680100>mov     [esp+168], bl
0040828A   .  889C24 340100>mov     [esp+134], bl
00408291   .  0F85 69010000 jnz     00408400                         ;  跳向失败
00408297   .  8A42 08       mov     al, [edx+8]
0040829A   .  3C 2D         cmp     al, 2D                           ;  第9个字符必须为'-'
0040829C   .  0F85 5E010000 jnz     00408400                         ;  结论:序列号格式为5小节,每小节8字符
004082A2   .  807A 11 2D    cmp     byte ptr [edx+11], 2D            ;  小节之间用'-'连接
004082A6   .  0F85 54010000 jnz     00408400
004082AC   .  807A 1A 2D    cmp     byte ptr [edx+1A], 2D
004082B0   .  0F85 4A010000 jnz     00408400
004082B6   .  807A 23 2D    cmp     byte ptr [edx+23], 2D
004082BA   .  0F85 40010000 jnz     00408400
004082C0   .  8DB424 F80000>lea     esi, [esp+F8]                    ;  从这里开始用输入的序列号进行比较
004082C7   .  8D8424 940100>lea     eax, [esp+194]
004082CE   >  8A10          mov     dl, [eax]
004082D0   .  8ACA          mov     cl, dl
004082D2   .  3A16          cmp     dl, [esi]
004082D4   .  75 1C         jnz     short 004082F2                   ;  跳(串不相等,下同)则失败
004082D6   .  3ACB          cmp     cl, bl                           ;  已达串尾否(bl=0)
004082D8   .  74 14         je      short 004082EE
004082DA   .  8A50 01       mov     dl, [eax+1]
004082DD   .  8ACA          mov     cl, dl
004082DF   .  3A56 01       cmp     dl, [esi+1]
004082E2   .  75 0E         jnz     short 004082F2                   ;  串不相等
004082E4   .  83C0 02       add     eax, 2
004082E7   .  83C6 02       add     esi, 2
004082EA   .  3ACB          cmp     cl, bl
004082EC   .^ 75 E0         jnz     short 004082CE
004082EE   >  33C0          xor     eax, eax
004082F0   .  EB 05         jmp     short 004082F7
004082F2   >  1BC0          sbb     eax, eax
004082F4   .  83D8 FF       sbb     eax, -1                          ;  eax = (-1)CF
004082F7   >  3BC3          cmp     eax, ebx
004082F9   .  0F85 01010000 jnz     00408400
004082FF   .  8DB424 900000>lea     esi, [esp+90]
00408306   .  8D8424 FC0100>lea     eax, [esp+1FC]
0040830D   >  8A10          mov     dl, [eax]
0040830F   .  8ACA          mov     cl, dl
00408311   .  3A16          cmp     dl, [esi]
00408313   .  75 1C         jnz     short 00408331                   ;  同上
00408315   .  3ACB          cmp     cl, bl
00408317   .  74 14         je      short 0040832D
00408319   .  8A50 01       mov     dl, [eax+1]
0040831C   .  8ACA          mov     cl, dl
0040831E   .  3A56 01       cmp     dl, [esi+1]
00408321   .  75 0E         jnz     short 00408331
00408323   .  83C0 02       add     eax, 2
00408326   .  83C6 02       add     esi, 2
00408329   .  3ACB          cmp     cl, bl
0040832B   .^ 75 E0         jnz     short 0040830D
0040832D   >  33C0          xor     eax, eax
0040832F   .  EB 05         jmp     short 00408336
00408331   >  1BC0          sbb     eax, eax
00408333   .  83D8 FF       sbb     eax, -1
00408336   >  3BC3          cmp     eax, ebx
00408338   .  0F85 C2000000 jnz     00408400
0040833E   .  8D7424 28     lea     esi, [esp+28]
00408342   .  8D8424 C80100>lea     eax, [esp+1C8]
00408349   >  8A10          mov     dl, [eax]
0040834B   .  8ACA          mov     cl, dl
0040834D   .  3A16          cmp     dl, [esi]
0040834F   .  75 1C         jnz     short 0040836D
00408351   .  3ACB          cmp     cl, bl
00408353   .  74 14         je      short 00408369
00408355   .  8A50 01       mov     dl, [eax+1]
00408358   .  8ACA          mov     cl, dl
0040835A   .  3A56 01       cmp     dl, [esi+1]
0040835D   .  75 0E         jnz     short 0040836D
0040835F   .  83C0 02       add     eax, 2
00408362   .  83C6 02       add     esi, 2
00408365   .  3ACB          cmp     cl, bl
00408367   .^ 75 E0         jnz     short 00408349
00408369   >  33C0          xor     eax, eax
0040836B   .  EB 05         jmp     short 00408372
0040836D   >  1BC0          sbb     eax, eax
0040836F   .  83D8 FF       sbb     eax, -1
00408372   >  3BC3          cmp     eax, ebx
00408374   .  0F85 86000000 jnz     00408400
0040837A   .  8D7424 5C     lea     esi, [esp+5C]
0040837E   .  8D8424 600100>lea     eax, [esp+160]
00408385   >  8A10          mov     dl, [eax]
00408387   .  8ACA          mov     cl, dl
00408389   .  3A16          cmp     dl, [esi]
0040838B   .  75 1C         jnz     short 004083A9
0040838D   .  3ACB          cmp     cl, bl
0040838F   .  74 14         je      short 004083A5
00408391   .  8A50 01       mov     dl, [eax+1]
00408394   .  8ACA          mov     cl, dl
00408396   .  3A56 01       cmp     dl, [esi+1]
00408399   .  75 0E         jnz     short 004083A9
0040839B   .  83C0 02       add     eax, 2
0040839E   .  83C6 02       add     esi, 2
004083A1   .  3ACB          cmp     cl, bl
004083A3   .^ 75 E0         jnz     short 00408385
004083A5   >  33C0          xor     eax, eax
004083A7   .  EB 05         jmp     short 004083AE
004083A9   >  1BC0          sbb     eax, eax
004083AB   .  83D8 FF       sbb     eax, -1
004083AE   >  3BC3          cmp     eax, ebx
004083B0   .  75 4E         jnz     short 00408400
004083B2   .  8DB424 C40000>lea     esi, [esp+C4]
004083B9   .  8D8424 2C0100>lea     eax, [esp+12C]
004083C0   >  8A10          mov     dl, [eax]
004083C2   .  8ACA          mov     cl, dl
004083C4   .  3A16          cmp     dl, [esi]
004083C6   .  75 1C         jnz     short 004083E4
004083C8   .  3ACB          cmp     cl, bl
004083CA   .  74 14         je      short 004083E0
004083CC   .  8A50 01       mov     dl, [eax+1]
004083CF   .  8ACA          mov     cl, dl
004083D1   .  3A56 01       cmp     dl, [esi+1]
004083D4   .  75 0E         jnz     short 004083E4
004083D6   .  83C0 02       add     eax, 2
004083D9   .  83C6 02       add     esi, 2
004083DC   .  3ACB          cmp     cl, bl
004083DE   .^ 75 E0         jnz     short 004083C0
004083E0   >  33C0          xor     eax, eax
004083E2   .  EB 05         jmp     short 004083E9
004083E4   >  1BC0          sbb     eax, eax
004083E6   .  83D8 FF       sbb     eax, -1
004083E9   >  3BC3          cmp     eax, ebx
004083EB   .  75 13         jnz     short 00408400
004083ED   .  68 9C534100   push    0041539C                         ;  ASCII "Very good! Now make ur keygen and tutorial!"
004083F2   >  8B4C24 18     mov     ecx, [esp+18]
004083F6   .  68 F3030000   push    3F3
004083FB   .  E8 10090000   call    <jmp.&MFC42.#5953_CWnd::SetDlgIt>

//////////  以上是代码  ///////////

从取得用户名字串的地方开始跟踪,当经过408096一句时,下方的状态框中出现:

   堆栈地址=0012E910, (ASCII "A360DF687F69642CD40B89E51587AE4C3C3E018C")

这很象是一个Hash值啊。数一下位数,40位16进数,正好是160位二进数。联系用
PEid检查的结果,猜测这可能就是SHA-1算法。不过现在只是粗跟踪,暂时不去管
它。接下来在4080CF、408108、408141处也出现了相似的情形,提示指令中引用
的堆栈地址是一个Hash字串的指针。

  接着跟到获取并处理序列号的部分,最初的时候用的假序列号是任意输的,
跟踪过程中发现序列号的格式有要求,因而重新输入符合格式的序列号。在
4082C0处开始用输入序列号的第一小节做串比较,用于比较的另一字串就是第一
次见到的Hash串的第一小节(每8字符一小节,下同)。由于输入过于任意,在第
一节的比较中就被踢到失败的分支里去了,无法继续跟踪下去,只好通过修改内
存值的方法使得流程进入下一节的比较,往后几节的比较也是如此。跟踪的结果
表明:

   输入码的第一小节与第一次出现的Hash串第一小节比较
   输入码的第二小节与第二次出现的Hash串第二小节比较
   输入码的第三小节与第三次出现的Hash串第??小节比较
   输入码的第四小节与第四次出现的Hash串第四小节比较
   输入码的第五小节与第五次出现的Hash串第??小节比较

当然现在只是粗跟踪一遍后得到的结论,然而这起码说明了输入的序列号仅仅是
用来比较而不进行其他变换,那就表明应该可以通过程序自身的运算而得到真的
序列号。

  既然真的序列号是上述Hash串的某些子串,那就有必要弄清这些Hash值是怎
么算出来的。观察40807D处对过程4084C0的调用,在调用前推入的参数有用户名
指针及长度等信息,调用完以后在408096处就出现了一个Hash串,那4084C0这个
过程应该就是计算Hash值的。用Hash计算器计算"PEDIY"的SHA-1值,怎么跟程序
里出现的值不一样!跟进过程4084C0看一看:

//////////  以下是代码  ///////////

004084C0  /$  64:A1 0000000>mov     eax, fs:[0]
004084C6  |.  6A FF         push    -1
004084C8  |.  68 78904000   push    00409078
004084CD  |.  50            push    eax
004084CE  |.  64:8925 00000>mov     fs:[0], esp
004084D5  |.  53            push    ebx
004084D6  |.  56            push    esi
004084D7  |.  57            push    edi
004084D8  |.  8D4C24 1C     lea     ecx, [esp+1C]                    ;  MD5 T1
004084DC  |.  C74424 14 000>mov     dword ptr [esp+14], 0
004084E4  |.  E8 27D3FFFF   call    00405810                         ;  SHA初始化
004084E9  |.  8BB424 F00000>mov     esi, [esp+F0]
004084F0  |.  83FE 01       cmp     esi, 1                           ;  参数5(子串重复次数)
004084F3  |.  75 1B         jnz     short 00408510
004084F5  |.  8B8424 EC0000>mov     eax, [esp+EC]                    ;  参数4(用户名长)
004084FC  |.  8B8C24 E00000>mov     ecx, [esp+E0]                    ;  参数3(用户名指针)
00408503  |.  50            push    eax
00408504  |.  51            push    ecx
00408505  |.  8D4C24 24     lea     ecx, [esp+24]
00408509  |.  E8 C2EAFFFF   call    00406FD0                         ;  字符串连接
0040850E  |.  EB 36         jmp     short 00408546
00408510  |>  85F6          test    esi, esi
00408512  |.  C705 60554100>mov     dword ptr [415560], 0
0040851C  |.  7E 28         jle     short 00408546
0040851E  |.  8BBC24 EC0000>mov     edi, [esp+EC]
00408525  |.  8B9C24 E00000>mov     ebx, [esp+E0]
0040852C  |>  57            /push    edi
0040852D  |.  53            |push    ebx
0040852E  |.  8D4C24 24     |lea     ecx, [esp+24]
00408532  |.  E8 99EAFFFF   |call    00406FD0
00408537  |.  A1 60554100   |mov     eax, [415560]
0040853C  |.  40            |inc     eax
0040853D  |.  3BC6          |cmp     eax, esi
0040853F  |.  A3 60554100   |mov     [415560], eax
00408544  |.^ 7C E6         \jl      short 0040852C
00408546  |>  8D4C24 1C     lea     ecx, [esp+1C]
0040854A  |.  E8 41EBFFFF   call    00407090                         ;  Hash值计算过程
0040854F  |.  8B9424 E40000>mov     edx, [esp+E4]
00408556  |.  6A 00         push    0                                ; /Arg2 = 00000000
00408558  |.  52            push    edx                              ; |存放Hash值的指针
00408559  |.  8D4C24 24     lea     ecx, [esp+24]                    ; |
0040855D  |.  E8 0EECFFFF   call    00407170                         ; \+gAs+.00407170
00408562  |.  8D4C24 1C     lea     ecx, [esp+1C]
00408566  |.  C74424 14 FFF>mov     dword ptr [esp+14], -1
0040856E  |.  E8 8DD2FFFF   call    00405800
00408573  |.  8B4C24 0C     mov     ecx, [esp+C]
00408577  |.  5F            pop     edi
00408578  |.  5E            pop     esi
00408579  |.  64:890D 00000>mov     fs:[0], ecx
00408580  |.  5B            pop     ebx
00408581  |.  83C4 0C       add     esp, 0C
00408584  \.  C3            retn

//////////  以上是代码  ///////////

其中查看一下过程405810的内容:

//////////  以下是代码  ///////////

00405810  |$  33C0          xor     eax, eax
00405812  |.  C701 78A46AD7 mov     dword ptr [ecx], D76AA478        
00405818  |.  C741 04 56B7C>mov     dword ptr [ecx+4], E8C7B756      
0040581F  |.  C741 08 DB702>mov     dword ptr [ecx+8], 242070DB      
00405826  |.  C741 0C EECEB>mov     dword ptr [ecx+C], C1BDCEEE      
0040582D  |.  C741 10 AF0F7>mov     dword ptr [ecx+10], F57C0FAF     
00405834  |.  8941 14       mov     [ecx+14], eax
00405837  |.  8941 18       mov     [ecx+18], eax
0040583A  \.  C3            retn

//////////  以上是代码  ///////////

这不是MD5的加法常数吗,难道用的是MD5算法?可是为什么又只用5个值呢,MD5一共
有64个加法常数呀!由于“先入为主”倾向于认为还是SHA-1算法,联想到SHA-1初始
化的时候用了5个双字整数。那这应该是用MD5的前5个Ti做SHA-1的初始化值!SHA-1
计算程序可谓多矣,可是无一例外的是用67452301h之类的“传统数值”初始化,能
自选初始化数值的却没有。不得已之下通过修改exe把初始化数值改成这里所需要的,
再来计算"PEDIY",果然出现了"A360DF687F69642CD40B89E51587AE4C3C3E018C"!

  第一次出现的Hash值是用户名的SHA-1,那第二次、第三次……这些Hash值,又
是谁的SHA-1呢?回到主调程序中,代替用户名的指针,4080B9处第二次调用4084C0
过程使用的就是上面这个Hash串的指针。难道是这个串的Hash值?计算一下,发现不
对。又想到在传递给4084C0的参数中还有一个串长(即ebp的值),第二次调用时这
个串长的值并未改变,还是5。那就取第一次的Hash串前5个字符组成的子串,即
"A360D",算一算看看怎么样呢?算了一下,还是不对!

  怎么搞的啊。再进入4084C0看一下,在4084F0处用到了调用此过程的第5个参数
(最先入栈参数),根据这个参数的值决定重复调用过程406FD0多少次。然而根据监
视相关内存单元的结果,对Hash值的计算及写入是在调用407090中完成的,那406FD0
这个过程究竟是干什么的呢?这个过程的两个参数分别是父过程传递进来的串长和串
指针,跟进这个过程可知它把串指针起始处的串长个字符复制到某个地方,而关键在
于如果在40852C到408544的循环中调用此过程,则每一次复制字符串的目的指针都是
上一次复制的串尾,也就是说,这本质上相当于字符串连接!这样的话,第二次传递
给过程4084C0的参数5的值是2,上述循环执行2遍,得到的字符串应该是
"A360DA360D",算一下它的SHA-1,与结果相符!

  这样的话,主调程序中每次调用4084C0的参数3都是上一次Hash值的串指针,而
究竟要计算哪个串的SHA-1,只需要看调用它的参数5就行了。

  如果只是简单地从每一次的Hash串中抽取一个子串来组合成序列号,那到这里就
没有什么更多的事了。问题是,序列号的第3、5小节在对应的Hash串中找不到。第3
次和第5次的Hash串分别是:

   "C4D6F82E3150BCB1C2AEAD7A7D47BAC1DF10C8C3"
   "C965332E4655754B5F089182C9E49DD9C0E1993B"   
而对应序列号的第3小节是:

    xxxxxxxx-xxxxxxxx-C1BCB051-xxxxxxxx-C9DD94E9

注意到如果把第10到17个字符组成的子串,即"150BCB1C",反过来读正好是
"C1BCB051",而第五次的Hash串第26到33个字符也存在同样的对应关系。这又是哪里
出了问题呢?回到程序中看一下,在408177处有一个移动8个字符小节的动作,对于
第2、4次的Hash串,只是简单地把要组合的小节移到串首;而第3、5次Hash串,由于
源指针是递减的,相当于移动的同时完成反序。

  至此可以把算法总结如下:

  以输入用户名"PEDIY"为例

  (1)取用户名串长,记为N。N必须大于或等于3。在本例中,N的值为5。
  (2)计算用户名的SHA-1字串,记为s1。这里的SHA-1用的初始化数据是MD5的
     前5个加法常数,下同。
        "PEDIY"的SHA-1为:
       "A360DF687F69642CD40B89E51587AE4C3C3E018C"
    (3)取s1的前N个字符(十六进制字母必须采用大写形式,下同),重复2遍后
     计算该串的SHA-1字串,记为s2。
      "A360DA360D"的SHA-1为:
              "EBA0E37BE9B7BD512AF60ABED40D9DA9EEACD579"
  (4)取s2的前N个字符,重复4遍后计算该串的SHA-1字串,记为s3。
      "EBA0EEBA0EEBA0EEBA0E"的SHA-1为:
              "C4D6F82E3150BCB1C2AEAD7A7D47BAC1DF10C8C3"
  (5)取s3的前N个字符,重复8遍后计算该串的SHA-1字串,记为s4。
        "C4D6F...C4D6F"(共8个C4D6F)的SHA-1为:
              "86DC3621A675D80043C6675A19E29FD9A03242AE"
  (6)取s4的前N个字符,重复16遍后计算该串的SHA-1字串,记为s5。
        "86DC3...86DC3"(共16个86DC3)的SHA-1为:
              "C965332E4655754B5F089182C9E49DD9C0E1993B"
  (7)取s1的第1到8个字符"A360DF68"、s2的第9到16个字符"E9B7BD51"、s3的
     第10到17个字符"150BCB1C"、s4的第25到32个字符"19E29FD9"、s5的第
     26到33个字符"9E49DD9C",并将第3、5次取的子串反序,即"C1BCB051"
     和"C9DD94E9",最后用连接符"-"依次组合而得序列号:

             A360DF68-E9B7BD51-C1BCB051-19E29FD9-C9DD94E9

  再考虑一种可能,SHA-1只有40个字符,万一N大于40会发生什么事呢?然而在
Name框中尝试一下就可以知道只能输32个字符,原来在407828处有调用:

==============================
00407818   .  6A 00         push    0
0040781A   .  6A 20         push    20
0040781C   .  68 C5000000   push    0C5                              ;  EM_LIMITTEXT
00407821   .  68 F1030000   push    3F1                              ;  用户名输入框ID
00407826   .  8BCE          mov     ecx, esi
00407828   .  E8 9B140000   call    <jmp.&MFC42.#5802_CWnd::SendDlgI>
==============================

正是这里限定了用户名最多为32个字符,所以没有上述可能性。


[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

上传的附件:
收藏
免费 7
支持
分享
最新回复 (5)
雪    币: 721
活跃值: (350)
能力值: ( LV9,RANK:1250 )
在线值:
发帖
回帖
粉丝
2
分析得很详细,鼓励一下。
http://www.crackmes.de的确有很多不错的CrackMe。
2006-6-22 19:12
0
雪    币: 333
活跃值: (40)
能力值: ( LV9,RANK:730 )
在线值:
发帖
回帖
粉丝
3
学习!分析很详细,是我们菜鸟的好教程。
2006-6-23 00:15
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
没具体说明怎么隐藏OD后方插件?     

真正的不懂
2006-6-23 17:53
0
雪    币: 433
活跃值: (176)
能力值: ( LV13,RANK:1250 )
在线值:
发帖
回帖
粉丝
5
看雪版OD的“插件”菜单里有个HideOD,打开Option子菜单,把能用的方法都打上勾。

如果你不懂插件的工作原理,你也可以手动去掉抗调试代码,就象下面这样:

0040782D   .  E8 48150000   call    <jmp.&KERNEL32.IsDebuggerPresent>; [IsDebuggerPresent
00407832      85C0          test    eax, eax                         ;  把这里改成xor eax, eax
00407834   .  74 07         je      short 0040783D                   ;  把这里改成jmp 40788F(EB 59)
00407836   .  8BCE          mov     ecx, esi
00407838   .  E8 AD130000   call    <jmp.&MFC42.#4376_CDialog::OnCan>
0040783D   >  E8 6E0E0000   call    004086B0                         ;  再度调用IsDebuggerPresent
00407842      85C0          test    eax, eax
00407844   .  74 07         je      short 0040784D
00407846   .  8BCE          mov     ecx, esi
00407848   .  E8 9D130000   call    <jmp.&MFC42.#4376_CDialog::OnCan>
0040784D   >  8B0D 74554100 mov     ecx, [415574]
00407853   .  8B15 6C554100 mov     edx, [41556C]
00407859   .  A1 68554100   mov     eax, [415568]
0040785E   .  51            push    ecx                              ; /Arg3 => 00000000
0040785F   .  52            push    edx                              ; |Arg2 => 00000000
00407860   .  50            push    eax                              ; |Arg1 => 00000000
00407861   .  E8 2A0D0000   call    00408590                         ; \这是人为产生异常的过程
00407866   .  83C4 0C       add     esp, 0C
00407869      85C0          test    eax, eax
0040786B   .  74 07         je      short 00407874
0040786D   .  8BCE          mov     ecx, esi
0040786F   .  E8 76130000   call    <jmp.&MFC42.#4376_CDialog::OnCan>
00407874   >  68 CCC04000   push    0040C0CC                         ; /String = "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s"
00407879   .  FF15 4CA04000 call    [<&KERNEL32.OutputDebugStringA>] ; \OutputDebugStringA
0040787F   .  E8 9C0D0000   call    00408620                         ;  这是人为产生异常的过程
00407884   .  85C0          test    eax, eax
00407886   .  74 07         je      short 0040788F
00407888   .  8BCE          mov     ecx, esi
0040788A   .  E8 5B130000   call    <jmp.&MFC42.#4376_CDialog::OnCan>
0040788F   >  8D4C24 10     lea     ecx, [esp+10]

这个程序抗调试的原理是人为产生异常,如果没有调试器它就调用预定的异常处理过程恢复运行,调试器加载后更换了异常处理过程导致程序终止。
2006-6-23 18:47
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
thank you
2006-6-25 12:59
0
游客
登录 | 注册 方可回帖
返回
//