160个CrackMe之111,一个关于浮点数操作的简单小程序
最近在学安卓,没咋上论坛,主要也没啥时间。今晚还是腾出了一点时间去搞之前的crackme。这次程序比之前发的053,081都要简单不少,但同样在论坛上没有找到破解的序列号,
https://www.52pojie.cn/thread-921654-1-1.html
https://www.52pojie.cn/thread-926825-1-1.html
程序主界面看上去很普通,一个Name/Serial的CM,不过分析后会发现还是比一般Name/Serial要简单的
程序很小,基本上不存在关键点定位的问题,貌似其他五星难度的也都很容易定位,基本就是纯算法逆向。
当然了,这个程序肯定不会有五星,如果不是操作浮点数的话,我觉得就是一个一星题。
很明显,上面两个获取name,Serial文本内容,下面两个弹窗判断,而验证函数就是中间夹着的sub_0040134A 了。返回1正确,0错误
跟进去之后,整个代码也没多长,不过都是一些浮点数的计算。半个多月不接触X86很多都记不得了(其实本来也没记得这些不怎么常用的指令)
这时候我们,上IDA F5X
当然是去学习这些指令啊√
进入到函数内部,它直截了当地就把name和Serial转变成了浮点数(atof),并向下取整(floor)
0040134A/$55 PUSH EBP
0040134B|.89E5 MOV EBP,ESP
0040134D|.83EC 68 SUB ESP,0x68
00401350|.FF75 08 PUSH ; /s = "245850922"
00401353|.E8 78010000 CALL <JMP.&CRTDLL.atof> ; \atof
00401358|.DD55 E8 FST QWORD PTR SS:
0040135B|.83EC 08 SUB ESP,0x8
0040135E|.DD1C24 FSTP QWORD PTR SS:
00401361|.E8 82010000 CALL <JMP.&CRTDLL.floor>
00401366|.DD5D F8 FSTP QWORD PTR SS:
00401369|.FF75 0C PUSH ; /s = "411557987"
0040136C|.E8 5F010000 CALL <JMP.&CRTDLL.atof> ; \atof
00401371|.DD55 D8 FST QWORD PTR SS:
00401374|.83EC 08 SUB ESP,0x8
00401377|.DD1C24 FSTP QWORD PTR SS:
0040137A|.E8 69010000 CALL <JMP.&CRTDLL.floor>
0040137F|.83C4 18 ADD ESP,0x18
00401382|.DD55 F0 FST QWORD PTR SS:
紧接着进行了一系列地判断,当然很多都是多余地判断
并且每个判断形式都差不多,搞懂一个其他的也就一个样。(实际上只有前两个判断起作用)
第一步,先将上面得到的两个整数相乘,并且和0比较,若为0则直接return 0;
第二个判断是比较name和Serial,它们不能相等.
第三个第四个是为了name和Serial不为0(1成立的条件下这是必然的)
下两个是为了使name和Serial小于10000000000(也是多余的,因为在之前GetDlgItemText的时候指定了最大读取10位)
00401377|.DD1C24 FSTP QWORD PTR SS:
0040137A|.E8 69010000 CALL <JMP.&CRTDLL.floor>
0040137F|.83C4 18 ADD ESP,0x18
00401382|.DD55 F0 FST QWORD PTR SS: ;name压入st0
00401385|.DC4D F8 FMUL QWORD PTR SS: ;name*psd
00401388|.D9EE FLDZ ;压入0
0040138A|.DED9 FCOMPP ;比较st0,st1;name*psd与0比较
0040138C|.DFE0 FSTSW AX ;设置AX为FST
0040138E|.9E SAHF ;AH赋值给段寄存器低8位
0040138F|.75 07 JNZ SHORT 111.00401398 ;name*psd不能等于0
00401391|.31C0 XOR EAX,EAX
00401393|.E9 96000000 JMP <111.return eax>
00401398|>DD45 F8 FLD QWORD PTR SS: ;name
0040139B|.DC5D F0 FCOMP QWORD PTR SS:
0040139E|.DFE0 FSTSW AX ;name不能等于psd
004013A0|.9E SAHF
004013A1|.75 07 JNZ SHORT 111.004013AA
004013A3|.31C0 XOR EAX,EAX
004013A5|.E9 84000000 JMP <111.return eax>
004013AA|>DD45 F8 FLD QWORD PTR SS:
004013AD|.DD5D C8 FSTP QWORD PTR SS: ;name
004013B0|.D9E8 FLD1
004013B2|.DD55 C0 FST QWORD PTR SS: ;40:1.0
004013B5|.DC5D C8 FCOMP QWORD PTR SS: ;name不能为0(貌似这步判断没什么用)
004013B8|.DFE0 FSTSW AX
004013BA|.9E SAHF
004013BB|.77 2D JA SHORT <111.return 0>
004013BD|.DF2D 38304000 FILD QWORD PTR DS: ;10000000000.00000000
004013C3|.DD55 B8 FST QWORD PTR SS:
004013C6|.DC5D C8 FCOMP QWORD PTR SS:
004013C9|.DFE0 FSTSW AX
004013CB|.9E SAHF
004013CC|.72 1C JB SHORT <111.return 0> ;name需小于10000000000.00000000
004013CE|.DD45 F0 FLD QWORD PTR SS:
004013D1|.DD5D B0 FSTP QWORD PTR SS: ;50:psd
004013D4|.DD45 C0 FLD QWORD PTR SS: ;40:1.0
004013D7|.DC5D B0 FCOMP QWORD PTR SS: ;psd不能为0
004013DA|.DFE0 FSTSW AX
004013DC|.9E SAHF
004013DD|.77 0B JA SHORT <111.return 0>
004013DF|.DD45 B8 FLD QWORD PTR SS:
004013E2|.DC5D B0 FCOMP QWORD PTR SS:
004013E5|.DFE0 FSTSW AX
004013E7|.9E SAHF ;psd需小于10000000000.00000000
004013E8|.73 04 JNB SHORT 111.004013EE
004013EA >|>31C0 XOR EAX,EAX
004013EC|.EB 40 JMP SHORT <111.return eax>
判断完就是一系列的计算,将name和Serial求正线值再乘10的16次方,最终将结果向下取整,若结果为0,则返回1
004013EC|. /EB 40 JMP SHORT <111.return eax>
004013EE|> |DD45 F8 FLD QWORD PTR SS:
004013F1|. |D9FE FSIN
004013F3|. |DD5D A8 FSTP QWORD PTR SS: ;0x58:sin(name)
004013F6|. |DD45 F0 FLD QWORD PTR SS:
004013F9|. |D9FE FSIN
004013FB|. |DD5D A0 FSTP QWORD PTR SS: ;0x60:sin(psd)
004013FE|. |DD45 A8 FLD QWORD PTR SS:
00401401|. |DC4D A0 FMUL QWORD PTR SS: ;sin(name)*sin(psd)
00401404|. |DF2D 30304000 FILD QWORD PTR DS: ;10^16
0040140A|. |DEC9 FMULP ST(1),ST ;sin(name)*sin(psd)*10^16
0040140C|. |83EC 08 SUB ESP,0x8
0040140F|. |DD1C24 FSTP QWORD PTR SS:
00401412|. |E8 D1000000 CALL <JMP.&CRTDLL.floor>
00401417|. |83C4 08 ADD ESP,0x8
0040141A|. |DD5D 98 FSTP QWORD PTR SS:
0040141D|. |D9EE FLDZ
0040141F|. |DC5D 98 FCOMP QWORD PTR SS:
00401422|. |DFE0 FSTSW AX
00401424|. |9E SAHF
00401425|. |75 05 JNZ SHORT <111.return 0> ;sin(name)*sin(psd)*10^16需要小于1
00401427|. |31C0 XOR EAX,EAX
00401429|. |40 INC EAX
0040142A|. |EB 02 JMP SHORT <111.return eax>
0040142C >|> |31C0 XOR EAX,EAX
0040142E >|> \C9 LEAVE
0040142F\.C3 RETN
整个流程这么多,因该还是比较容易的,就是浮点计算的汇编看的有点陌生,下面就是写注册机。
两个不相同的整数取正弦值相乘,再乘10^16,最终结果要小于1大于0(向下取整为0)
而这两个整数的范围是一开始获取文本内容时候就确定的,最高10位字符串(包含0),而并非后面的10000000000
所以我们只要保证每个正弦的值小于10的-8次方就行了(也就是最高10的-9)
然后就可以很容易写出注册机了,当然需要注意一下两个sin的符号需要同号
#include <vector>
vector<DWORD64> res;
int main()
{
printf("第一组\n");
for (DWORD64 i = 1; i < 1000000000; i++)
{
if (sin(i) < 1e-8&&sin(i) > -(1e-8))
{
if (sin(i) > 0)
printf("%lld\n", i);
else
res.push_back(i);
}
}
printf("第二组\n");
for (DWORD i = 0; i < res.size(); i++)
printf("%lld\n", res);
return 0;
}
当然,也可以不穷举,通过sin(n*pi)=0去写注册机,不过试了下只用double去存pi的话貌似还不够精准。
如果有大佬有什么好方法的话也欢迎来讨论{:17_1082:}
支持一下。 不错 支持下 能不能带做项目
页:
[1]