标 题: 初级 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环境下编译通过,需要请下载,谢谢~
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!