首页
社区
课程
招聘
[原创]fornix'2nd crackme,利用INT3混乱算法
发表于: 2006-8-27 07:52 7679

[原创]fornix'2nd crackme,利用INT3混乱算法

2006-8-27 07:52
7679

xTiNtxTiNt【文章标题】: fornix'2nd crackme,利用INT3混乱算法
【文章作者】: laomms
【软件名称】: fornix'2nd crackme
【软件大小】: 16K
【下载地址】: 附件
【加壳方式】: 无
【编写语言】: MASM
【使用工具】: OLLYDBG
【操作平台】: WINXP SP2
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
      这个CRACKME做的非常好,很灵活,防INT3断点,一旦检测到CC代码,就将关键的比较地方内存中正确的值进行修改,你永远都别想逆推到真的注册码。
  
  OD载入,下GetWindowTextA断点或者根据字符串参考很容易找到关键处:
  
  00401147   .  68 84324000   PUSH 00403284                            ;  断在这里
  0040114C   .  E8 D0000000   CALL 00401221                            ;  跟进这个CALL,其实这个CALL中的算法是迷惑人的,没有什么用
  
  ======================
  
  00401224  |.  8B75 08       MOV ESI,DWORD PTR SS:[EBP+8]             ;  注册码
  00401227  |>  803E 00       /CMP BYTE PTR DS:[ESI],0                 ;  是否为0
  0040122A  |.  74 0C         |JE 00401238
  0040122C  |.  8A06          |MOV AL,BYTE PTR DS:[ESI]                ;  逐个取注册码
  0040122E  |.  34 15         |XOR AL,15                               ;  异或15
  00401230  |.  C0C8 05       |ROR AL,5                                ;  循环右移5
  00401233  |.  8806          |MOV BYTE PTR DS:[ESI],AL                ;  放回DS:[ESI],计算的最终结果就在这里
  00401235  |.  46            |INC ESI                                 ;  ESI累加
  00401236  |.^ EB EF         \JMP 00401227
  00401238  |> \E8 04000000   CALL 00401241                            ;  检测断点
  0040123D  |.  C9            LEAVE
  0040123E  \.  C2 0400       RETN 4
  00401241  /$  8D3D 00104000 LEA EDI,DWORD PTR DS:[<ModuleEntryPoint>>;  入口地址401000装入EDI
  00401247  |.  B9 97020000   MOV ECX,297                              ;  ECX赋值297
  0040124C  |.  E8 45000000   CALL 00401296                            ;  CC装入AL
  00401251  |.  F2:AE         REPNE SCAS BYTE PTR ES:[EDI]             ;  重复操作
  比如断点设在00401147处,入口出处为00401000,则F8后,ECX=297-(00401147-00401000+1)=14F,当然你也可以在原地不停的按住F4,直到ECX=1后再按F8
  00401253  |.  85C9          TEST ECX,ECX                             ;  ECX是否为0,如果下了断点,这里的ECX是非0值
  00401255  |.  75 3E         JNZ 00401295                             ;  既然你下了断点,这里一定不能跳
  00401257  |.  8D05 9A124000 LEA EAX,DWORD PTR DS:[40129A]
  0040125D  |.  A3 7D324000   MOV DWORD PTR DS:[40327D],EAX
  00401262  |>  A1 7D324000   /MOV EAX,DWORD PTR DS:[40327D]
  00401267  |.  8B15 7D324000 |MOV EDX,DWORD PTR DS:[40327D]           
  0040126D  |.  833A 00       |CMP DWORD PTR DS:[EDX],0
  00401270  |.  74 14         |JE  00401286
  00401272  |.  8BC8          |MOV ECX,EAX
  00401274  |.  E8 1D000000   |CALL 00401296
  00401279  |.  3801          |CMP BYTE PTR DS:[ECX],AL
  0040127B  |.  74 18         |JE 00401295
  0040127D  |.  8305 7D324000>|ADD DWORD PTR DS:[40327D],6
  00401284  |.^ EB DC         \JMP 00401262
  00401286  |>  8A1D 40324000 MOV BL,BYTE PTR DS:[403240]              ;  DS:[00403240]=02
  0040128C  |.  FEC3          INC BL                                   ;  02+1
  0040128E  |.  881D 40324000 MOV BYTE PTR DS:[403240],BL              ;  放回DS:[403240]
  00401294  |.  C3            RETN
  00401295  \>  C3            RETN                                     ;  如果下了断,跳到这里直接返回
  
  
  
  
  
  ======================
  
  00401151   .  BF 20114000   MOV EDI,00401120
  00401156   .  83C7 0B       ADD EDI,0B
  00401159   .  BE 84324000   MOV ESI,00403284                         ;  可以看这里内存中的直接常数
  0040115E   .  B9 09000000   MOV ECX,9
  00401163   >  49            DEC ECX
  00401164   .  AC            LODS BYTE PTR DS:[ESI]                   ;  刚才计算后的的注册码
  00401165   .  AE            SCAS BYTE PTR ES:[EDI]                   ;  与寄存器ES:[EDI]中的各个值对比
  00401166   .^ 74 FB         JE 00401163                              ;  没有跳
  00401168   .  8BC1          MOV EAX,ECX
  0040116A   .  C9            LEAVE
  0040116B   .  C2 0400       RETN 4                                   ;  返回
  
  
  
  004010B0   .  0BC0          OR EAX,EAX                               ;  EAX是否为0
  004010B2   .  75 14         JNZ 004010C8                             ;  这个得让它跳,作者在这里开了个玩笑,如果这里不跳成立,注册码为fuckolly,但事实上是错误的
  004010B4   .  68 33324000   PUSH 00403233                            ;  right serial
  004010B9   .  68 E8314000   PUSH 004031E8                            ;  you've done it. write a tutorial and send it to fornix@fusionrulez.cjb.net
  004010BE   .  FF75 08       PUSH DWORD PTR SS:[EBP+8]
  004010C1   .  E8 A8000000   CALL 0040116E                    
  004010C6   .  EB 12         JMP 004010DA
  004010C8   >  68 DB314000   PUSH 004031DB                            ;  wrong serial
  004010CD   .  68 B7314000   PUSH 004031B7                            ;  it's not so easy boy. keep tryin...
  004010D2   .  FF75 08       PUSH DWORD PTR SS:[EBP+8]
  004010D5   .  E8 94000000   CALL 0040116E                            ;  关键CALL,一定要跟入
  004010DA   >  EB 37         JMP 00401113
  
  =============================
  
  0040116E   $  55            PUSH EBP
  0040116F   .  8BEC          MOV EBP,ESP
  00401171   .  68 68324000   PUSH 00403268                            ; /lParam = 403268
  00401176   .  6A 14         PUSH 14                                  ; |wParam = 14
  00401178   .  6A 0D         PUSH 0D                                  ; |Message = WM_GETTEXT
  0040117A   .  68 EA030000   PUSH 3EA                                 ; |ControlID = 3EA (1002.)
  0040117F   .  FF75 08       PUSH DWORD PTR SS:[EBP+8]                ; |hWnd
  00401182   .  E8 49010000   CALL <JMP.&user32.SendDlgItemMessageA>   ; \SendDlgItemMessageA
  00401187   .  EB 08         JMP 00401191
  00401189   .  91            XCHG EAX,ECX
  0040118A   .  71 39         JNO 004011C5
  0040118C   .  A9 41112103   TEST EAX,3211141
  00401191   >  68 68324000   PUSH 00403268
  00401196   .  E8 66000000   CALL 00401201                            ;  跟进这个CALL,关键算法,可以用于做注册机
  
  =============================
  
  00401202  |.  8BEC          MOV EBP,ESP
  00401204  |.  8B75 08       MOV ESI,DWORD PTR SS:[EBP+8]             ;  注册码入ESI
  00401207  |>  803E 00       /CMP BYTE PTR DS:[ESI],0
  0040120A  |.  74 0C         |JE 00401218
  0040120C  |.  8A06          |MOV AL,BYTE PTR DS:[ESI]                ;  逐个取注册码ASCII
  0040120E  |.  34 41         |XOR AL,41                               ;  异或41H
  00401210  |.  C0C0 03       |ROL AL,3                                ;  循环左移3
  00401213  |.  8806          |MOV BYTE PTR DS:[ESI],AL                ;  放回DS:[ESI],循环完后这个段寄存器中放着最终的结果
  00401215  |.  46            |INC ESI                                 ;  ESI累加
  00401216  |.^ EB EF         \JMP 00401207
  00401218  |>  E8 24000000   CALL 00401241
  00401218  |> \E8 24000000   CALL 00401241
  0040121D  |.  C9            LEAVE
  0040121E  \.  C2 0400       RETN 4                                   ;  返回
  
  ================================
  
  0040119B   .  B8 05000000   MOV EAX,5                                ;  EAX赋值5
  004011A0   .  F625 40324000 MUL BYTE PTR DS:[403240]                 ;  乘DS:[403240]的值,这个值为4才是对的,如果有断点这里是0
  004011A6   .  BE 68324000   MOV ESI,00403268                         ;  正确的值放到ESI
  004011AB   .  BF 75114000   MOV EDI,00401175                         ;  刚才计算的结果
  004011B0   .  03F8          ADD EDI,EAX                              ;  关键就在EAX的值,EAX=14H是对的
  
  00401175  [00] 6A 14 6A 0D 68 EA 03 00 00 FF 75 08 E8 49 01  .jj.h?..?枭
  00401185  00 00 EB 08 [91] 71 39 A9 41 11 21 03 68 68 32 40  ..??9┝!hh2@
  这里的00401175处的00跟401189处的91正好差14H。
  
  004011B2   .  B9 09000000   MOV ECX,9                                ;  ECX=9
  004011B7   >  49            DEC ECX                                  ;  ECX=ECX-1.
  004011B8   .  AC            LODS BYTE PTR DS:[ESI]                   ;  这就是最终的结果
  004011B9   .  AE            SCAS BYTE PTR ES:[EDI]                   ;  与ES:[EDI]地址放的结果对比
  004011BA   .^ 74 FB         JE 004011B7                              ;  如果相等就循环判断下一位
  004011BC   .  0BC9          OR ECX,ECX
  004011BE   .  74 21         JE 004011E1                              ;  必须要跳,也就是循环8次后最终要相等
  004011C0   .  BF B6314000   MOV EDI,004031B6
  004011C5   >  BE DA314000   MOV ESI,004031DA
  004011CA   .  47            INC EDI
  004011CB   .  46            INC ESI
  004011CC   .  B8 C9124000   MOV EAX,004012C9
  004011D1   .  40            INC EAX
  004011D2   .  6A 10         PUSH 10                                  ; /Style = MB_OK|MB_ICONHAND|MB_APPLMODAL
  004011D4   .  56            PUSH ESI                                 ; |Title => "Wrong Serial"
  004011D5   .  57            PUSH EDI                                 ; |Text
  004011D6   .  FF75 08       PUSH DWORD PTR SS:[EBP+8]                ; |hOwner
  004011D9   .  FFD0          CALL EAX                                 ; \MessageBoxA
  004011DB   .  C9            LEAVE
  004011DC   .  C2 0400       RETN 4
  004011DF   .  EB 20         JMP 00401201
  004011E1   >  BF E7314000   MOV EDI,004031E7
  004011E6   .  BE 32324000   MOV ESI,00403232
  004011EB   .  47            INC EDI
  004011EC   .  46            INC ESI
  004011ED   .  90            NOP
  004011EE   .  B8 C9124000   MOV EAX,04012C9
  004011F3   .  40            INC EAX
  004011F4   .  6A 40         PUSH 40                                  ; /Style = MB_OK|MB_ICONASTERISK|MB_APPLMODAL
  004011F6   .  56            PUSH ESI                                 ; |Title => "Right Serial"
  004011F7   .  57            PUSH EDI                                 ; |Text => "You've Done it. Write a tutorial and send it to fornix@fusionrulez.cjb.net"
  004011F8   .  FF75 08       PUSH DWORD PTR SS:[EBP+8]                ; |hOwner
  004011FB   .  FFD0          CALL EAX                                 ; \MessageBoxA
  004011FD   .  C9            LEAVE
  004011FE   .  C2 0400       RETN 4
  
  
  
  
  关键在下面这处:
  004011B9   .  AE            SCAS BYTE PTR ES:[EDI]                   ;  这里的ES:[EDI]内存地址
  
  假如检测到CC,这里的内存地址就变成这里:
  00401175  00 6A 14 6A 0D 68 EA 03 00 00 FF 75 08 E8 49 01  .jj.h?..?枭
  而真正的地址应该在这里:
  00401189  91 71 39 A9 41 11 21 03 68 68 32 40 00 E8 66 00    ?9┝!hh2@.桄.
  
--------------------------------------------------------------------------------
【经验总结】
  那逆推注册码应该很简单了,直接将原来的那段变形代码逆向一下嵌入高级语言:
  
  function cacl(str: Byte): String;
  var
    a:Byte;
    b:Byte;
    s:string;
  begin
      a:= str;
      asm
      xor eax,eax
      mov al,a
      ror al,3
      xor al,$41
      mov b,al
      end;
      s:=chr(b);
      Result := s;
  end;
  
  procedure TForm1.Button1Click(Sender: TObject);
    begin
    Edit1.Text:=cacl($91)+cacl($71)+cacl($39)+cacl($A9)+cacl($41)+cacl($11)+cacl($21)+cacl($03);
    end;
  
  end.
  
  算出的注册码为softice!,作者还虚幻一招,用了假注册码fuckolly。
  
  
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!

                                                       2006年08月27日


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

上传的附件:
收藏
免费 7
支持
分享
最新回复 (3)
雪    币: 461
活跃值: (93)
能力值: ( LV9,RANK:1170 )
在线值:
发帖
回帖
粉丝
2
很精彩,支持楼主!
2006-8-27 10:00
0
雪    币: 433
活跃值: (176)
能力值: ( LV13,RANK:1250 )
在线值:
发帖
回帖
粉丝
3
Int3都算是很初级的调试方式了,单步,“运行到”这些技巧不掌握根本不算调试入门。
汇编的程序也就只能f**k下OD而已,IDA屠刀下去,五脏六腑全部揪出来……
2006-8-28 11:37
0
雪    币: 560
活跃值: (359)
能力值: ( LV13,RANK:1370 )
在线值:
发帖
回帖
粉丝
4
最初由 冲天剑 发布
Int3都算是很初级的调试方式了,单步,“运行到”这些技巧不掌握根本不算调试入门。
汇编的程序也就只能f**k下OD而已,IDA屠刀下去,五脏六腑全部揪出来……


学习了,IDA确实强大,平时只用来静态分析.可惜对它的动态调试了解不多,不过防Int3对于ring3级的一些调试器还是非常有效的.
2006-8-28 12:44
0
游客
登录 | 注册 方可回帖
返回
//