首页
社区
课程
招聘
[原创]第四题:达芬奇密码
发表于: 2019-6-18 09:53 4211

[原创]第四题:达芬奇密码

2019-6-18 09:53
4211

首先运行程序,熟悉程序流程。本程序是要求用户在文本框中输入数据,点击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);

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

最后于 2019-6-24 17:56 被kanxue编辑 ,原因:
收藏
免费 3
支持
分享
最新回复 (1)
雪    币: 1475
活跃值: (74)
能力值: ( LV5,RANK:75 )
在线值:
发帖
回帖
粉丝
2
看了大佬的wp,这可能是最菜的一种解法了
2019-6-24 21:52
0
游客
登录 | 注册 方可回帖
返回
//