我们在使用IDA进行逆向分析的时候,会遇到一些问题,这篇文章来带领大家学习IDA中疑难杂症的修复:函数大小限制,栈不平衡,switch无法识别(跳转表修复),ida Decompile as call。
一.函数大小限制
通常IDA反编译函数时会有大小限制,超过这个大小就会反编译失败,而这个大小是我们可以修改的。
修改方法:
打开IDA的安装目录,找到cfg文件夹下的hexray.cfg,搜索MAX_FUNCSIZE将64改为1024。
二.堆栈平衡
如果函数堆栈不平衡,会导致IDA positive反编译出错。
网上关于这个问题的教程多数都是让调栈指针,然后怎么alt+k如何去修复,其实他们没有发现问题的本质,一旦稍微变化,就无法解决IDA重新反编译,这种问题应该对症下药。
总的来说思路就是:因为这种情况出现的原因时函数堆栈不平衡,这个时候就应该去检查函数中对栈进行操作的指令,并判断是否平衡
分析方法:
-
- 分析函数头函数尾,检查堆栈是否平衡
-
- 当函数头函数尾平衡时,我们分析函数内部对栈操作的指令,以及部分函数的调用约定是否识别正确(调用约定识别不正确也会破坏堆栈平衡)
三.switch无法识别(跳转表识别)
我们想要修复switch,必须先对switch case汇编进行分析,识别出这是switch case语句,之后再进行修复。
修复方法:
光标移动到switch语句的值的哪一行(通常是mov,eax eax),然后选择Edit->Other->Specify Switch idiom,这时候就会跳出来一个窗口,让我们修复switch语句。
参数填写:
- Address Of jump table:跳转表的首地址
Number of elements:跳转表的项数(这个学过C++汇编的同学肯定会识别),也就是switch中,除default的case个数
Size of table element:跳转表每一项的字节数(一般就是从lea rax,da 0[rax*4]这条指令或者直接去跳转表查看得到,也有可能是其他固定值)
Element base value:跳转表偏移的基地址,观察汇编得到偏移与跳转表的首地址相加,跳转表中的偏移时相对于跳转表首地址的,也有可能是其他固定值。
Start of the idiom switch:switch语法的起始地址
Input register of switch:switch(var)中的var对应的寄存器(该寄存器应该是switoidiom处的)
Signed jump table elements:跳转表的元素是有符号的,因为有负数
其他没有提到的选项,默认即可,再次按下F5反编译即可得到正确的结果。
四.ida Dwcompile as call
场景一:
强网杯某vm逆向
设想这样一种情况:在某个自定义的运行环境中,syscall
上图的自定义环境中的rax的值作为syscall的调用符号,返回结果也是通过rax传递
默认情况下,ida认为此处的syscall不会修改rax的值,导致rax寄存器常量传播优化,最后得到的代码结果如下:
从上图中可以看出,ida会直接进行常量传播优化,那肯定时错的。
ida直接将某一条指令强行解释为函数调用,操作方法:
-
- 选中syscall指令
-
- 菜单->Edit->Other->Decompile as call
-
- 输入函数定义
场景二:
由于两次fs:0读取,ida会认为两次读取结果一样,就只会保留一次结果,实际上,vm在每次读取fs:0的时候,修改fs:0,这就导致错误
错误的反编译结果如下:
修改方法:将两次读取fs:0的指令用Decompile as call定义为:__int64 GetKey();不给参数,效果很好。