算法难度:⭐⭐
爆破难度:⭐
信息收集
运行情况:
开始有个启动屏幕,然后进入程序主界面
按照说明,目标是禁用启动屏幕,完成硬编码校验,写用户名序列号注册机
查壳与脱壳:
无壳:
调试分析
用户函数比较少,直接从起点硬刚:
这个call应该就是程序的入口了
这个call里面就进入窗口消息循环了,在那之前调用了几个用户函数:
有一个是对参数进行处理的,有一个call的参数是实例句柄,很可疑,进入查看
这里头是创建了一个窗口,然后延时关闭,要去除NAG,直接把这个函数处理了就好:
然后找到一个函数貌似是消息处理函数:这里根据参数的Msg号进行跳转执行
往下找,发现硬编码check分支:将用户输入和硬编码:HardCoded
进行比对,一致了跳转
一致了跳转的最终位置是,说明这里硬编码已经找到了:
接下来找找用户名序列号验证:
验证会进行三次计算,首先是计算用户名得到一个结果:
然后计算序列号得到一个结果:
最后将两个运算结果进行比对:
算法分析
拿用户名计算一个结果,跟序列号计算一个结果进行比对的验证逻辑,写注册机的话则是先用用户名计算一个结果,然后用这个结果反推序列号
#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;
}
结果:
总结
算是个编写注册机的练习,这个cm中练习了汇编转C的操作