首页
社区
课程
招聘
[原创]riijj-CrackMe1分析+注册机
发表于: 2012-5-14 22:56 8751

[原创]riijj-CrackMe1分析+注册机

2012-5-14 22:56
8751

标 题: 初级 crackme (入门级)的详解
作 者: riijj
时 间: 2004-05-17, 21:48:48
链 接: http://bbs.pediy.com/showthread.php?t=984&highlight=riijj

【破文标题】crackme (入门级)的详解
【对    象】初级新手
【下载地址】http://bbs.pediy.com/upload/files/1084801702.zip
【破解工具】OD
【保护方式】序号
【任    务】分析算法,找出序号,写出注册机
【破文作者】AJISky
【破解声明】破解功力有限,CM2没有分析出来,所以把CM1分析结果贴出,缓解下情绪……
【备    注】老手勿看
【破解过程】如下
一、废话
二、CM分析
三、写注册机

一、废话

    首先,注意riijj已经很久了,经常在CrackMe<>ReverseMe板块逛得大家都对他都很熟悉,并且出的CrackMe系列已将近二十了,难度逐渐增大也是可想而知,如果能够将他的这些CrackMe一一攻破,那逆向上的功力也会有不小的飞跃。最近在调他的CrackMe2,已经近一周了。我想说riijj你的CM2难度很大,算法基本清楚了,可是徒有算法最终的DLL文件很难解析出来,否则04年的这个CM竟然至今未见破文。真不甘心跳过这个CM。另外,今天有幸坛主发了面试邀请,于是兴起发破文一篇。希望明天带来好运~

二、CM分析
     同样,OD载入程序,
