【破文标题】Crackme 02-04 的详解
【难度级别】初入门的新手
【下载地址】见附件(三个程序本身+注册机代码+注册机)
【破解工具】OD,peid
【加壳方式】无壳
【保护方式】无Anti-debug
【破解声明】本人破解很菜,此CrackMe算是入门级的,希望以此作为一些简单的案例,给我室友以
【前文连接】http://bbs.pediy.com/showthread.php?t=138186
【后文连接】http://bbs.pediy.com/showthread.php?t=139076
及才开始接触逆向的各位兄弟,希望大家有所收获,如果不出意外这是一个长期的学习笔记,请
大家多多指教。
【备 注】老手勿看
这三个CrackMe应该都是一个作者写的,采用Masm,难度较低,就合在一起吧。
首先,来看第一个程序:CRACKME1.EXE
还是老套路,用PEid载入,看出应该是没有加壳。
我们首先在"Help"菜单下,点击"Register"弹出了一个注册窗口,好了,这次我们采用下"消息断
点"的方法来找到注册算法的地方,首先用OD将程序载入,然后按"F9",让程序跑起来,然后我们在
"Name"和"Serial"窗口处随便输入:loongzyd 123456,然后我们在OD的"查看"菜单栏里面选择"窗
口",找到标题为"OK"的一行,选择在"ClassProc上设消息断点",
然后我们在消息选择里面选
择"202 WM_LBUTTONUP"(即当我们在"OK",BUTTON按钮窗口上面左键单击的时候,系统将会拦截下
来),按下"确定"之后,在CrackMe01上面左键点击"OK"按钮,我们看到此时程序中断在了系统领空,
然后按"Alt+F9",即在调试菜单下,选择"执行到用户代码".此时我们看到中断在了0x401223!,我
们发现下面要调用两个函数,而这两个函数的参数分别就是刚才我们输入的loongzyd和123456,即
这两个函数的作用是分别处理Name和Serial。我们分别跟进去看看:
0040137E /$ 8B7424 04 MOV ESI,DWORD PTR SS:[ESP+4]
00401382 |. 56 PUSH ESI
00401383 |> 8A06 /MOV AL,BYTE PTR DS:[ESI] ; 对Name字符串
的字符进行依次处理
00401385 |. 84C0 |TEST AL,AL
00401387 |. 74 13 |JE SHORT CRACKME.0040139C ; 如果已经处理
完毕
00401389 |. 3C 41 |CMP AL,41 ; 字符小于'A'
0040138B |. 72 1F |JB SHORT CRACKME.004013AC ; 用户名字符串
的ASC码不能小于'A'
0040138D |. 3C 5A |CMP AL,5A
0040138F |. 73 03 |JNB SHORT CRACKME.00401394 ; 如果大于等于
0x5A就减去0x20
00401391 |. 46 |INC ESI
00401392 |.^ EB EF |JMP SHORT CRACKME.00401383
00401394 |> E8 39000000 |CALL CRACKME.004013D2 ; 大于等
于'0x5a'的字符减去0x20
00401399 |. 46 |INC ESI
0040139A |.^ EB E7 \JMP SHORT CRACKME.00401383
0040139C |> 5E POP ESI
0040139D |. E8 20000000 CALL CRACKME.004013C2 ; EDI存放上一步
处理之后用户的ASC码之和
004013A2 |. 81F7 78560000 XOR EDI,5678 ; 与0x5678异或
004013A8 |. 8BC7 MOV EAX,EDI ; 放入EAX作为返
回值
004013C2 /$ 33FF XOR EDI,EDI ; edi初始为0
004013C4 |. 33DB XOR EBX,EBX
004013C6 |> 8A1E /MOV BL,BYTE PTR DS:[ESI] ; 继续处理第一
步之后的Name字符串,edi存放所有字符的ASC码和
004013C8 |. 84DB |TEST BL,BL
004013CA |. 74 05 |JE SHORT CRACKME.004013D1 ; 如果已经处理
完毕
004013CC |. 03FB |ADD EDI,EBX ; edi加上该字符
的ASC码值
004013CE |. 46 |INC ESI
004013CF |.^ EB F5 \JMP SHORT CRACKME.004013C6
004013D1 \> C3 RETN
004013D8 /$ 33C0 XOR EAX,EAX
004013DA |. 33FF XOR EDI,EDI
004013DC |. 33DB XOR EBX,EBX
004013DE |. 8B7424 04 MOV ESI,DWORD PTR SS:[ESP+4]
004013E2 |> B0 0A /MOV AL,0A
004013E4 |. 8A1E |MOV BL,BYTE PTR DS:[ESI] ; esi指向Serial
字符串
004013E6 |. 84DB |TEST BL,BL
004013E8 |. 74 0B |JE SHORT CRACKME.004013F5 ; 如果已经处理
完毕
004013EA |. 80EB 30 |SUB BL,30 ; 密码的每个字
符ASC码减去0x30('1'->1)
004013ED |. 0FAFF8 |IMUL EDI,EAX ; edi乘以10
004013F0 |. 03FB |ADD EDI,EBX ; edi加上当前字
符的值
004013F2 |. 46 |INC ESI ; 处理下一个字
符
004013F3 |.^ EB ED \JMP SHORT CRACKME.004013E2 ; 数字的字符串
转化成10禁止的数字("123456"->123456)
004013F5 |> 81F7 34120000 XOR EDI,1234 ; 与0x1234异或
004013FB |. 8BDF MOV EBX,EDI ; 结果放在EBX里
面
004013FD \. C3 RETN
00401241 . 3BC3 CMP EAX,EBX ; eax必须要与
ebx相等
00401243 . 74 07 JE SHORT CRACKME.0040124C ; 这个跳转必须
实现
00401245 . E8 18010000 CALL CRACKME.00401362
0040124A .^ EB 9A JMP SHORT CRACKME.004011E6
0040124C > E8 FC000000 CALL CRACKME.0040134D ; 此为注册正确
的情况
#include <stdio.h>
#include <string.h>
/*
测试所用= =
*/
int main(void)
{
int index;
int len_name;
int sum;
char str_name[20];
printf("input name:\n");
scanf("%s", str_name);
len_name = strlen(str_name);
sum = 0;
for (index = 0; index < len_name; index++)
{
if (str_name[index] < 'A') //如果Name字符的值小于'A'
{
printf("ASC's value lower than 'A'!\n");
return;
}
if (str_name[index] >= 'Z') //如果Name字符的值大于等于'Z'就减去
0x20
{
str_name[index] -= 0x20;
}
sum += str_name[index]; //sum记录所有字符的和
}
sum = sum ^ 0x5678; //与0x5678异或,现在得到的结果为用户名
处理函数之后的值
sum = sum ^ 0x1234; //与0x1234异或(A=A^B^B)
printf("密码为:%d\n", sum); //这里就偷懒个懒=_= 嘿嘿
getchar();
getchar();
}
00401365 /$ C605 18214000>MOV BYTE PTR DS:[402118],0 ; [402118]作为
计数器
0040136C |. 8B7424 04 MOV ESI,DWORD PTR SS:[ESP+4]
00401370 |. 56 PUSH ESI
00401371 |> 8A06 /MOV AL,BYTE PTR DS:[ESI] ; 依次取出输入
的字符
00401373 |. 84C0 |TEST AL,AL
00401375 |. 74 19 |JE SHORT CRACKME2.00401390 ; 如果结束
00401377 |. FE05 18214000 |INC BYTE PTR DS:[402118]
0040137D |. 3C 41 |CMP AL,41 ; 如果小于0x41,
跳过继续一下个
0040137F |. 72 04 |JB SHORT CRACKME2.00401385
00401381 |. 3C 5A |CMP AL,5A
00401383 |. 73 03 |JNB SHORT CRACKME2.00401388 ; 如果大于等于
0x5A,则减去0x20
00401385 |> 46 |INC ESI
00401386 |.^ EB E9 |JMP SHORT CRACKME2.00401371
00401388 |> E8 25000000 |CALL CRACKME2.004013B2
0040138D |. 46 |INC ESI
0040138E |.^ EB E1 \JMP SHORT CRACKME2.00401371
00401390 |> 5E POP ESI
00401391 |. E8 03000000 CALL CRACKME2.00401399
00401396 |. EB 00 JMP SHORT CRACKME2.00401398
00401398 \> C3 RETN
00401399 /$ 33DB XOR EBX,EBX
0040139B |. 33FF XOR EDI,EDI ;
4021A3:Messing_in_bytes
0040139D |> 8A8F A3214000 /MOV CL,BYTE PTR DS:[EDI+4021A3] ; 依次取出内存
中特定字符串的字符
004013A3 |. 8A1E |MOV BL,BYTE PTR DS:[ESI] ; 取出上面变形
之后的密码字符串
004013A5 |. 84DB |TEST BL,BL
004013A7 |. 74 08 |JE SHORT CRACKME2.004013B1 ; 如果输入的密
码处理完毕
004013A9 |. 32D9 |XOR BL,CL ; 与内存中特定
字符串的对应下标字符进行异或
004013AB |. 881E |MOV BYTE PTR DS:[ESI],BL
004013AD |. 46 |INC ESI
004013AE |. 47 |INC EDI
004013AF |.^ EB EC \JMP SHORT CRACKME2.0040139D
004013B1 \> C3 RETN
004013B8 /$ 33FF XOR EDI,EDI
004013BA |. 33C9 XOR ECX,ECX
004013BC |. 8A0D 18214000 MOV CL,BYTE PTR DS:[402118] ; [402118存放的
是输入密码的长度]
004013C2 |. 8B7424 04 MOV ESI,DWORD PTR SS:[ESP+4]
004013C6 |. BF 50214000 MOV EDI,CRACKME2.00402150
004013CB |. F3:A6 REPE CMPS BYTE PTR ES:[EDI],BYTE PTR DS:>; 处理之后的字
符串必须和402150:开始的字符串能够匹配(以输入的密码长度为准)
004013CD \. C3 RETN
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!
上传的附件: