【破文标题】Crackme 01 的详解
【难度级别】初入门的新手
【下载地址】
【破解工具】OD,peid
【加壳方式】无壳
【保护方式】无Anti-debug
【破解声明】本人破解很菜,此CrackMe算是入门级的,希望以此作为一些简单的案例,给我室友以及才开始接触逆向的各位兄弟,希望大家有所收获,如果不出意外这是一个长期的学习笔记,请大家多多指教。
【备 注】老手勿看
首先用PEiD载入目标文件,发现时masm编写,米有壳。接着用OD载入,来到入口处。右键选择"超级字符串参考",然后选择"查找ASCII",这是很经典的一个方法,如图:
发现了很多有用的信息,看来作者没有将这些信息加密处理,算是比较温柔的,从这些信息中我们可以推测用户名的长度应该是5-32位,我们测试之后发现是正确的,看来作者的信息无误,值得信任。好了,接下来我们需要定位到关键的算法处,方法有很多种,在接下来的CrackMe中我们会逐一学习。我们双击"Good Cracker",我们来到0x004013A8处,我们发现这里有一系列的MessageBox,这些都是用来给用户作为提示信息的,我们来到0x004013A6,左键点击这一行,我们发现有条红色的箭头指向这一行,顺,着这条线往上走,我们来到0x0040131F,这里是个JE指令,看来这是最后的迈向成功的跳转处,那么这里已经进入算法部分了,我们往上走发现了重要的API:GetDlgItemText,这个函数的作用是获取用户输入的用户名和密码,好了现在我们就从第一个API调用开始分析算法吧。
首先我们来看对用户名的处理:
00401248 |. 6A 28 PUSH 28 ; /Count = 28 (40.)
0040124A |. 68 8C314000 PUSH d2k2_cra.0040318C ; |Buffer = d2k2_cra.0040318C
0040124F |. 6A 02 PUSH 2 ; |ControlID = 2
00401251 |. FF75 08 PUSH DWORD PTR SS:[EBP+8] ; |hWnd
00401254 |. E8 8F010000 CALL <JMP.&USER32.GetDlgItemTextA> ; \GetDlgItemTextA
00401259 |. 84C0 TEST AL,AL ; 0x40318c存放输入的用户名
0040125B |. 0F84 06010000 JE d2k2_cra.00401367
00401261 |. 3C 20 CMP AL,20
00401263 |. 0F8F 13010000 JG d2k2_cra.0040137C ; 如果长度大于32就退出
00401269 |. 3C 05 CMP AL,5
0040126B |. 0F8C 20010000 JL d2k2_cra.00401391 ; 如果长度小于5也退出
00401271 |. 8D1D 8C314000 LEA EBX,DWORD PTR DS:[40318C]
00401277 |. 33C9 XOR ECX,ECX
00401279 |. B0 05 MOV AL,5 ; 用户名的前5个字符,AL依次减1
0040127B |. 33D2 XOR EDX,EDX
0040127D |> 8A0C1A MOV CL,BYTE PTR DS:[EDX+EBX] ; 依次取用户名的前5个字符,存放在CL里面(后面对CL进行操作)
00401280 |. 80F1 29 XOR CL,29 ; 与0x29异或
00401283 |. 02C8 ADD CL,AL ; 加上al
00401285 |. 80F9 41 CMP CL,41 ; 如果小于0x41
00401288 |. 7C 1C JL SHORT d2k2_cra.004012A6
0040128A |. 80F9 5A CMP CL,5A
0040128D |. 7F 17 JG SHORT d2k2_cra.004012A6 ; 如果大于0x5A
0040128F |> 888A 3C314000 MOV BYTE PTR DS:[EDX+40313C],CL ; 将处理之后的字符值放入0x40313C首地址中(数组)
00401295 |. C682 3D314000>MOV BYTE PTR DS:[EDX+40313D],0 ; 下一个将要放入的地址清0(C语言中数组的结束符'\0')
0040129C |. FEC2 INC DL ; DL增加,指向下一个字符
0040129E |. FEC8 DEC AL ; AL减1(循环体执行一次)
004012A0 |. 3C 00 CMP AL,0 ; 判断前5个字符是否处理完毕
004012A2 |. 74 08 JE SHORT d2k2_cra.004012AC
004012A4 |.^ EB D7 JMP SHORT d2k2_cra.0040127D
004012A6 |> B1 52 MOV CL,52 ; CL为0x52
004012A8 |. 02C8 ADD CL,AL ; 加上AL
004012AA |.^ EB E3 JMP SHORT d2k2_cra.0040128F ; 进过初步处理的前5个字符放在0x40313C
004012AC |> 33D2 XOR EDX,EDX
004012AE |. B8 05000000 MOV EAX,5 ; 同样是用户名的前5个字符
004012B3 |> 8A0C1A MOV CL,BYTE PTR DS:[EDX+EBX] ; 依次取用户名的前5个字符
004012B6 |. 80F1 27 XOR CL,27 ; 与0x27异或
004012B9 |. 02C8 ADD CL,AL ; 加上Al
004012BB |. 80C1 01 ADD CL,1 ; 加上1
004012BE |. 80F9 41 CMP CL,41 ; 如果小于0x41
004012C1 |. 7C 1C JL SHORT d2k2_cra.004012DF
004012C3 |. 80F9 5A CMP CL,5A
004012C6 |. 7F 17 JG SHORT d2k2_cra.004012DF ; 如果大于0x5A
004012C8 |> 888A 41314000 MOV BYTE PTR DS:[EDX+403141],CL ; 处理完毕后放入0x403141首地址中(注意141-13c=5!意味着与前面处理之后的5个字符恰好"相连")
004012CE |. C682 42314000>MOV BYTE PTR DS:[EDX+403142],0 ; 下一个将要放入的地址清0(C语言中数组的结束符'\0')
004012D5 |. FEC2 INC DL ; DL增加,指向下一个字符
004012D7 |. FEC8 DEC AL
004012D9 |. 3C 00 CMP AL,0
004012DB |. 74 08 JE SHORT d2k2_cra.004012E5 ; 判断处理完毕否
004012DD |.^ EB D4 JMP SHORT d2k2_cra.004012B3
004012DF |> B1 4D MOV CL,4D ; CL为0x4D
004012E1 |. 02C8 ADD CL,AL
004012E3 |.^ EB E3 JMP SHORT d2k2_cra.004012C8 ; 处理完毕之后的5个字符放在0x403141
004012E5 |> 33C0 XOR EAX,EAX
if (strlen(str_name) < 5 || strlen(str_name) > 32)
{
break;
}
for(var_1 = 5, var_2 = 0, var_1 > 0, var_1--,var_2++)
{
var_3 = var_1 + str_name[var_2] ^ 0x29;
if (var_3 < 0x41 || var_3 > 0x5a)
{
var_3 = var_1 + 0x52;
}
str_name_temp[var_2] = var_3;
}
for (var_4 = 5, var_5 = 0, var_4 > 0, var_4--,var_5++)
{
var_6 = var_4 + str_name[var_5] ^ 0x27 + 1;
if(var_6 < 0x41 || var_6 > 0x5a)
{
var_6 = var_4 + 0x4d;
}
str_name_temp[var_5+5] = var_6;
}
004012E7 |. 6A 28 PUSH 28 ; /Count = 28 (40.)
004012E9 |. 68 B4314000 PUSH d2k2_cra.004031B4 ; |Buffer = d2k2_cra.004031B4
004012EE |. 6A 04 PUSH 4 ; |ControlID = 4
004012F0 |. FF75 08 PUSH DWORD PTR SS:[EBP+8] ; |hWnd
004012F3 |. E8 F0000000 CALL <JMP.&USER32.GetDlgItemTextA> ; \GetDlgItemTextA
004012F8 |. 66:85C0 TEST AX,AX ; 密码放在0x4031B4
004012FB |. 74 55 JE SHORT d2k2_cra.00401352 ; 长度为空失败
004012FD |. 66:83F8 0A CMP AX,0A
00401301 |. 7F 4F JG SHORT d2k2_cra.00401352 ; 长度大于10,失败
00401303 |. 7C 4D JL SHORT d2k2_cra.00401352 ; 长度小于10,失败
00401305 |. 33C0 XOR EAX,EAX
00401307 |. 33DB XOR EBX,EBX
00401309 |. 33C9 XOR ECX,ECX
0040130B |. 33D2 XOR EDX,EDX
0040130D |. 8D05 B4314000 LEA EAX,DWORD PTR DS:[4031B4]
00401313 |> 8A1C01 MOV BL,BYTE PTR DS:[ECX+EAX] ; 依次取出输入的密码
00401316 |. 8A91 3C314000 MOV DL,BYTE PTR DS:[ECX+40313C] ; 依次取出之前处理完毕的10个字符,放入DL中
0040131C |. 80FB 00 CMP BL,0
0040131F |. 0F84 81000000 JE d2k2_cra.004013A6 ; 这条语句为真,注册成功
00401325 |. 80C2 05 ADD DL,5 ; DL加5
00401328 |. 80FA 5A CMP DL,5A
0040132B |. 7F 14 JG SHORT d2k2_cra.00401341 ; 如果大于0x5A
0040132D |> 80F2 0C XOR DL,0C ; 与0xc异或
00401330 |. 80FA 41 CMP DL,41
00401333 |. 7C 11 JL SHORT d2k2_cra.00401346 ; 如果小于0x41
00401335 |. 80FA 5A CMP DL,5A
00401338 |. 7F 12 JG SHORT d2k2_cra.0040134C ; 如果大于0x5A
0040133A |> 41 INC ECX
0040133B 38DA CMP DL,BL ; 两者必须相等
0040133D ^ 74 D4 JE SHORT d2k2_cra.00401313
0040133F EB 11 JMP SHORT d2k2_cra.00401352 ; 否者失败
00401341 |> 80EA 0D SUB DL,0D
00401344 |.^ EB E7 JMP SHORT d2k2_cra.0040132D
00401346 |> B2 4B MOV DL,4B
00401348 |. 02D1 ADD DL,CL
0040134A |.^ EB EE JMP SHORT d2k2_cra.0040133A
0040134C |> B2 4B MOV DL,4B
0040134E |. 2AD1 SUB DL,CL
00401350 |.^ EB E8 JMP SHORT d2k2_cra.0040133A
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)