00401368 >/$  55            PUSH EBP                                                  ;停在此指令处
00401369  |.  8BEC         MOV EBP,ESP
0040136B  |.  6A FF         PUSH -1
0040136D  |.  68 E8404000   PUSH ncrackme.004040E8
00401372  |.  68 9C1E4000   PUSH ncrackme.00401E9C           ;  SE 处理程序安装
00401377  |.  64:A1 0000000> MOV EAX,DWORD PTR FS:[0]
0040137D  |.  50            PUSH EAX
0040137E  |.  64:8925 00000> MOV DWORD PTR FS:[0],ESP
00401385  |.  83EC 58       SUB ESP,58
00401388  |.  53            PUSH EBX
00401389  |.  56            PUSH ESI
0040138A  |.  57            PUSH EDI
0040138B  |.  8965 E8           MOV DWORD PTR SS:[EBP-18],ESP
0040138E  |.  FF15 44404000 CALL DWORD PTR DS:[<&KERNEL32.GetVersion>;  kernel32.GetVersion
……………….
首先快捷键CTRL+N看下调用的函数,(运气不错~,果真是初级唉)发现有GetDlgItemTextA,那好光标移到该函数上点击右键选择“在每个参考上设置断点”,(上图无法显示请原谅)
这时已经在该函数上下好断点了,可以选择工具栏中的B按钮(标红处)查看断点位置
这时可以F9运行下看看是否可以断下,运行后弹出对话框,
分别在
RegName中输入12345678
RegKey中输入ABCDEFGHIJ
点击注册按钮后程序果然被中断(上图无法显示请原谅)
这个时候就可以单步来跟踪程序了,按F8单步执行,可以在GetDlgItemTextA执行前,EAX执行接受字符串缓冲区地址,可以通过将光标移到 EAX指示的地址0013FB94(每个机子不一样)点击右键选择数据窗口中跟随,来观察调用函数后取到RegName框中输入的内容是否一致,字符长度由EAX寄存器返回。
(上图无法显示请原谅)
发现地址中是输入的内容
0013FB94  31 32 33 34 35 36 37 38 00 02 00 00 03 00 00 00  12345678. .. ...
下面开始具体分析算法主要有三部分:
第一部分:
0040123F  |.  8B35 94404000 MOV ESI,DWORD PTR DS:[<&USER32.GetDlgItemTextA>]    ;  USER32.GetDlgItemTextA
00401245  |.  6A 10         PUSH 10                    ; /Count = 10 (16.)
00401247  |.  50            PUSH EAX                  ; |Buffer
00401248  |.  68 E8030000   PUSH 3E8                   ; |ControlID = 3E8 (1000.)
0040124D  |.  51            PUSH ECX                 ; |hWnd => 00140438 (class='#32770',parent=000D0554)
0040124E  |.  33DB          XOR EBX,EBX              ; |
00401250  |.  FFD6          CALL ESI                    ; \GetDlgItemTextA ;取RegName内容
00401252  |.  83F8 03       CMP EAX,3                        ;EAX返回长度;当长度小于等于3时错误
00401255  |.  73 0B         JNB SHORT ncrackme.00401262  ;退出,否则跳转到00401262继续执行
00401257  |.  5E            POP ESI
00401258  |.  B8 01000000   MOV EAX,1
0040125D  |.  5B            POP EBX
0040125E  |.  83C4 30       ADD ESP,30
00401261  |.  C3            RETN
00401262  |>  A1 BC564000   MOV EAX,DWORD PTR DS:[4056BC]
00401267  |.  8D5424 28     LEA EDX,DWORD PTR SS:[ESP+28]
0040126B  |.  6A 10         PUSH 10
0040126D  |.  52            PUSH EDX
0040126E  |.  68 E9030000   PUSH 3E9
00401273  |.  50            PUSH EAX                                  ;再次调用\GetDlgItemTextA
00401274  |.  FFD6          CALL ESI                                  ;取RegKey内容
00401276  |.  0FBE4424 08   MOVSX EAX,BYTE PTR SS:[ESP+8] ;取RegName第一个字符
0040127B  |.  0FBE4C24 09   MOVSX ECX,BYTE PTR SS:[ESP+9] ;取RegName第二个字符
00401280  |.  99            CDQ                                                      ;清DX寄存器
00401281  |.  F7F9          IDIV ECX                                              ;第一个字符除以第二个
00401283  |.  8BCA          MOV ECX,EDX                                   ; 取余数
00401285  |.  83C8 FF       OR EAX,FFFFFFFF                              ;置EAX=FFFFFFFFH
00401288  |.  0FBE5424 0A   MOVSX EDX,BYTE PTR SS:[ESP+A] ;取第三个字符
0040128D  |.  0FAFCA        IMUL ECX,EDX                                 ;余数乘以第三个字符
00401290  |.  41            INC ECX                                              ;乘积再加一
00401291  |.  33D2          XOR EDX,EDX                                      ;清EDX
00401293  |.  F7F1          DIV ECX                                        ;全F即EAX除以加一后的结果
00401295  |.  50            PUSH EAX                                                       
00401296  |.  E8 A5000000   CALL ncrackme.00401340          ;  结果存起来
0040129B  |.  83C4 04       ADD ESP,4
0040129E  |.  33F6          XOR ESI,ESI
子过程00401340:的具体内容看下
00401340  /$  8B4424 04     MOV EAX,DWORD PTR SS:[ESP+4]               
00401344  |.  A3 AC504000   MOV DWORD PTR DS:[4050AC],EAX ;结果保存到变量中
00401349  \.  C3            RETN
总结下以上操作
步骤一(1)R1=FFFFFFFF / ((RegName.1 MOD RegName.2)* RegName.3+1)
具体就是得到多次运算结果R1值参与后续运算

好的继续第二部分:
004012A0  |> /E8 A5000000   /CALL ncrackme.0040134A   ;具体分析如下
004012A5  |. |99            |CDQ                                         ;清EDX
004012A6  |. |B9 1A000000   |MOV ECX,1A                                 
004012AB  |. |F7F9          |IDIV ECX
004012AD  |. |80C2 41       |ADD DL,41                             ;R2除26余数+41H转换成字母
004012B0  |. |885434 18     |MOV BYTE PTR SS:[ESP+ESI+18],DL ;保存转换后结果
004012B4  |. |46            |INC ESI
004012B5  |. |83FE 0F       |CMP ESI,0F                             ;计算十五次得到十五个字母
004012B8  |.^\72 E6         \JB SHORT ncrackme.004012A0
子过程0040134A功能如下:
0040134A  /$  A1 AC504000   MOV EAX,DWORD PTR DS:[4050AC] ;取结果R1
0040134F  |.  69C0 FD430300 IMUL EAX,EAX,343FD                      ;R1乘以343FD
00401355  |.  05 C39E2600   ADD EAX,269EC3                             ;再加上269EC3
0040135A  |.  A3 AC504000   MOV DWORD PTR DS:[4050AC],EAX  ;保存R1设R2=R1
0040135F  |.  C1F8 10       SAR EAX,10                                          ;R2右移16位
00401362  |.  25 FF7F0000   AND EAX,7FFF                                   ;R2于7FFF相与
00401367  \.  C3            RETN
总结下第二部分
For(i=0; i<15; i++)
{
步骤二(2)R1=(R1*343FDH)+269EC3H
步骤三 (3)  R2=R1
步骤四 (4)  R3=[(R2>>10H)&7FFFH MOD 1AH ]+ 41H
步骤五 (5)  R3保存到数组Num[i]
}
具体就是得到多次运算结果R1值和15个字符(无具体用处)
第三部分
004012BB  |.  8D7C24 0C     LEA EDI,DWORD PTR SS:[ESP+C]
004012BF  |.  83C9 FF       OR ECX,FFFFFFFF
004012C2  |.  33C0          XOR EAX,EAX
004012C4  |.  33F6          XOR ESI,ESI
004012C6  |.  F2:AE         REPNE SCAS BYTE PTR ES:[EDI]
004012C8  |.  F7D1          NOT ECX
004012CA  |.  49            DEC ECX
004012CB  |.  74 59         JE SHORT ncrackme.00401326
以上代码无实际意义,再次计算RegName长度
关键算法如下:
004012CD  |> /8A4434 0C    /MOV AL,BYTE PTR SS:[ESP+ESI+C]  ;取RegName第i字符
004012D1  |. |C0F8 05       |SAR AL,5                                                ;右移5位
004012D4  |. |0FBEC0        |MOVSX EAX,AL                                        ;结果放入EAX
004012D7  |. |8D1480        |LEA EDX,DWORD PTR DS:[EAX+EAX*4];EDX=5*EAX
004012DA  |. |8D04D0        |LEA EAX,DWORD PTR DS:[EAX+EDX*8] ;EAX=EAX+EDX*8
004012DD  |. |8D0440        |LEA EAX,DWORD PTR DS:[EAX+EAX*2] ; EAX=EAX+2*EAX
004012E0  |. |85C0          |TEST EAX,EAX                                   ;即:123EAX
004012E2  |. |7E 0A         |JLE SHORT ncrackme.004012EE           ;EAX小于等于0则跳转
004012E4  |. |8BF8          |MOV EDI,EAX                                   ;否则执行
004012E6  |> |E8 5F000000   |/CALL ncrackme.0040134A        ;执行一次步骤二
004012EB  |. |4F            ||DEC EDI                                           ;EAX减一
004012EC  |.^|75 F8         |\JNZ SHORT ncrackme.004012E6           ;不为零循环执行步骤二
004012EE  |> |E8 57000000   |CALL ncrackme.0040134A           ;为零时再执行一次步骤二
004012F3  |. |99            |CDQ                                                   ;且执行步骤三、四清EDX
004012F4  |. |B9 1A000000   |MOV ECX,1A                                   ;ECX=1AH
004012F9  |. |8D7C24 0C     |LEA EDI,DWORD PTR SS:[ESP+C]               
004012FD  |. |F7F9          |IDIV ECX                                                ;R3除以1AH
004012FF  |. |0FBE4C34 2C   |MOVSX ECX,BYTE PTR SS:[ESP+ESI+2C]  ;取RegKey.i
00401304  |. |80C2 41        |ADD DL,41                              ;相除结果取余数+41H
00401307  |. |0FBEC2        |MOVSX EAX,DL
0040130A  |. |2BC1          |SUB EAX,ECX                           ;结果减去text2.i
0040130C  |. |885434 1C     |MOV BYTE PTR SS:[ESP+ESI+1C],DL  ;存储相减结果
00401310  |. |99            |CDQ                                                        ;EDX始终为0
00401311  |. |33C2          |XOR EAX,EDX                                 ;计算忽略
00401313  |. |83C9 FF       |OR ECX,FFFFFFFF
00401316  |. |2BC2          |SUB EAX,EDX                                ;计算忽略
00401318  |. |03D8          |ADD EBX,EAX                                ;EBX+EAX
0040131A  |. |33C0          |XOR EAX,EAX
0040131C  |. |46            |INC ESI
0040131D  |. |F2:AE         |REPNE SCAS BYTE PTR ES:[EDI]
0040131F  |. |F7D1          |NOT ECX
00401321  |. |49            |DEC ECX
00401322  |. |3BF1          |CMP ESI,ECX                              ;计算RegName长度次
00401324  |.^\72 A7         \JB SHORT ncrackme.004012CD
最终得到EBX=0则注册成功
总结下以上步骤
                For (i=0; i<Len(RegName); i++)
               {
步骤六(6)If (RegName.i>>5)*123 <= 0
     
           Elseif
步骤七(7) For(a=0; a< (RegName.i>>5)*123; a++)
                {
                    步骤二
                 }
步骤八 (8)   步骤二
                    步骤三
                    步骤四
                    R3-RegKey.i+EBX
                 }
最终结果将EBX赋值给EAX返回,如果EAX为0则注册成功可知EBX=0则R3=RegKey.i
所以将每次计算的结果R3保存到一个数组中,最终数组内容即为RegKey值。
三、注册机
分析出算法后可以试着写注册机了关键代码如下:
;########################################################################
CalRegKey         Proc
        INVOKE GetDlgItemText,hWnd,IDC_EDT1,ADDR szText1,255
        LEA         ESI, szText1
        LEA        EDI, Num
        MOV         AL,BYTE PTR [ESI]
        MOV         BL,BYTE PTR [ESI+1]
        DIV         BL
        MOVZX         AX,AH
        MOV        BL, BYTE PTR [ESI+2]
        MUL        BL
        INC         AX
        MOVZX         EBX,  AX
        XOR         EAX, EAX
        DEC         EAX
        XOR         EDX, EDX
        DIV         EBX
        MOV         ECX, 0FH
        MOV        Temp1, EAX
@@:
        MOV        EAX, Temp1
        MOV         EBX, 343FDH
        MUL        EBX
        ADD         EAX, 269EC3H
        MOV         Temp1, EAX
        SHR        EAX, 10H
        AND        EAX, 7FFFH
        MOV        EBX, 1AH
        CDQ
        DIV        EBX
        ADD        DL, 41H
        MOV         BYTE PTR [EDI],DL
        INC         EDI
        LOOP        @B
        INVOKE lstrlen,ADDR szText1
        XCHG         EAX, ECX
        LEA        ESI, szText1
        LEA        EDI, Text2
@2:
        MOVZX        AX, BYTE PTR [ESI]
        SHR        AX, 5
        MOV        BL, 123
        MUL        BL
        CMP         AX, 0
        JBE        @F
        PUSH         CX
        MOV        CX, AX
@1:
        MOV        EAX, Temp1
        MOV         EBX, 343FDH
        MUL        EBX
        ADD         EAX, 269EC3H
        MOV         Temp1, EAX       
        LOOP        @1
        POP         CX
@@:       
        MOV        EAX, Temp1
        MOV         EBX, 343FDH
        MUL        EBX
        ADD         EAX, 269EC3H
        MOV         Temp1, EAX
        SHR        EAX, 10H
        AND        EAX, 7FFFH
        MOV        EBX, 1AH
        CDQ
        DIV        EBX
        ADD        DL, 41H
        MOV         BYTE PTR [EDI],DL
        INC         EDI
        ;MOV        BYTE PTR [Text2],DL
        INC         ESI
        LOOP         @2
        INVOKE        SetDlgItemText,hWnd,IDC_EDT2,ADDR Text2
        RET
CalRegKey Endp
附件为打包的注册机代码和程序,在RadAsm环境下编译通过,需要请下载,谢谢~


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

上传的附件:
收藏
免费 6
支持
分享
最新回复 (5)
雪    币: 35
活跃值: (139)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
2
占个沙发,分析得不错
2012-5-14 23:33
0
雪    币: 230
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
分析的很不错
2012-6-8 07:55
0
雪    币: 269
活跃值: (906)
能力值: ( LV12,RANK:345 )
在线值:
发帖
回帖
粉丝
4
多谢捧场
2012-6-14 22:24
0
雪    币: 358
活跃值: (104)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
学习了,不关注算法写注册机的话,断点设在40130A,记下每次F9后EAX的数值就OK
2013-12-28 16:11
0
雪    币: 17
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
学习下,

/* Note:Your choice is C IDE */
#include "stdio.h"
void main()
{   int R1,R2,i,a;
     char RegName[20];
printf("===============================\n");
printf("        Made by Crakme[cctv]   \n");
printf("===============================\n");
printf("Please Input Your Name: ");
gets(RegName);
R1=0xFFFFFFFF/((RegName[0] % RegName[1])* RegName[2]+1);
printf("The code is:");
for(i=0; i<15;i++)
{
R1=(R1*0x343FD)+0x269EC3;
}
for(i=0;i<strlen(RegName);i++)
{

if((RegName[i]>>5)*123<=0)
   {           
                   R1=(R1*0x343FD)+0x269EC3;
   }
else

{
for(a=0;a<(RegName[i]>>5)*123;a++)
                {
                      R1=(R1*0x343FD)+0x269EC3;  
                }
}

        R1=(R1*0x343FD)+0x269EC3;  
        R2=(((R1>>0x10)&0x7FFF) % 0x1A)+0x41;
       printf("%c",R2);
  }
}
2014-3-23 08:48
0
游客
登录 | 注册 方可回帖
返回
//