新CrackMe160之042 - crackme

作者提示要先创建一个key.dat的文件,创建好后再运行,提示文件内容不对,根据提示OD中搜索定位到004011F1,向上找到读文件处00401144下好断点,单步分析文件内容

  1. 每一位与长度异或
  2. 0x54, 0x4D, 0x47 "TMG"与文件开头三位 异或
  3. 剩下的每3位分别与前三位异或,不足三位的补齐
  4. 将前三位结果与00405030~004051AF这一大堆数每三位异或
  5. 取异或结果前三位相乘, 是否等于0x2A8BF4
    到这里算法就分析完了,有用的数据就是前三位, 所以只需要三位密钥就行了, 算法为: (设3位数分别为a,b,c)
    1). a^3, b^3, c^3
    2). a30x54, b30x4D, c30x47
    3). a30x54^0x1E, b30x4D^0xBF, c30x47^0xA2
    接下来通过结果反算密钥
    0x2A8BF4 = 2 * 2 * 5 * 17 * 59 * 139 = (259) * (25*17) * 139 = (5 * 17) * (2 * 2 * 59) * 139
    = 0x76 * 0x8B * 0xAA (可能1)
    = 0x55 * 0x8B * 0xEC (可能2)
    只能分成这两种情况(顺序不限,总的会有12种可能,每组6种), 接下来分别反算
    可能1: (銍m)
    a30x54^0x1E = 0x76 => a = 0x3F
    b30x4D^0xBF = 0x8B => b = 0x7A
    c30x47^0xA2 = 0xAA => c = 0x4C
    可能2: (イm)
    a30x54^0x1E = 0x55 => a = 0x1C
    b30x4D^0xBF = 0x8B => b = 0x7A
    c30x47^0xA2 = 0xEC => c = 0x0A
    两个值验证都可以正常通过错误弹框, 来到0040120C处需要验证密钥串是否有0x20才会退出循环,如果没有就死循环了~
    说明密钥不能只有3位, 再加一位d, 重新计算上面的两种情况: (因为现在是4位了)
    可能1: (无法显示,只有写入16进制)
    a40x54^0x1E = 0x76 => a = 0x38
    b40x4D^0xBF = 0x8B => b = 0x7D
    c40x47^0xA2 = 0xAA => c = 0x4B
    d4a40x54 = 0x20 => d = 0x4C
    可能2: (无法显示,只有写入16进制)
    a40x54^0x1E = 0x55 => a = 0x1B
    b40x4D^0xBF = 0x8B => b = 0x7D
    c40x47^0xA2 = 0xEC => c = 0x0D
    d4a40x54 = 0x20 => d = 0x6F
    验证可能1没有通过,程序异常了,可能2成功了, 说明12组可能里有些还是不正确的 (后记, 这里有个小经验, 因为在00401250处会call 00405030, 说明这个00405030是一个方法入口, 看到可能2中有55, 是不是可以联想到什么, 对的方法第一行代码一般就是55, 经事后验证,其它11组都无法通过,也就是答案是唯一的55 BF EC)
    00405030方法解码后,又是一个带用户名的算法, 注册机如下:
#include <stdio.h>
#include <string.h>

int main() {
	char code[5] = {0};
	char user[22] = {0};
	printf("用户名(21位内): ");
	fgets(user, sizeof(user), stdin);
	int i, len = strlen(user) - 1;
	if(len % 3 != 0){ len = len + 3 - len % 3; }
	code[0] = 0x55 ^ 0x1E ^ (len + 4);
	code[1] = 0x8B ^ 0xBF ^ (len + 4);
	code[2] = 0xEC ^ 0xA2 ^ (len + 4);
	code[3] = 0x20 ^ code[0];
	printf("密钥为(16进制): %X %X %X %X", code[0] ^ 0x54,code[1] ^ 0x4D,code[2] ^ 0x47,code[3]);
	for(i=0; i<len; i++){ 
		user[i] = user[i] ^ code[(i + 1) % 3];
		printf(" %X", user[i]);
	}
	getchar();
	return 0;
}

运行示例:
用户名(21位内): crackme042
密钥为(16进制): F 69 19 7B 47 2C 3A 47 35 36 41 6E 6F 16 54 5B

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

 
 
 

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

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

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