首页
社区
课程
招聘
[原创]我的第一个Crack Me 高手越过
发表于: 2008-3-27 16:44 6420

[原创]我的第一个Crack Me 高手越过

2008-3-27 16:44
6420
【文章标题】: 加密解密习题破文
【文章作者】: kanghtta
【作者邮箱】: kanghtta@hotmail.com
【作者主页】: http://kanghtta.cublog.cn
【作者QQ号】: 18381291
【软件名称】: echap511
【软件大小】:  4kb
【下载地址】: 加密解密第二版光盘
【加壳方式】:  无
【编写语言】: masm32
【使用工具】: peid ollyICE
【软件介绍】: 系列号保护
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
  
    大家好,这是我第一次写破文,(其实这样说蛮不好意思的,不过对于我这种菜鸟级的来说,也算是破文吧)
    见习题上是中等难度,虽然有答案,但还是自己练练。嘿嘿,多动手比光看代码好吧!
   
      首先,还是和通常一样,先运行下看看,点check  ,嘿嘿,有字串,Bad Serial ,Sorry!“ 算是看到点希望了,毕竟
    刚开始接触crack 。
       1, 用peid 察看,无壳,汇编语言编写,(怪不得短小精炼),由于在学动态分析,就用OD载入了。
       分析:
              由于是用masm32汇编编写的,嘿嘿,一开始就看到了熟悉的函数,GetModuleHandle,刚开始打算用字串参考,
    向下拉拉看,代码不长,就想自己来分析一下代码。
    00401070  |> \83F8 10       cmp     eax, 10
    00401073  |.  75 0C         jnz     short 00401081
    00401075  |.  6A 00         push    0                                ; /Result = 0; Case 10 (WM_CLOSE) of switch 0040104F
    00401077  |.  FF75 08       push    dword ptr [ebp+8]                ; |hWnd
    0040107A  |.  E8 F7000000   call              ; \EndDialog
    0040107F  |.  EB 3F         jmp     short 004010C0
    00401081  |>  3D 11010000   cmp     eax, 111
    00401086  |.  75 2F         jnz     short 004010B7
    00401088  |.  8B45 10       mov     eax, dword ptr [ebp+10]          ;  Case 111 (WM_COMMAND) of switch 0040104F
    0040108B  |.  66:3D B90B    cmp     ax, 0BB9
    0040108F  |.  75 2F         jnz     short 004010C0
    00401091  |.  C1E8 10       shr     eax, 10
    00401094  |.  66:0BC0       or      ax, ax
    00401097  |.  75 1C         jnz     short 004010B5
    00401099  |.  6A 0A         push    0A                               ; /Count = A (10.)
    0040109B  |.  68 44304000   push    00403044                         ; |Buffer = echap511.00403044
    004010A0  |.  68 B80B0000   push    0BB8                             ; |ControlID = BB8 (3000.)
    004010A5  |.  FF35 54304000 push    dword ptr [403054]               ; |hWnd = 00330266 ('Pusillus Crackme 1.0',class='#32770')
    004010AB  |.  E8 D2000000   call        ; \GetDlgItemTextA
    004010B0  |.  E8 14000000   call    004010C9
    004010B5  |>  EB 09         jmp     short 004010C0
    004010B7  |>  B8 00000000   mov     eax, 0                           ;  Default case of switch 0040104F
    004010BC  |.  C9            leave
    004010BD  |.  C2 1000       retn    10
   
    看004010AB处, GetDlgItemTextA函数,功能是获取和对话框关联的控件文本和标题。
    004010B0  |.  E8 14000000   call    004010C9  //猜测这个是关键,F7跟进,比较完了当然是验证了嘛。
   
   
    004010C9  /$  56            push    esi
    004010CA  |.  57            push    edi
    004010CB  |.  51            push    ecx
    004010CC  |.  33F6          xor     esi, esi
    004010CE  |.  33FF          xor     edi, edi
    004010D0  |.  B9 08000000   mov     ecx, 8
    004010D5  |.  BE 44304000   mov     esi, 00403044                    ;  ASCII "kanghtta"
    004010DA  |>  8036 32       /xor     byte ptr [esi], 32
    004010DD  |.  46            |inc     esi
    004010DE  |.^ E2 FA         \loopd   short 004010DA
    004010E0  |.  BE 44304000   mov     esi, 00403044                    ;  将输入和0x32异或运算 得ASCII "YS\UZFFS"
   
    004010E5  |.  B9 04000000   mov     ecx, 4
    004010EA  |>  8A06          /mov     al, byte ptr [esi]
    004010EC  |.  8A5E 01       |mov     bl, byte ptr [esi+1]
    004010EF  |.  32C3          |xor     al, bl
    004010F1  |.  8887 4C304000 |mov     byte ptr [edi+40304C], al
    004010F7  |.  83C6 02       |add     esi, 2
    004010FA  |.  47            |inc     edi
    004010FB  |.^ E2 ED         \loopd   short 004010EA
    004010FD  |.  BE 4C304000   mov     esi, 0040304C       ;将ASCII "YS\UZFFS"两两字符运算得4位存0040304C中
                                                             ; 0040304C数据为 0A 09 1C 15
    00401102  |.  8A06          mov     al, byte ptr [esi]
    00401104  |.  8A5E 01       mov     bl, byte ptr [esi+1]
    00401107  |.  32C3          xor     al, bl
    00401109  |.  8A5E 02       mov     bl, byte ptr [esi+2]
    0040110C  |.  8A4E 03       mov     cl, byte ptr [esi+3]
    0040110F  |.  32D9          xor     bl, cl
    00401111  |.  32C3          xor     al, bl                ;0A 09 1C 15两两异或后的结果在异或 存al =03
    00401113  |.  B9 08000000   mov     ecx, 8
   
    00401118  |.  BE 44304000   mov     esi, 00403044              
    0040111D  |>  3006          /xor     byte ptr [esi], al         ;将ASCII "YS\UZFFS"和al异或后存入
    0040111F  |.  46            |inc     esi
    00401120  |.^ E2 FB         \loopd   short 0040111D   
   
    00401122  |.  B9 08000000   mov     ecx, 8
    00401127  |.  BE 44304000   mov     esi, 00403044
    0040112C  |.  BF 08304000   mov     edi, 00403008               ;启0040303008的数据和运算后的比较
    00401131  |>  8A06          /mov     al, byte ptr [esi]
    00401133  |.  3A07          |cmp     al, byte ptr [edi]
    00401135      75 1D         jnz     short 00401154               ;不等则完蛋
    00401137  |.  46            |inc     esi
    00401138  |.  47            |inc     edi
    00401139  |.^ E2 F6         \loopd   short 00401131
     
      在这里的问题是如何知道00403008的数据呢? 很简单,信息窗口中:右键,数据窗口中跟随地址
   
    可以看到 :00403008  71 18 59 1B 79 42 45 4C                          qYyBEL
   
    可 这些数据是怎么来的呢?
          现在有两种推断,这些数据是程序运行时动态产生的呢 还是程序一开始就有的呢?
       ctrl+F2 重新载入  
   在数据窗口下内存写断点,不行,断不下来。猜测可能是静态数据。
      
       在反汇编窗口中右键:转到 表达式 输入  :00403008
    00403008   /71 18           jno     short 00403022
    0040300A   |59              pop     ecx
    0040300B   |1B79 42         sbb     edi, dword ptr [ecx+42]
    0040300E   |45              inc     ebp
    0040300F   |4C              dec     esp
   
   
     有没有见到机器码中的数据很熟悉呢?  原来是启3008后的4字节作为比较参数!
      嘿嘿。现在来看看这个注册的算法?
   
     1)从对话框中的编辑框控件中提取用户输入的字符串。
     2)将字符串中的每个字符和0x32作异或运算
     3)将异或运算得到的结果在两两运算,得到4位的结果
     4)将四位的结果两两异或,得到二位结果,
     5)在将4运算的结果异或,结果存al
     6)al和与0x32运算存入的字符串再次逐一异或运算。
     7)将6运算的结果和00403008中的数据比较,不等则完蛋。
   
     现在来算它的注册码: 由于00403008的数据固定,固写起来比较简单。
    #include
    void main()
    {
            char middle_1[4];
            char middle_2[2];
            char b[8]={0x71,0x18,0x59,0x1B,0x79,0x42,0x45,0x4C} ;
            middle_1[0]=b[0]^b[1];
            middle_1[1]=b[2]^b[3];
            middle_1[2]=b[4]^b[5];
            middle_1[3]=b[6]^b[7];
            cout<<middle_1[0]<<middle_1[1]<<middle_1[2]<<middle_1[3]<<endl;
            middle_2[0]=middle_1[0]^middle_1[1];
            middle_2[1]=middle_1[2]^middle_1[3];
            char al=middle_2[0]^middle_2[1];
            cout<<al<<endl;
            for(int i=0;i<=8;i++)
            {
                    b[i]=b[i]^al;
                    b[i]=b[i]^0x32;
                    cout<<b[i]<<' ';
            }               
    }
    Z3r0Ring 运行程序将Z3r0Ring输入
   
    Good work Cracker   哈哈。。。。成功!
   
   
   
   
  
