本帖最后由 我形我塑 于 2015-11-15 12:03 编辑
破解目的:交流学习 破解过程: 一、查壳:Borland Delphi 3.0 二、试运行,弹出信息框,点“确定”退出,如图:
三、OD载入,分析004383E7至00438421处代码,发现关键是00438411处的那个跳转:如果程序在当前目录下发现Reg.dat,则调用CreateFileA函数成功返回创建的文件句柄,否则返回-1。用GetLastError函数获取错误类型为ERROR_FILE_NOT_FOUND(2),返回值在eax中:
0043840F 85C0 TEST EAX, EAX
00438411 7415 JE SHORT crackme_.00438428 …… …… 00438421 E8BED5FCFF CALL <JMP.&user32.MessageBoxA> 办法就不用说了吧? 四、再次运行,如图: 五、单击弹出菜单项About,选Register子菜单,进入注册窗口。又是无效按钮(能不能来点新鲜的?),不过无效按钮也是按钮,应该可以试试Delphi 的按钮事件的特征码:740E8BD38B83???????? FF93???????? Ctrl+B,粘贴特征码,确定, 来到这里: 0042C045 /74 0E JE SHORT crackme_.0042C055 0042C047 |8BD3 MOV EDX, EBX 0042C049 |8B83 D8000000 MOV EAX, DWORD PTR DS:[EBX+0xD8] 0042C04F |FF93 D4000000 CALL NEAR DWORD PTR DS:[EBX+0xD4] 在CALL这行下F2,然后Ctrl+L,又找到一处,再下断。如此四次。 六、随便输入用户名和序列号(小技巧:先输入用户名假码,然后再下断点会更有利于后面的跟踪),更改比如最后一个编辑框中输入的内容,触发断点。OD断在这里: 0042F458 FF93 28010000 CALL NEAR DWORD PTR DS:[EBX+0x128] F7步入,F8单步一次,F7步入EditChange(能猜出大概意思吧?)事件处理函数: 00437D1C 55 PUSH EBP 00437D1D 8BEC MOV EBP, ESP 00437D1F 6A00 PUSH 0x0 00437D21 53 PUSH EBX 七、一路F8单步,遇到Call观察右上角的寄存器窗口,大概能猜出它们的功能:取出编辑框中你输入的假码,eax里是返回的假码长度;然后把这些字符转换成数值,存到ds:[0043A73C]开始的地址中。最后来到关键调用处: 00437DD3 E8 00FEFFFF CALL crackme_.00437BD8 八、F7步入,然后一路F8单步,观察寄存器窗口,尤其是eax,发现这个函数首先是获取你输入的用户名(不能少于5个字符),然后对用户名进行一系列的处理,结果保存在ds:[0043A72C]开始的地址中,最后将这段地址中的数值与前面提到的ds:[00437A38]开始的那段地址中的数值比较,完全相等则使OK按钮有效,大功告成。关键代码如下: 00437C9B B8 2CA74300 MOV EAX, crackme_.0043A72C 00437CA0 BA 3CA74300 MOV EDX, crackme_.0043A73C 00437CA5 8B0A MOV ECX, DWORD PTR DS:[EDX] 00437CA7 3B08 CMP ECX, DWORD PTR DS:[EAX] 00437CA9 74 07 JE SHORT crackme_.00437CB2 00437CAB B9 01000000 MOV ECX, 0x1 00437CB0 EB 15 JMP SHORT crackme_.00437CC7 00437CB2 33C9 XOR ECX, ECX 00437CB4 46 INC ESI 00437CB5 83C2 04 ADD EDX, 0x4 00437CB8 83C0 04 ADD EAX, 0x4 00437CBB 83FE 05 CMP ESI, 0x5 00437CBE 75 E5 JNZ SHORT crackme_.00437CA5 数据窗口中0043A72C开始的地址中存的是经过处理的用户名(我输的是“Samsonn”),下面是我输入的假码(还记得吗?是4个):DE=222;0x2=2;0x3=3;0x18=24。 现在知道注册码该怎么找了吧? 最后附上注册机代码(vs2008调试通过): #include "stdafx.h" #include <stdio.h> int _tmain(int argc, _TCHAR* argv[]) { char szUser[20]={0}; int ptr1[4]; printf("\n\n\t用户名 "); scanf("%s",szUser); printf("\t注册码 "); ptr1[0]=szUser[0]/10; ptr1[1]=szUser[2]/10; ptr1[2]=szUser[3]/10; ptr1[3]=szUser[4]/10; for(int i=0;i<4;i++) { char str[3]={0}; intnCount=strlen(itoa(ptr1,str,10));
if(nCount>1)
ptr1/=10;
printf("%d",ptr1);
}
printf("\n\n"); return 0; } |