WHCTF 2017 逆向题 CRACKME、BABYRE、EASYHOOK 的解题思路
2017-09-20 13:21
573 查看
1、CRACKME
程序用 MFC 编写,查壳,没壳。直接运行,输入注册码,注册错误,弹框显示错误信息。可见程序执行逻辑很简单,并且猜测弹框显示是调用了 MessageBox 函数。用 IDA 打开,直接 F5 查看函数,发现在sub_4016E0 和 sub_401720 这两个函数里面都调用了 MessageBox 函数。
通过 IDA 的交叉引用功能,发现在.text:00401617 处调用了 sub_4016E0,往前翻可以看到很多信息,比如说对sub_401630 和 UpdateDate 函数的调用,以及.text:004015FB 和 .text:00401613 处的两个跳转。
于是猜测程序在这里通过UpdateDate 获取了注册码编辑框的输入注册码,然后先判断注册码长度是否为 0x21,接着在sub_401630 里面对注册码进行进一步验证,注册码正确则通过 sub_4016E0 弹出正确信息,错误则通过 sub_401720 弹出错误信息。
照这种思路,那么 sub_401630 验证函数就比较关键了,我们用 F5 查看如下:
可以知道,在函数里面对内存中的两处字符串进行了逐字符循环比较,这两处字符串应该就是我们输入的注册码和内存中的真码。在这里每一轮循环的种子和产生的随机数都是固定不变的,确保了正确的注册码的唯一性。
这时候就可以上 OD 调试了,在004015E0 处下断,输入任意长度为 0x21 的注册码,然后程序被断下。长度验证正确后单步进入 sub_401630,这时候在 00401669 处下断就可以观察到注册码的每一个字符了。
2、 BABYRE
在Linux 下用 file 命令查看,可知这是一个ELF64 文件,并且符号表没有被抽取掉,调试起来会好一点。用 IDA 打开,直接 F5 查看main 函数,然而报错。没关系,直接看图表视图就好。
在红框这一部分可以看到,程序通过 scanf 读取输入的 flag,然后有一个关于验证 flag 长度的跳转,正确长度为 0x0E。
这一部分红框可以看到,长度验证正确后调用 judge 函数进一步验证 flag,然后通过 puts 输出结果信息。
很自然这时候我们应该重点关注 judge 函数,我们双击 judge 跳转,可以知道 judge 的起始地址是 0x600B00,然而此时 judge 函数被加密了,解密过程在下图中的红框部分:
好,整个流程到现在已经分析清楚了,我们用 gdb 调试,在靠近 call judge 的地方下个断点。注意此时不能直接在 judge 函数里面下断点,否则解密时断点信息会被冲刷掉。
输入任意长度为 0x0E 的 flag,然后断了下来,单步步入 judge 函数里面。此时 judge 函数已经解密完成,分析可知:
上图红框为内存中存放的 flag。
上图红框部分对输入的 flag 做一个异或运算。
上图红框部分比较运算后的 flag 和内存中存放的 flag。
现在我们得到了内存中存放的 flag,那么只需要将这个 flag 做一个异或的逆运算就可以得到输入正确的 flag 了。
3、 EASYHOOK
查壳,没有壳。用 IDA 打开,F5 分析 main 函数如下:大概分析可得,输入的 flag 长度应为 19,长度验证正确后会先调用 sub_401220 函数,该函数功能未知。然后通过 CreateFileA 和 WriteFile 将输入的 flag 写入到一个文件里面,双击 FileName 可知是写入到本地目录下的 Your_Input 文件里面。接着调用 sub_401240 函数,因为传入了 buffer 和NumberOfBytesWritten 的地址,结合紧跟着 sub_401240 后面的一个关键判断,所以很可能
sub_401240 就是对 flag 进行验证的关键函数了。
从上面分析得知,输入的长度为 19 的 flag 会被写入到文件里面。然而测试之后发现,写入到文件里面的 flag 发生了改变。回顾 main 函数的执行流程,可知对 flag 的修改要么发生在 sub_401220 函数里面,要么是WriteFile 函数出了问题。由于题目的名称给出了 hook 的提示信息,于是猜测在 sub_401220 里面 hook 了WriteFile 函数。直接 F5 分析 sub_401220 函数,报错。查看汇编代码得知猜测正确,分析如下:
在 sub_401220 中获取进程句柄后跳转到loc_4011B0。
在 loc_401180 里面通过GetProcAddress 获取WriteFile 的地址,然后调用了sub_4010D0。注意红框框处的几个数据。
F5 查看 sub_4010D0,可知调用 VirtualProtectEx和 WriteProcessMemory 修改了 WriteFile 函数的起始 5 个字节。动态调试后发现修改为跳转到 sub_401080 的一条无条件跳转指令,从而实现了 hook WriteFile 的功能。
那么当 main 函数调用 WriteFile 的时候,程序将转去执行 sub_401080 函数。来看一下sub_401080:
首先调用 sub_401000 函数,分析参数传递可知参数 lpBuffer 即是我们输入的 flag,那么很有可能就是在 sub_401000 里面对 flag 进行了修改。然后调用 sub_401140 函数,接着又一次调用了WriteFile 函数。我们知道虽然 WriteFile 被 hook 了,但最后确实是把 flag 写入到了文件里面,所以很有可能是在 sub_401140 里面对 WriteFIle 进行了 hook 还原。最后对
sub_401000 的返回值进行判断,如果非 0 则将NumberOfBytesWritten 置 1。
先分析 sub_401140,证实了里面的 hook 还原操作。然后看一下 sub_401000,可知里面主要是两个循环处理:
这个循环处理比较简单,就不分析了。看接下来的一个循环:
这里就有一个很明显的字符串比较的意图了,结合上面的分析可知,我们输入的长度为 19 的 flag 经过第一个循环的处理之后,如果和 byte_40A030 指向的全局字符串相同,那么 sub_401000 返回 1。在 sub_401080 里面对sub_401000 的返回值进行判断,如果返回值为 1,则将NumberOfBytesWritten 置 1。然后在最外层的 main函数里面进行判断,如果NumberOfBytesWritten 为
1,则输出正确的提示信息。
所以,我们只需要将 byte_40A030 指向的字符串做一次 sub_401000 函数里面第一个循环处理的逆运算,就可以得到输入正确的 flag 了。
当然别忘了在 main 函数里面的 sub_401240 函数,我们刚开始时分析认为在 sub_401240 里面对输入的 flag 做了关键验证,但事实上真正的验证函数是 sub_401000,只要 sub_401000 验证正确即可。sub_401240 只是一个幌子,纯属糊弄人的。
相关文章推荐
- 南邮CTF逆向题第一道Hello,RE!解题思路
- 南邮CTF逆向题第五道maze解题思路
- 看雪CTF 2017 第六题设计思路和解题思路
- CrackME 2011 # 2 逆向练习解题思路
- 南邮CTF逆向题第二道ReadAsm2解题思路
- 南邮CTF逆向题第三道Py交易解题思路
- 171104 逆向-上海CTF(Re)
- 牛客网-网易2017春招笔试真题编程题集合-解题思路及源码
- 牛客网-2017网易游戏雷火盘古实习生招聘笔试真题-解题思路及源码
- 西普ctf解题思路——《貌似有点难》
- 牛客网-网易2017秋招编程题集合-解题思路及源码
- 西普ctf解题思路-——《Fobidden》
- 170920 逆向-CTF练习平台(RE-love)
- 牛客网-网易2017内推笔试编程题合集(二)-解题思路及源码
- 练习-CTF解题 - XMAN比赛 8-8-babyweb(netspark扫扫)
- 0ctf 2017 babyheap writeup
- Dungeon Game | leetcode 解题思路
- ACM1174_爆头解题思路_空间三维坐标求点到直线的距离
- 2017-2018-2 《网络对抗技术》 20155302 第二周 Exp1 PC平台逆向破解(5)M
- [面试算法]链表类面试算法解题思路