题目拿到手,先跑下,

惯例PEID查下壳,恩啥也没有。

strings扫一遍字符串,发现有Registration和error字眼,OD载入程序,右键分析字符串可以看到判断处,点击进入:

向上可以看到整个判断的代码部分,bp GetDlgItemTextA下断点(该函数用于获取输入框文本),F9运行,输入注册码1234,断在这里: 
注意这里是系统领空,内存窗口对代码段下断,F9返回程序领空:


结合IDA分析可知此处调用strlen函数对输入注册码长度判断,长度必须为4:

接下来程序对输入的注册码判断是否存在0,存在则跳转到注册失败处:(0x30是‘0’的ascii码)

然后把注册码转换为数字(如:'1'-0x30=1):(ecx值为0x30)

其中涉及到了几个浮点运算指令
指令格式 | 指令含义 | 执行操作 |
---|
FILD src | 装入整数到st(0) | st(0) <- src |
FIDIV src | 除以一个整数 | st(0) <- st(0) /src |
FSUBP st(i),st | 相减 | st(i) <-st(i) - st(0),然后执行一次出栈操作 |
FIMUL src | 乘上一个整数 | st(0) <- st(0) * src |
FSTP dest | 目标地址赋st(0)值 | dest <- st(0) |
FLD src | 装入实数到st(0) | st(0) <- src |
FCOMP src | 比较 | 将st(0)和src比较 |
分析程序,逻辑很简单,依次读入CABD并转化为数字(设注册码格式为A-B-C-D),其中读入CA到st(1)和st(0)寄存器后,存储B除以A的结果到st(0),将C减去st(0)的值并存入st(0),将D的值和st(0)相乘,之后乘一个常数16,得到结果和常数384相比,相同则注册成功,伪代码如下:
C=C-0x30;
st(0)=C;
A=A-0x30;
st(0)=A;
st(1)=C;
st(0)=st(0)/B;
st(0)=st(1)-st(0);
st(0)=st(0)*D;
st(0)=st(0)*16;
if st(0)==384
goto success;
else
goto fail;

核心验证方程为:
16*(D*(C-A/B))=384
写个脚本:
for a in range(0,10):
for b in range(1,10):
for c in range(0,10):
for d in range(0,10):
if d*(c-a/b)==24:
break
print 'Found it!The code is: ',a,b,c,d
最后结果:

注:此题存在严重多解情况,满足该方程的值不只一个,大家可以试试。
[培训]科锐逆向工程师培训第53期2025年7月8日开班!