--------------------------------------------------------------------------------
【经验总结】
    虽然比较简单,但当  
    Good work Cracker   出来时,仍然按捺不住心中的那种激动,如果自己能破的,就不要看别人的答案,实在没思路了,
  在参考,希望自己能在这条路上坚持下去。
     
     感谢看雪,让我入门。
   
  
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!

                                                       2008年03月27日 下午 04:42:42

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

上传的附件:
收藏
免费 0
支持
分享
最新回复 (10)
雪    币: 347
活跃值: (30)
能力值: ( LV9,RANK:420 )
在线值:
发帖
回帖
粉丝
2
沙发

不简单不简单

很好 很强大

学习了
2008-3-27 21:03
0
雪    币: 485
活跃值: (12)
能力值: ( LV9,RANK:490 )
在线值:
发帖
回帖
粉丝
3
学习并支持一下。
2008-3-27 21:05
0
雪    币: 420
活跃值: (77)
能力值: ( LV13,RANK:500 )
在线值:
发帖
回帖
粉丝
4
谢谢楼上鼓励 ,嘿嘿
     看来大半年的书,最近才开始慢慢的练练手.
上传的附件:
2008-3-28 17:18
0
雪    币: 43
活跃值: (116)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
不错不错。
偶是菜鸟,爆掉了。
2008-3-29 22:27
0
雪    币: 201
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
跟了下,算法简单,但是否只有一组KEY不确定。
用穷举试了下,果然只有一组。。。
#include<stdio.h>
#include<string.h>
void main()
{
        int i,j,C;
        char mid[10]={0};
        int        key[8]={0x71,0x18,0x59,0x1B,0x79,0x42,0x45,0x4C};
        for(i=0;i<=126;i++)
        {
                for(j=0;j<8;j++)
                {
                        mid[j]=i^key[j]^50;
                }
                C=mid[0]^mid[1]^mid[2]^mid[3]^mid[4]^mid[5]^mid[6]^mid[7];
                if(i==C)
                        printf("%s\n",mid);
        }
}
2008-3-30 20:26
0
雪    币: 201
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
又看了下,一组定数据0x71,0x18,0x59,0x1B,0x79,0x42,0x45,0x4C,
异或出的数是一定的,只有用户名逐个异或0x32后再一起异或与之相等方能PASS,
用户名又是定数据0x71,0x18,0x59,0x1B,0x79,0x42,0x45,0x4C和一个常数(异或数异或0x32)异或所得,所以只有一组。
其实异或0x32只是幌子,因为是同一个数又是偶次异或故无用,
只要用户名异或与定数据0x71,0x18,0x59,0x1B,0x79,0x42,0x45,0x4C异或的结果相等即可。
2008-3-30 21:00
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
Crack不了,一气之下爆破了。
2008-4-10 13:30
0
雪    币: 517
活跃值: (64)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
9
我来加注释
sn:ccbszhxd

