一个CM的脱壳与爆破

【作者主页】: www.iawen.com
【作者QQ号】: =======**======
【软件名称】: Crackme.exe
【下载地址】: 见附件
【使用工具】: OD,PETool,ImportREC
【操作平台】: XP SP3
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
——————————————————————————–
【详细过程】
  一个简单的压缩壳,用PEID查看显示为:Morphine 1.4 – 2.7 -> Holy_Father & Ratter/29A
  我没见过,直接用OD载入得啦:
  


  00511654 Cr>  67:97           xchg eax,edi                               ; ntdll.7C930208
  00511656      67:97           xchg eax,edi
  00511658      F5              cmc
  00511659      90              nop
  0051165A      84ED            test ch,ch
  

  
  先F8单步一下吧:
  


  0051165F      51              push ecx          //单步到这里时,ESP显示红色
  00511660      52              push edx
  00511661      53              push ebx
  

  
  呵呵,就先用ESP试试吧,下断点:hr 0013FFC0
  F9运行时,出现一个错误提示窗口,不管它了,确定后继续运行,就到了这里:

  


  00401941      6A 00           push 0
  00401943      E8 60060000     call Crackm_1.00401FA8                     ; jmp 到,停在了这里,呵呵
  00401948      A3 30364000     mov dword ptr ds:[403630],eax
  0040194D      6A 00           push 0
  0040194F      68 69194000     push Crackm_1.00401969
  00401954      6A 00           push 0
  00401956      6A 65           push 65
  00401958      FF35 30364000   push dword ptr ds:[403630]
  0040195E      E8 09060000     call Crackm_1.00401F6C                     ; jmp 到
  00401963      50              push eax
  00401964      E8 33060000     call Crackm_1.00401F9C                     ; jmp 到
  

  
  嗯,一看,不是MASM的入口了么??难道就到了?
  先DUMP一下试试吧!
  在00401941上新建EIP,然后DUMP,再修复!
  我用LoadPE来Dump时,修正大小之后就无法Dump了,只好用PETool了,呵呵,修复一路顺风,运行OK!
  到些壳也就脱了,我也不来什么优化了,(我不会,^#^),再试试破解吧,哈
  
  用OD载入脱壳后的程序,直接运行起来!用户名,程序直接取了电脑名了,呵呵!
  我们也就不用输入了,随便输入一个假码吧,按确定,有出错提示!这样,我们就直接用堆栈调用来返回吧!
  


  00401B3E    /$  55            push ebp
  00401B3F    |.  8BEC          mov ebp,esp
  00401B41    |.  68 75304000   push Dumped_.00403075                      ;  ASCII "Error !"
  00401B46    |.  E8 D4FFFFFF   call Dumped_.00401B1F
  00401B4B    |.  68 C3304000   push Dumped_.004030C3                      ;  ASCII "The Serial You Entered Is Not Valid !"
  00401B50    |.  E8 CAFFFFFF   call Dumped_.00401B1F
  00401B55    |.  6A 30         push 30                                    ; /Style = MB_OK|MB_ICONEXCLAMATION|MB_APPLMODAL
  00401B57    |.  68 75304000   push Dumped_.00403075                      ; |Title = "Error !"
  00401B5C    |.  68 C3304000   push Dumped_.004030C3                      ; |Text = "The Serial You Entered Is Not Valid !"
  00401B61    |.  FF75 08       push dword ptr ss:[ebp+8]                  ; |hOwner
  00401B64    |.  E8 21040000   call <jmp.&user32.MessageBoxA>             ; \MessageBoxA
  00401B69    |.  68 75304000   push Dumped_.00403075                      ;  ASCII "Error !"
  00401B6E    |.  E8 ACFFFFFF   call Dumped_.00401B1F
  00401B73    |.  68 C3304000   push Dumped_.004030C3                      ;  ASCII "The Serial You Entered Is Not Valid !"
  00401B78    |.  E8 A2FFFFFF   call Dumped_.00401B1F
  00401B7D    |.  C9            leave
  00401B7E    \.  C2 0400       retn 4
  

  
  返回到上面的代码,在段首位置00401B3E上点击一下,留意提示窗口:
  Local Calls from 00401B06, 00401CD8
  
  先来到00401B06处,跑到段首下好断点:
  


  00401AD6    /$  55            push ebp         //F2下断
  00401AD7    |.  8BEC          mov ebp,esp
  00401AD9    |.  33DB          xor ebx,ebx
  00401ADB    |.  8A1D 34384000 mov bl,byte ptr ds:[403834]
  00401AE1    |.  53            push ebx
  00401AE2    |.  C605 34384000>mov byte ptr ds:[403834],0
  00401AE9    |.  6A 00         push 0
  00401AEB    |.  6A 04         push 4
  00401AED    |.  68 30384000   push Dumped_.00403830                      ;  ASCII "1111"
  00401AF2    |.  E8 19FEFFFF   call Dumped_.00401910
  00401AF7    |.  8B1D 11324000 mov ebx,dword ptr ds:[403211]
  00401AFD    |.  0FCB          bswap ebx
  00401AFF    |.  3BC3          cmp eax,ebx
  00401B01    |.  74 0C         je short Dumped_.00401B0F
  00401B03    |.  FF75 08       push dword ptr ss:[ebp+8]
  00401B06    |.  E8 33000000   call Dumped_.00401B3E
  00401B0B    |.  33C0          xor eax,eax
  00401B0D    |.  EB 05         jmp short Dumped_.00401B14
  00401B0F    |>  B8 01000000   mov eax,1
  00401B14    |>  5B            pop ebx
  00401B15    |.  881D 34384000 mov byte ptr ds:[403834],bl
  00401B1B    |.  C9            leave
  00401B1C    \.  C2 0400       retn 4
  

  
  再到00401CD8处,同样到段首下断:
  


  00401C8D    /$  55            push ebp         //F2下断
  00401C8E    |.  8BEC          mov ebp,esp
  00401C90    |.  68 8E394000   push Dumped_.0040398E
  00401C95    |.  6A 20         push 20
  00401C97    |.  68 6C374000   push Dumped_.0040376C
  00401C9C    |.  E8 F3FDFFFF   call Dumped_.00401A94
  00401CA1    |.  68 C0394000   push Dumped_.004039C0
  00401CA6    |.  6A 20         push 20
  00401CA8    |.  68 34384000   push Dumped_.00403834
  00401CAD    |.  E8 E2FDFFFF   call Dumped_.00401A94
  00401CB2    |.  BF 8E394000   mov edi,Dumped_.0040398E
  00401CB7    |.  BE C0394000   mov esi,Dumped_.004039C0
  00401CBC    |.  B9 20000000   mov ecx,20
  00401CC1    |.  FC            cld
  00401CC2    |.  F3:A6         repe cmps byte ptr es:[edi],byte ptr ds:[e>
  00401CC4    |.  75 0F         jnz short Dumped_.00401CD5
  00401CC6    |.  FF75 08       push dword ptr ss:[ebp+8]
  00401CC9    |.  E8 39FFFFFF   call Dumped_.00401C07
  00401CCE    |.  B8 01000000   mov eax,1
  00401CD3    |.  EB 0A         jmp short Dumped_.00401CDF
  00401CD5    |>  FF75 08       push dword ptr ss:[ebp+8]
  00401CD8    |.  E8 61FEFFFF   call Dumped_.00401B3E
  00401CDD    |.  33C0          xor eax,eax
  00401CDF    |>  C9            leave
  00401CE0    \.  C2 0400       retn 4
  

  
  下好这两个断点后,我们就可以继续了,确定错误窗口后,重新输入一个假码,然后确定,中断在了:
  00401AD6    /$  55            push ebp         //F2下断
  我们F8单步:
  


  00401AE9    |.  6A 00         push 0
  00401AEB    |.  6A 04         push 4
  00401AED    |.  68 30384000   push Dumped_.00403830                      ;  ASCII "1234"
  00401AF2    |.  E8 19FEFFFF   call Dumped_.00401910                      ;  这里开始取假码的前4位
  

  
  跟进去一看,一个循环,通过查表取值,然后进行XOR运算,得到的值保存到EAX
  


  00401910    /$  55            push ebp
  00401911    |.  8BEC          mov ebp,esp
  00401913    |.  56            push esi
  00401914    |.  8B45 10       mov eax,dword ptr ss:[ebp+10]
  00401917    |.  8B4D 0C       mov ecx,dword ptr ss:[ebp+C]
  0040191A    |.  83F0 FF       xor eax,FFFFFFFF
  0040191D    |.  85C9          test ecx,ecx
  0040191F    |.  8B75 08       mov esi,dword ptr ss:[ebp+8]
  00401922    |.  74 15         je short Dumped_.00401939
  00401924    |>  3206          /xor al,byte ptr ds:[esi]
  00401926    |.  0FB6D0        |movzx edx,al
  00401929    |.  C1E8 08       |shr eax,8
  0040192C    |.  8B1495 283240>|mov edx,dword ptr ds:[edx*4+403228]       ;  查表取值
  00401933    |.  46            |inc esi
  00401934    |.  33C2          |xor eax,edx
  00401936    |.  49            |dec ecx
  00401937    |.^ 75 EB         \jnz short Dumped_.00401924
  00401939    |>  83F0 FF       xor eax,FFFFFFFF
  0040193C    |.  5E            pop esi
  0040193D    |.  C9            leave
  0040193E    \.  C2 0C00       retn 0C
  

  
  计算返回后,就来到了一个关键的比较处了:
  


  00401AF7    |.  8B1D 11324000 mov ebx,dword ptr ds:[403211]              ;  取一个固定的值
          ds:[00403211]=89EB6EA5
  00401AFD    |.  0FCB          bswap ebx                                  ;  逆转一下
          //逆转后得到:A56EEB89
  00401AFF    |.  3BC3          cmp eax,ebx                                ;  然后开始与上面取得的值比较
  00401B01    |.  74 0C         je short Dumped_.00401B0F                  ;  不相等再出错
  

  
  爆破的话,就只需要把 je short Dumped_.00401B0F 改成 jmp short Dumped_.00401B0F 了,呵呵!
  我这里先爆了,修改之后,F9运行,又来到了第2个断点处:
  00401C8D    /$  55            push ebp         //F2下断
  
  继续F8单步吧,没几下,出现一个字符串:
  ASCII “017341B-1D1E518-9DDE3AB-EADCC91C”
  


  00401C97    |.  68 6C374000   push Dumped_.0040376C                      ;  ASCII "017341B-1D1E518-9DDE3AB-EADCC91C"
  00401C9C    |.  E8 F3FDFFFF   call Dumped_.00401A94
  00401CA1    |.  68 C0394000   push Dumped_.004039C0                      ;  ASCII "50B594E2B5C0234FD98240F2F2F9ABCD"
  

  
  这里的call Dumped_.00401A94
  其实就是一个简单的MD5加密了,所以注册码的后32位就是对应的ASCII “017341B-1D1E518-9DDE3AB-EADCC91C”
  就OK了,至于这个这个字符串如何得来,我没有继续分析了!
  
  然后取假码的后32位(我这里明显不够,呵呵):
  


  00401CA1    |.  68 C0394000   push Dumped_.004039C0
  00401CA6    |.  6A 20         push 20
  00401CA8    |.  68 34384000   push Dumped_.00403834                      ;  ASCII "5678901234afdsf"
  00401CAD    |.  E8 E2FDFFFF   call Dumped_.00401A94
  

  
  运算得出上个字符串,然后与上面运算得出的字符串,进行比较,
  


  00401CB2    |.  BF 8E394000   mov edi,Dumped_.0040398E                   ;  ASCII "50B594E2B5C0234FD98240F2F2F9ABCD"
  00401CB7    |.  BE C0394000   mov esi,Dumped_.004039C0                   ;  ASCII "5E8C523F88968DA0BAE6EBF3073315F9"
  00401CBC    |.  B9 20000000   mov ecx,20
  00401CC1    |.  FC            cld
  00401CC2    |.  F3:A6         repe cmps byte ptr es:[edi],byte ptr ds:[e>  //这里按位比较
  00401CC4    |.  75 0F         jnz short Dumped_.00401CD5                   //不等就OVER了
  

  
  我这里爆破,直接将jnz short Dumped_.00401CD5给NOP掉,呵呵
  F9运行,就出现正确的对话框了!
  
——————————————————————————–
【经验总结】
  
  这个CM的关键之处在于:
  1、前4位的获取算法,如何逆向运算?
  2、那个字符串是如何得来??其实这个字符串,也是通过一个MD5运算得来的,呵呵
  
——————————————————————————–
【版权声明】: 转载请注明作者并保持文章的完整, 谢谢!

                                                       2009年01月28日 21:04:00

Crackme.rar

发表评论