算法难度:⭐⭐⭐
爆破难度:⭐
信息收集
运行情况:
查壳与脱壳:
调试分析
程序验证逻辑很简单:
首先以硬编码0xce6d和0x58bf创建了一个对象结构,然后读取Name,计算一个字符串,然后读取Serial字符串,进行比对,一样则表示成功,否则表示失败
这里要注意,delphi使用的是32位的fastcall,传参顺序是eax,edx,ecx,栈,最后调用计算字符串的函数的时候,有一个栈中的参数
计算逻辑也很简单:
首先保存变量,初始化输出缓冲区
然后计算Name长度,遍历每一个字符
对于每一个字符,和两字节变量右移8位后的结果异或一下,然后转换成十六进制(大写)拼接到输出缓冲区里
然后中间处理了一下两字节值,初值是4DE1是参数传入的,修改方式是使用异或后的一字节,加上原本的两字节值,然后乘以安全对象的第一个成员,最后加上安全对象的第二个成员的值(第一个成员的值和第二个成员的值可以通过动态调试得知,是固定值)
注册机
注册码生成算法:
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
typedef struct _TSecurity
{
_TSecurity(uint16_t a, uint16_t b) :vul1(a), vul2(b) {}
uint16_t vul1;
uint16_t vul2;
}TSecurity,*PTSecurity;
int main()
{
TSecurity obj(0xce6d,0x58bf);
char name[100] = { 0 };
short num = 0x4de1;
char serial[100] = { 0 };
char tmp[100] = { 0 };
std::cin >> name;
int len = strlen(name);
for (int i = 0; i < len; i++)
{
uint8_t c = name[i] ^ (num >> 8);
num = (c + num) * obj.vul1 + obj.vul2;
sprintf(tmp, "%02X", c);
strcat(serial, tmp);
}
std::cout << serial;
}
效果: