新手破解练习Crackme160之032 -

  1. 运行程序有个提示界面阻挡了去路, 看来是要先把这个界面干掉, 提示信息说是需要reg.dat那我们就创建一个, 果然不再提示了直接进入到主界面了
    既然是去NAG, 那我们直接跳过这个文件验证, 004383EC处改为 jmp 00438428, 搞定~
    主界面什么作用都没有, 我们也把它当作NAG干掉吧, 因为程序是delphi写的, 我们这里需要了解delphi窗体的加载原理, 在delphi中, 第一个创建的窗体就是第一个加载的, 所以我们找到窗体的创建在哪里, OD中, 00438447, 00438459, 00438471, 三处即为三个窗体创建, 用IDR来分析更容易看出来
EntryPoint
004383DC    push       ebp
004383DD    mov        ebp,esp
004383DF    add        esp,0FFFFFFF4
004383E2    mov        eax,4382E4
004383E7    call       @InitExe
>004383EC    jmp        00438428
004383EE    nop
004383EF    nop
004383F0    nop
004383F1    mov        eax,43A760; gvar_0043A760:TFileRec
004383F6    call       @Assign
004383FB    mov        edx,80
00438400    mov        eax,43A760; gvar_0043A760:TFileRec
00438405    call       @ResetFile
0043840A    call       IOResult
0043840F    test       eax,eax
>00438411    je         00438428
00438413    push       0
00438415    push       4384A0; 'Missing!'
0043841A    push       4384AC; 'Hey, where is my little Reg.dat\rI love it so much that I can't\rlive without it. Return it back! Arrgh!'
0043841F    push       0
00438421    call       user32.MessageBoxA
>00438426    jmp        00438488
00438428    mov        eax,[00439A90]; ^Application:TApplication
0043842D    mov        eax,dword ptr [eax]
0043842F    call       TApplication.Initialize
00438434    mov        ecx,dword ptr ds:[439B0C]; ^gvar_0043A758:TForm1
0043843A    mov        eax,[00439A90]; ^Application:TApplication
0043843F    mov        eax,dword ptr [eax]
00438441    mov        edx,dword ptr ds:[4380C8]; TForm1
00438447    call       TApplication.CreateForm
0043844C    mov        ecx,dword ptr ds:[439B20]; ^gvar_0043A728:TForm2
00438452    mov        eax,[00439A90]; ^Application:TApplication
00438457    mov        eax,dword ptr [eax]
00438459    mov        edx,dword ptr ds:[4379C0]; TForm2
0043845F    call       TApplication.CreateForm
00438464    mov        ecx,dword ptr ds:[439A6C]; ^gvar_0043A750:TForm3
0043846A    mov        eax,[00439A90]; ^Application:TApplication
0043846F    mov        eax,dword ptr [eax]
00438471    mov        edx,dword ptr ds:[437F38]; TForm3
00438477    call       TApplication.CreateForm
0043847C    mov        eax,[00439A90]; ^Application:TApplication
00438481    mov        eax,dword ptr [eax]
00438483    call       TApplication.Run
00438488    call       @Halt0

