hd的师傅们出的题还是十分有意思的……这道题花了很多天时间才有了头绪,现在才搞出来。
我们把程序扔进ida反复调试后发现了一个奇怪的函数:sub_401460(v10),这个函数将我们输入的数字进行操作。我们点进去看:
很懵逼,没有见过的底层函数,和奇奇怪怪的变量名称。由于内部对toplevelexceptionfilter变量进行的操作比较多,我们首先关注这个变量。
在每次调试的时候都发现toplevelexceptionfilter的初始值始终是0x401000,点进TopLevelExceptionFilter发现是一个函数,因此我们可以大致确定TopLevelExceptionFilter应当是一个指向函数的指针,对其的操作都是相当于改变了整个程序在某一处的流程。
那么改变的到底是什么流程呢?我们不妨将这段函数换成汇编代码进行调试
对这段流程进行分析,我们能够大致知道:
假设我们输入的数为ip,将TopLevelExceptionFilter记为tp,则最终程序会转移到地址为*(tp+(ip>>3))^(1<<(ip&7))的地方
但是为什么要这么转移呢?因为程序本身存在一个问题:
若不加修改,4018de处的代码会直接跳入4018f5,然后进入sub_4014FA函数,但是函数的参数并没更新,0x4018e5处对函数参数赋值的代码并没有进行,所以函数的执行会有问题,最终得到我们不希望的结果。
所以我们要让tp最终存的值为0x4018e5。
jmp short loc_4018F5的机器码是EB 15 ,其中EB表示jmp,15表示偏移,即:0x15 = 0x4018F5 - 0x4018DE - jmp指令长度(2字节)
我们要跳到 loc_4018E5,即0x5 = 0x4018e5-0x4018de-0x2
0x4018de存的是jmp指令,0x4018df存的是loc_4018f5,即偏移量0x15
因此tp初始为401000,先加上0x8df得到0x4018df,在将此处存的0x15异或一个值得到0x5。
显然需要异或0x10,即(1<<4),所以输入的值的低三位为4,剩下的位数为0x8df。
(0x8df<<3)+4=18172,我们要输入的数字就是18172。
后面的字符串加密就比较简单了,先将输入的字符串base64加密后每一个位都异或1,然后和打开的文本的后几位比较。
最后解密能得到字符串Byt3_H4cker_sho0O0o0t!