首先运行程序,熟悉程序流程。本程序是要求用户在文本框中输入数据,点击check按钮,如果没有通过校验则弹出带有"Wrong!"字符串的弹框。
将程序拖入IDA,查找字符串,没有找到Wrong字符串。运行程序,使用process excplorer查看程序内存中的字符串,发现有Wrong字符串。说明这个程序会在内存中解密出要使用的字符串,因此可以借助OD查找Wrong字符串引用地址。
运行程序,使用OD附加该进程。在主模块中查看字符串,果然找到了Wrong字符串。
如图,可以计算出该字符引用偏移为0x1FDE。
将程序拖入IDA,转到偏移0x1FDE处,按F5反编译该函数。该函数为sub_401EA0,简单看一下会发现,这个就是check的关键函数,函数逻辑如下:
从输入框就收用户输入。
然后会对输入进行初步检查
公式如下,分别要求输入字符串长度为16,输入字符要是ascii码。
之后会将wchar转换为char并存储到另一个字符串中,之后操作的都是char类型的字符串。
然后动态解密了一个函数,函数为sub_4010E0,大小为0xD17u。
通过查找byte_5647B8的引用,发现byte_5647B8起始的大小为0x330的数据之前在函数sub_401D80中进行过异或处理。
接下来就是调用解密后的sub_4010E0函数,如果该函数返回1就通过检查。
使用IDAPython脚本解密sub_4010E0函数,脚本代码如下:
反编译解密后的sub_4010E0函数。该函数将用户输入的16个字节的字符串划分为两个8字节的字符串,并把这两个字符串看做大整数进行了计算。具体逻辑如下:
取前8个字节的数据与 0x646E9881E38C9616异或,结果存储在v38;取后8个字节的数据与 0x4F484DBE81DC0884异或,结果存储在v44;
分别对v38和v44进行检查,要求v38和v44的第8个字节不为0,但是v38的第八个字节要小于0x10.
分别对v38和v44进行乘方运算,并将v44乘方结果乘上7。(代码太长就不贴了)
最后将计算两个结果的差值,并将差值与0x8比较,如果相等则返回1.
综上可知,实际就是要求v38 v38 = 7 v44 * v44 + 8,接下来尝试计算满足该公式的整数。
8字节的穷举空间太大,难以爆破。所以满足这个公式的数据必然有其特殊之处,因此先计算出一些满足公式的整数,观察其规律。
计算脚本如下:
计算结果如下:
可以发现每一个v38大概都是上一个v38的0x10倍,具体计算其比值如下:
发现这个比值越来越趋于稳定,大概在15.9372539和15.9372540之间,因此用其控制遍历空间。脚本代码调整如下:
运行结果如下:
当v38 > 0x55d5672587809a时就很难计算出结果了,查其原因是除法运算和开方运算出了问题,因为整数太大。而0x55d5672587809a之后的那个8个字节但第8字节小于0x10的数就是我们想要的,因此可以进行有针对的计算。计算脚本如下:
计算结果如下:
编写脚本计算最终的flag:
得到flag:L3mZ2k9aZ0a36DMM
CWnd::GetDlgItemTextW(v1, 1000, &input_str, 20);
wcslen(&input_str) == 16
(*(&input_str + v2) & 0xFF00) )
*(&tmpszChar + v2) = *((_BYTE *)&input_str + 2 * v2);
VirtualProtect(sub_4010E0, 0xD17u, 0x40u, &flOldProtect);
//...
qmemcpy(sub_4010E0, byte_5647B8, 0x330u);
VirtualProtect(sub_4010E0, 0xD17u, flOldProtect, &v8);
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课
最后于 2019-6-24 17:56
被kanxue编辑
,原因: