easy_flat
本题涉及代码混淆,具体是控制流平坦化
直接拖入IDA,F5:
然后查看流程框图:
经过晴宇哥的指点以后,我去搜了一些关于控制流平坦化的资料:
实际上,只是控制流程的方式变了,这道题相对简单,我们还是能够看出流程来。
继续分析伪代码,先看到一个长得像scanf的函数,把里面参数重命名为input,然后继续往下看,发现其中存在一个字符串比较的过程,点击查看被比较的另一个字符串后,发现是这样的字符串,长得很像flag,应该就是flag被加密后的形式.
现在就是要去寻找加密的方式,查看input被引用的地方,发现也就是这:
cnss-re-snake
刚看到这道题目的时候有点懵,因为从来没有用过CheatEngine进行逆向调试,题目提示可以使用CE进行调试,于是我就先学了一波CE的教程,具体过程前文已经写了。
但是,学完使用CE后,仍然不会逆,于是跑去请教炮王,炮王不愧是炮王,虽然没帮我拿到Flag,但是给我演示了静态调试和动态调试的过程,受益匪浅。
下面是逆的过程。
首先把文件拖到ida里进行静态调试。找到主函数。
这一步不需要看伪代码也能看出,就是六个函数的调用。
我们这时候打开游戏来看,首先看到有个菜单,根据C语言的经验,应该至少有一个switch语句和死循环。然后我们开始游戏一看,游戏就是个贪食蛇的游戏,提示是这样:
我们先用CE去搜得分,确实搜到了,但是正如提示的那样,直接修改是没有用的。
接着我们发现游戏失败时有对话框弹出,我们可以先尝试下搜索字符串。搜索到后查看调用:
发现这个字符串在 sub_4031EB
函数里被调用,我们搜索进入这个函数,发现里面全是一些失败的提示消息:
这里将这个函数名改成fail,以便于我们的理解。
fail函数被sub_4027BE
函数调用,而这个函数有两个分支,其中一个是fail,那另一个应该就是succeed了吧.找到进去一看,应该就是了,但是整个函数很复杂,可能就是计算出flag的过程.我们查看下那个可疑的 sub_4027BE
函数.查看之后,发现一个很熟悉的printf函数:
这个函数告诉我们,得分对应的参数就是显示出来的分数,我们将它命名为score.
往上一看,发现这个score的值是dword_40eDC0赋予的,这个也许就是存储得分的真正位置.
那就继续看dword_40eDC0这个什么时候被访问,往下看我们发现这样一段代码:
这里面调用的函数正是我们之前怀疑的succeed函数,他们原来是在这里py交易的!
仔细看这段代码,发现出题人是将真正的得分的低八位和0xE9H相与,判断相与后的值是否大于265.
抓住这一点我们就可以拿到Flag了,
这时候进行动态调试,这里用的是CE.
我们要先找到得分对应的真正位置,将其改成265^0xE9的值就好了.
还是先搜索得分,然后找出访问了这个得分的这段代码,发现长这样:
因为此时我们就在整个函数里面了,所以那个变量应该就在附近,我们看到483这个数字很可疑,因为1对应, —————————-我们找到这个变量的地址,将其修改成483,
再去游戏里面,就发现通关拿到flag了,flag是: cnss{CE_caN_ju5T_Act_w1lfulLy!!}
本题总结:
1、之前没有好好利用IDA去了解整个程序的主体就直接去动态调试,导致整个过程思路不明确,效率极低。
2、使用IDA进行调试时,可以用快捷键N修改变量名,函数名,这样有利于整个代码的阅读和理解。
Confusion
直接拖入IDA,F5
看到这个像scanf一样的函数,心里就有个底了。sub_426980
这个应该就是读入的函数.
进入下个函数查看,简单分析后,发现应该是判断输入的flag的长度,如果长度是32个字符,才能够进入下个函数.
再下面的函数,是用来判断输入的flag的前五位是否是”cnss{“,如果不是的话,程序也会直接跳出.
再接下来看到一个比较复杂的函数,里面有很多次循环,应该是一个加密的函数.函数很复杂,直接逆出来的话,难度相当大.这时候要采用动态调试的方法,在函数执行的时候把flag找出来.
直接在函数返回之前下好断点,在寄存器里就找到了flag
本题总结
1.IDA是真的好用
2.加密函数很复杂的时候,动态调试很顶