selph
selph
发布于 2022-07-19 / 244 阅读
0
0

新160个CrackMe练习:014-Splish

算法难度:⭐⭐

爆破难度:⭐

信息收集

运行情况:

开始有个启动屏幕,然后进入程序主界面

按照说明,目标是禁用启动屏幕,完成硬编码校验,写用户名序列号注册机

image

image

查壳与脱壳:

无壳:

image

调试分析

用户函数比较少,直接从起点硬刚:

这个call应该就是程序的入口了

image

这个call里面就进入窗口消息循环了,在那之前调用了几个用户函数:

有一个是对参数进行处理的,有一个call的参数是实例句柄,很可疑,进入查看

image

这里头是创建了一个窗口,然后延时关闭,要去除NAG,直接把这个函数处理了就好:

image

然后找到一个函数貌似是消息处理函数:这里根据参数的Msg号进行跳转执行

image

往下找,发现硬编码check分支:将用户输入和硬编码:HardCoded进行比对,一致了跳转

image

一致了跳转的最终位置是,说明这里硬编码已经找到了:

image

接下来找找用户名序列号验证:

验证会进行三次计算,首先是计算用户名得到一个结果:

image

然后计算序列号得到一个结果:

image

最后将两个运算结果进行比对:

image

算法分析

拿用户名计算一个结果,跟序列号计算一个结果进行比对的验证逻辑,写注册机的话则是先用用户名计算一个结果,然后用这个结果反推序列号

#include <iostream>

int main()
{
	const char* num = "2345678901";
    	char serial[20] = { 0 };
	char name[20] = { 0 };
	char name_res[20] = { 0 };
	int len = 0;

	std::cin >> name;
	len = strlen(name);
	//std::cin >> serial;

	for (int i = 0; i < len; i++)
	{
		name_res[i] = name[i] % 0xA;
		name_res[i] ^= i;
		name_res[i] += 2;
		if (name_res[i] > 0xA)name_res[i] -= 0xA;
	}

	//for (int i = 0; i < len; i++)
	//{
	//	serial_res[i] = serial[i] % 0xA;
	//}

	for (int i = 0; i < len; i++)
	{
		serial[i] = num[name_res[i]];
	}

	std::cout << serial << std::endl;
}

结果:

image

总结

算是个编写注册机的练习,这个cm中练习了汇编转C的操作


评论