004010C9  PUSH ESI
004010CA  PUSH EDI                                 ;  0x12FC18进栈;//EDI
004010CB  PUSH ECX                                 ;  0x77D3218C进栈;//ECX
004010CC  XOR ESI,ESI                              ;  ESI=0,CF=0;//自身xor运算结果为0,CF=0
004010CE  XOR EDI,EDI                              ;  EDI=0,CF=0;//自身xor运算结果为0,CF=0
004010D0  MOV ECX,8                                ;  ECX=0x8
004010D5  MOV ESI,403044                           ;  ASCII "CCBSZHXD"
004010DA  /XOR BYTE PTR DS:[ESI],32                ;  DS段[403044]=0x51;        //DS段[403044]=0x63^0x32   ("ccbszhxd")
004010DD  |INC ESI                                 ;  ESI=(0x403044)++   (字符串"Qcbszhxd")
004010DE  \LOOPD SHORT 004010DA                    ;  004010DA
004010E0  MOV ESI,403044                           ;  ASCII "QQPAHZJV"
004010E5  MOV ECX,4                                ;  ECX=0x4
004010EA  /MOV AL,BYTE PTR DS:[ESI]                ;  AL=0x51 ('Q');//DS段[403044];   (字符串"QQPAHZJV")
004010EC  |MOV BL,BYTE PTR DS:[ESI+1]              ;  BL=0x51 ('Q');//DS段[403045];   (字符串"QPAHZJV")
004010EF  |XOR AL,BL                               ;  AL=0x0;//AL=0x51^0x51
004010F1  |MOV BYTE PTR DS:[EDI+40304C],AL         ;  DS段[403F1C]=0x0;
004010F7  |ADD ESI,2                               ;  ESI=0x403046;//ESI=ESI+2;
004010FA  |INC EDI                                 ;  EDI=(0x0)++
004010FB  \LOOPD SHORT 004010EA                    ;  004010EA
004010FD  MOV ESI,40304C                           ;  ESI=0x40304C
00401102  MOV AL,BYTE PTR DS:[ESI]                 ;  AL=0x0;//DS段[40304C];
00401104  MOV BL,BYTE PTR DS:[ESI+1]               ;  BL=0x11;//DS段[40304D];
00401107  XOR AL,BL                                ;  AL=0x11;//AL=0x0^0x11
00401109  MOV BL,BYTE PTR DS:[ESI+2]               ;  BL=0x12;//DS段[40304E];
0040110C  MOV CL,BYTE PTR DS:[ESI+3]               ;  CL=0x1C;//DS段[40304F];
0040110F  XOR BL,CL                                ;  BL=0xE;//BL=0x12^0x1C
00401111  XOR AL,BL                                ;  AL=0x1F;//AL=0x11^0xE
00401113  MOV ECX,8                                ;  ECX=0x8
00401118  MOV ESI,403044                           ;  ASCII "QQPAHZJV"
0040111D  /XOR BYTE PTR DS:[ESI],AL                ;  DS段[403044]=0x4e;        //DS段[403044]=0x51^0x1F   ("QQPAHZJV")
0040111F  |INC ESI                                 ;  ESI=(0x403044)++   (字符串"NQPAHZJV")
00401120  \LOOPD SHORT 0040111D                    ;  0040111D
00401122  MOV ECX,8                                ;  ECX=0x8
00401127  MOV ESI,403044                           ;  ASCII "NNO^WEUI"
0040112C  MOV EDI,403008                           ;  EDI=0x403008   ("q")
00401131  /MOV AL,BYTE PTR DS:[ESI]                ;  AL=0x4E ('N');//DS段[403044];   (字符串"NNO^WEUI")
00401133  |CMP AL,BYTE PTR DS:[EDI]                ;  ZF=0;//DS段[403008]=0x71;AL=0x4e   ("q")
00401135  |JNZ SHORT 00401154                      ;  跳到00401154  //ZF=0   失败了!
2008-4-16 00:15
0
雪    币: 206
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
我才接触CrackMe不到一周的时间,下载下来模仿一下
2008-4-22 21:18
0
雪    币: 201
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
我在学习中,他们的经历就是最好的教程啊啊
2008-4-25 19:23
0
游客
登录 | 注册 方可回帖
返回
//