那我们就把TForm1 和 TForm2的地址互换一下, 即让程序先创建TForm2, 在OD中我们找到下面这四行,
00438434 mov ecx,dword ptr ds:[439B0C]; ^gvar_0043A758:TForm1
00438441 mov edx,dword ptr ds:[4380C8]; TForm1
0043844C mov ecx,dword ptr ds:[439B20]; ^gvar_0043A728:TForm2
00438459 mov edx,dword ptr ds:[4379C0]; TForm2
将它们改为
00438434 mov ecx,dword ptr ds:[439B20]; ^gvar_0043A758:TForm2
00438441 mov edx,dword ptr ds:[4379C0]; TForm2
0043844C mov ecx,dword ptr ds:[439B0C]; ^gvar_0043A728:TForm1
00438459 mov edx,dword ptr ds:[4380C8]; TForm1
保存, 第二个NAG也去掉了

  1. 暴力破解, 4个选择框的change事件都到00437BD8这个方法来验证数据, 我们就下断点跟踪, 首先, 判断name长度有没有5位, 记录这边关键跳位置004383EC, 然后一路向下我们看到了算法, 看到了很多对比, 我们都先不管, 一直执行到最后的关键跳00437CC9, 这时我们4位数是乱选的, 到这边就跳过了, , 本次调试就结束了, 说明, 不跳过就是成功分支, 所以我们让第一次判断直接跳入成功分支, 将004383EC改为jmp 00437CCB, 保存测试~ 随便选择一个数ok亮起, 暴破完成~

  2. 正常破解, 由上一步, 我们进入00437BD8这个方法详细分析, 用户名输入abcde, 太长也没用, 程序只取了0234这4位来验证的, 验证码第一位选1, 即当前为1, 0, 0, 0, 单步跟踪, 到00437C16处, 取用户名第一位a=97, 除于10 = 9, 同理得到其它3位为c/10=9, d/10=10, e/10=10, 4位取值计算完成, 进入校验环节, 分别判断计算结算有没有大于10的, 有的话继续除于10, 接着与输入的4位验证码进行对比, 由此, 算法就已经清晰了, 做了正反向计算, c代码如下:

#include <iostream>
#include <stdlib.h> 
#include <time.h> 
#include "string.h"

int main(){
	while(true){
		char rlt[5] = {0};
		char user[20] = {0};
		printf("请选择 1.用户名(5~20位) 2.系列号(4位数字): ");
		int inp;
		scanf("%d",&inp);
		if(inp == 2){
			printf("请输入系列号(4位): ");
			scanf("%s", rlt);
			int len = strlen(rlt);
			if(len != 4){
				printf("系列号必须为4位");
				continue; 
			}
			int a,i,j;
			srand((unsigned int)time(0));
			for(i=0,j=0; i<4; i++,j++){
				a = rlt[i] - 0x30; //字符数字转整形数字 
				if(a == 1) { a = 10; }
				if(a == 0) { a = 1; } else  //不可见符号
				if(a == 2) { a = 21; } else  //不可见符号
				if(a == 3) { a = 30 + rand() % 8 + 2; } else //0~7 +2 = 2~9
				if(a >= 4 && a <= 10) { //40~109 可见符号
					a *= 10;
					a += rand() % 10; //0~9
				}
				user[j] = a;
				if(i == 0){ j++; }
			}
			user[1]='?'; //第二位任意 
			printf("用户名为: %d,%d,%d,%d=%s\n", user[0],user[2],user[3],user[4],user);
		} else {
			printf("请输入用户名(5~20位): ");
			scanf("%s", user);
			int len = strlen(user);
			if(len < 5){
				printf("用户名长度小于5位");
				continue; 
			}
			int a = 0;
			for(int i=0,j=0; i<5; i++,j++){
				a = user[i] / 10;
				while(a >= 10){ a = a / 10; }
				rlt[j] = a+0x30; //整形数字转字符数字 
				if(i == 0) i++;
			}
			printf("系列号为: %s\n", rlt);
		}
	}
	return 0;
}

注意: 用户名输入完后就算当前系列号是对的, 也需要改变一下再改回来才会触发验证

这是160个软件part1
这是160个软件part2

1~160每个破解过程,在吾爱破解论坛都有高手破解过了,也有整理好现成的, 我这边主要就是自己动手操作的过程,与他们的不太一样
附上高手们的连接: 点击前往查看
使用的工具连接(工具有点多有点大,可以先下OD,其它的后面慢慢下) 点击前往下载

新人入门教程"玩玩破解,写给新人看" 点击前往查看
我就是从这里开始的,对我这样的小白感觉超级友好~

下面是我的OD的界面布局,我觉得这4个是最常用的界面,其它的我基本上没用到~
OD界面布局

posted @ 2024-05-10 15:29  hankerstudio  阅读(11)  评论(0)    收藏  举报