新手破解练习Crackme160之078 - fireworx.10(内存注入拿ESI)

  1. 脱壳, 程序有ASPack 1.06b / 1.061b -> Alexey Solodovnikov的壳, 在xp下PEiD通用脱壳插件脱壳成功~

  2. 暴力破解, OD载入去壳后的程序, IDR找到图片按钮入口00453E94, 单步分析得知, 成功分支在循环里, 而且需要ebx循环0x13次, 所以我们在进入循环之前就跳到成功分支去, 找个地方00453EAD, 往下两行分别改为, mov ebx, 0x12(让循环直接到最后一次), jmp 00453F82(进入成功分支), 保存所有修改~

  3. 正常破解, 开始从按钮入口00453E94单步分析算法,
    1). 按位取用户名
    2). esi += user[i]
    3). 将esi转十进制字符串与code比较
    所以不管输入多少, 只有其中有一个字符+这个常量=系列号就可以了, 现在还有一个问题, 这个esi是固定的还是变化的我们需要继续研究一下, 启动程序前esi=0x454144是程序的启动入口, 点击OK按钮后, 这个值是会变的, 先猜他是一个随机数, 现在我们就要找出它生成的规律, 不然我们就没办法写注册机了, 跟踪了无数遍也没找到是哪里赋值的, 百度一翻后, 大概了解到esi这个寄存器是用来记录地址的, 也就是说, 这个应该就是ok方法的入口地址, 但程序里找半天也没找到这个入口的具体地址是哪个(能力有限就放弃了, 大佬应该可以从二进制文件中反算出来), 现在只好从程序最开始的form1入口开始找了,

