新CrackMe160之057 - keygen-crackme4

  1. 脱壳
    OD手动脱壳, F8运行一次,ESP变红,右键HW break [ESP]下好硬件断点, F9运行,看到了下面的jmp, 以为要成功了, 结果又跳到了乱码处, 说明还需要继续解密, 重来,F9运行到jmp前面时, 再F9两次来到00401871处, 观察下面的代码, 虽然不乱了, 但还是一堆的push, pop, 说明还是不对, F8单步跟踪, 直到00401930 call 00401690, 运行这一行,程序界面就出来了,说明到这里就完成脱壳了, 继续重来, 运行到00401930这一行后不继续F8了,改为F7进入方法,这里就是程序入口处了(00401690), 接着便右键 ollydump 方式1脱壳成功~

  2. 破解
    运行脱壳后程序, 按验证按钮有错误提示信息, 搜索界面可定位到004015FA,向上找到入口0040158A, 下好断点, 输入伪码, 开始分析算法(004011B0处)
    算法比较简单, 注册机如下:

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

int main() {
	unsigned int sid, edx, esi = 0x12345678;
	char user[51] = {0};
	char code[51] = {0};
	printf("系统ID: ");
	fgets(code, sizeof(code), stdin);
	code[strlen(code)-1] = 0;
	char *endstr;
	sid = strtol(code, &endstr, 16);
	if(*endstr != 0) {
		printf("系统ID输入错误!");
		return 0; 
	}
	printf("用户名: ");
	fgets(user, sizeof(user), stdin);
	int i, rnd, len = strlen(user) - 1;
	for(i=0; i<len; i++){
		edx = esi;
		esi *= 2;
		edx = edx >> 7;
		edx |= esi;
		esi = user[i] ^ edx;
	}
	esi ^= sid;
	printf("系列号: %X\r\n", esi);
	getchar();
	return 0;
}

运行示例:
系统ID: 12345DC0 (这个每个人电脑不一样)
用户名: crackme4
系列号: 2442228B
可用计算器直接将这个示例系列号转为你自己的系列号 => 2442228B ^ 12345DC0 ^ 你的系统ID

[( 后记 )]
系统ID是004014C9处设置的, (通过命令行下断点可跟踪: bp SetDlgItemTextA), 值的产生在004014A6这行的方法中, 跟踪进去有一个小阻碍, 作者设置了防调试栏路虎, 这个也简单, F8运行到00401012处,不要再继续向下运行了, 这时只要在00401037处右键设为新EIP即可跳过验证,
00401057~00401065是密文,运行完00401057这行即可解密, 向下就可以很容易看到, 系统ID的值就等于0x12345678 ^ cpuid, cpuid这行参数的入参
eax当前值为0x00401057, 到此, 分析完毕, 上面的注册机也可以简化一点了,不需要再手动输入系统ID号了:

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

//32bit
void cpuid(int code, int data[4])
{
	asm volatile("cpuid"
	    : "=a" (data[0]),
	      "=b" (data[1]),
	      "=c" (data[2]),
	      "=d" (data[3])
	    : "0" (code));
}

/*//64bit
void cpuid(int code, int data[4]) {
	__cpuid(data, code);
}
*/

int main() {
	unsigned int sid, edx, esi = 0x12345678;
	char user[51] = {0};
	char code[51] = {0};
	int data[4];
	cpuid(0x00401057, data);
	sid = esi ^ data[0]; //cpuid
	printf("系统ID: %X\n", sid);
	printf("用户名: ");
	fgets(user, sizeof(user), stdin);
	int i, rnd, len = strlen(user) - 1;
	for(i=0; i<len; i++){
		edx = esi;
		esi *= 2;
		edx = edx >> 7;
		edx |= esi;
		esi = user[i] ^ edx;
	}
	esi ^= sid;
	printf("系列号: %X\r\n", esi);
	getchar();
	return 0;
}

运行示例:
系统ID: 12345DC0
用户名: crackme4
系列号: 2442228B

 
 
本节高手录制的视频,点击前往查看

 
 
 

使用的工具连接(工具有点多有点大,可以先下OD,其它的后面慢慢下) 点击前往下载

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

posted @ 2024-12-19 14:12  hankerstudio  阅读(0)  评论(0)    收藏  举报