00454144 > $  55            push ebp
00454145   .  8BEC          mov ebp,esp
00454147   .  83C4 F4       add esp,-0xC
0045414A   .  B8 24404500   mov eax,fireworx.00454024                ;  #
0045414F   .  E8 801AFBFF   call fireworx.00405BD4
00454154   .  A1 F8644500   mov eax,dword ptr ds:[0x4564F8]
00454159   .  8B00          mov eax,dword ptr ds:[eax]
0045415B   .  E8 FCA1FEFF   call fireworx.0043E35C
00454160   .  8B0D CC654500 mov ecx,dword ptr ds:[0x4565CC]          ;  fireworx.00457810
00454166   .  A1 F8644500   mov eax,dword ptr ds:[0x4564F8]
0045416B   .  8B00          mov eax,dword ptr ds:[eax]
0045416D   .  8B15 D83C4500 mov edx,dword ptr ds:[0x453CD8]          ;  $=E
00454173   .  E8 FCA1FEFF   call fireworx.0043E374
00454178   .  8B0D EC654500 mov ecx,dword ptr ds:[0x4565EC]          ;  fireworx.00457808
0045417E   .  A1 F8644500   mov eax,dword ptr ds:[0x4564F8]
00454183   .  8B00          mov eax,dword ptr ds:[eax]
00454185   .  8B15 143B4500 mov edx,dword ptr ds:[0x453B14]          ;  `;E
0045418B   .  E8 E4A1FEFF   call fireworx.0043E374

其中 0045160这行就是form1的定义, 0x4565CC就是form1的入口地址了, 0x4565EC是form2的入口地址, 我们在数据区定位到004565CC, 看到数据还是一个地址00457810, 我们继续定位到00457810, 看到数据是空的, 那是因为我们程序还没运行, F9运行后, 此处数据变了03494DC8(每个人的电脑对应的值不对, 每次运行的结果也可能不同), 这个就是真实内存地址了, 我们定位到真实地址去ctrl+g, 输入03494DC8, 我们在按钮事件00453E94处先下个断点, 点击ok按钮,在断点处停下, 这时我们可以看到右侧寄存器区域esi的值已经变了03491454(每个人的电脑值不同, 每次运行也可能不同), 此值与form1的真实入口值是同一个内存段的, 说明我们原来的猜测基本上是对的了, 我们在数据区定位到esi这个值的位置看到的值是0043F608, 这个值应该就是ok方法的定义入口地址, 再看这个值后面4位竟然就是form1的地址, 再后面4位又是一个地址值, 根据这个特征, 我们就可以反过来直接从内存中找到这个值了, 我们将数据区的下拉条拉到最上面, 点击第一个值03490000处(每个人的电脑地址不一样哈, 只要点击第一个值就行了), 然后ctrl+b, 在hex框输入08 F6 43 00 C8 4D 35 03, 搜索, 可以找出两处位置来, 如下所示: (每个人电脑结果不一样哈, 但都是类似的)
03351454 08 F6 43 00 C8 4D 35 03 24 65 35 03 00 00 00 00 鯟.萂5$e5....
03356544 08 F6 43 00 C8 4D 35 03 38 65 35 03 00 00 00 00 鯟.萂58e5....
为什么会有两个结果, 这个也比较好理解, 一个是方法的定义, 一个是方法的实现, 定义在程序的最上方, 就是要先定义再实现, 所以我们就选08 F6 43 00 C8 4D后面4位数值小的那个, 那就是03351454这个了, 与OD中的esi一致~

注册机代码如下, 有点长: keygen.c

#include <stdio.h>
#include "string.h"
#include <Windows.h>

int byteArrayToInt(byte* bytes) {
    return (bytes[3] << 24) | (bytes[2] << 16) | (bytes[1] << 8) | bytes[0];
}

//XP提权
int AddPrivilege(const   char* Name)
{
	HANDLE   hToken;
	TOKEN_PRIVILEGES   tp;
	LUID   Luid;
	if (!OpenProcessToken(GetCurrentProcess(),
		TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
		&hToken))
	{
		//printf("OpenProcessToken   error.\n ");
		return   1;
	}
	if (!LookupPrivilegeValue(NULL, (LPCSTR)Name, &Luid))
	{
		//printf("LookupPrivilegeValue   error.\n ");
		return   1;
	}
	tp.PrivilegeCount = 1;
	tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
	tp.Privileges[0].Luid = Luid;
	if (!AdjustTokenPrivileges(hToken,
		0,
		&tp,
		sizeof(TOKEN_PRIVILEGES),
		NULL,
		NULL))
	{
		//printf("AdjustTokenPrivileges   error.\n ");
		return   1;
	}
	return   0;
}

int main() {
	AddPrivilege((char*)SE_DEBUG_NAME);
	int pid;
	printf("友情提示:\n\n请先运行程序,再运行本注册机,如果获取进程失败,以管理员身份运行本注册机再试一次~\n\n");
	byte form1[4] = {0}; //记录form1入口真实内存地址,运行后才可获取 
	byte ok[4] = {0x08,0xf6,0x43,0x00}; //记录按钮入口真实地址(暂且认为esi是这个地址吧) 
	int form1Addr = 0x00457810; //form1入口的文件地址 
	int esi[2] = {0}; //内存中会搜索出两个可能值 
	byte esiSign[2][4];
	while(true){
		printf("请输入程序PID: ");
		scanf("%d", &pid);
		HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
		if (hProcess == 0) {
			printf("没有发现%d这个PID的进程,请确认程序是否已运行,或未以管理员权限运行此注册机~\n\n",pid);
		    continue;
		}
		bool flag = ReadProcessMemory(hProcess, (void *)form1Addr, &form1, 4, 0);
		if (!flag) {
			printf("获取Form1入口地址失败\n\n");
		 	continue;
		}
		form1Addr = byteArrayToInt(form1); //换成真实地址 
		printf("Form1入口地址 = 0x%08X\n", form1Addr);
		byte memBegin[4] = {0x00,0x00,form1[2],form1[3]};
		int memB =  byteArrayToInt(memBegin); //内存搜索开始 
		byte buff[0xfff0]; //一次性读取整个内存块 
		int nowi = 0; //记录当前找到了几个结果 
		flag = ReadProcessMemory(hProcess, (void *)memB, &buff, 0xfff0, 0);
		if (!flag) { break; }
		for(int i=0; i<0xfff0; i++){ //开始搜索 
			if (buff[i] == ok[0]){ //发现可能值 
				esi[nowi] = memB + i; //记录当前位置
				i++; if (buff[i] != ok[1]) { esi[nowi] = 0; continue;}
				i++; if (buff[i] != ok[2]) { esi[nowi] = 0; continue; }
				i++; if (buff[i] != ok[3]) { esi[nowi] = 0; continue; }
				i++; if (buff[i] != form1[0]) { esi[nowi] = 0; continue; } 
				i++; if (buff[i] != form1[1]) { esi[nowi] = 0; continue; } 
				i++; if (buff[i] != form1[2]) { esi[nowi] = 0; continue; } 
				i++; if (buff[i] != form1[3]) { esi[nowi] = 0; continue; } 
				//成功找到一个,记录后4位地址 
				esiSign[nowi][0] = buff[i+1+0];
				esiSign[nowi][1] = buff[i+1+1];
				esiSign[nowi][2] = buff[i+1+2];
				esiSign[nowi][3] = buff[i+1+3];
				nowi++;
				if(nowi >= 2){ break; } //找到2个了就结束了 
			}
		}
		if(esi[0] == 0){
			printf("当前进程未能找到 ESI 这个值, 重新运行程序再试~\n\n");
			continue; 
		}
		int esiOK =  byteArrayToInt(esiSign[0]) < byteArrayToInt(esiSign[1]) ? esi[0] : esi[1];
		printf("当前进程的 ESI = 0x%08X\n\n",esiOK);
		int len = 0; 
		char user[21] = {0};
		while((len == 0) || (len > 0x12)){
			printf("请输入用户名(18位以内): ");
			scanf("%s", user);
			len = strlen(user);
		}
		int rlt = 0;
		for(int i=0; i<len; i++){ rlt += user[i]; }
	 	printf("系列号为: %d\n\n", rlt+esiOK);
	}
    return 0;
}

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

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

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

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

posted @ 2024-05-23 17:53  hankerstudio  阅读(12)  评论(0)    收藏  举报