之前我们介绍了如何开始使用反编译器,但未经修改的反编译器输出并不总是易于阅读,特别是在二进制文件没有符号或调试信息的情况下。
然而,只需进行一些小的修改,您就可以显着改善结果。让我们看一下伪代码视图中可用的一些基本交互操作。
重命名
虽然听起来微不足道,但重命名可以极大地提高可读性。
即使是像将 v3 重命名为 counter 这样简单的事情也可以立即清晰地了解函数中发生的情况。
结合 IDA 7.6 中添加的自动重命名功能,这可以帮助您在分析时通过伪代码传播好听的名称。
以下项目可以直接在伪代码视图中重命名:
-
local variables -
function arguments -
function names -
global variables (data items) -
structure members
重命名非常简单:将光标放在要重命名的项目上,然后按 N 与反汇编列表中使用的快捷键相同。
当然,该命令也可以在上下文菜单中找到重命名选项:
您还可以选择在反汇编视图中而不是伪代码中进行重命名。
如果您打算重命名一个大函数中的许多项目并且不想每次都等待反编译完成,这会很有用。
完成重命名后,按 F5 刷新伪代码并查看所有新名称。请注意,寄存器分配的局部变量不能在反汇编中重命名;它们只能在伪代码视图中进行管理。
类型修正
类型恢复是反编译中最难的问题之一。
一旦代码转换为机器指令,就不再有类型,而只有原始内存布局。
尽管如此,反编译器仍然可以做出一些猜测,例如正在处理的数据的大小,以及在某些情况下是否将其视为有符号值,但总的来说,高级类型恢复仍然是一个挑战,而人脑可以在其中提供很大帮助。
例如,考虑这个小 ARM 函数
sub_4FF203A8
SUB R2, R0, #1
loc_4FF203AC
LDRB R3, [R1],#1
CMP R3, #0
STRB R3, [R2,#1]!
BNE loc_4FF203AC
BX LR
其最初的反编译如下所示:
我们看到反编译器可以猜测第二个参数(a2,在 R1 中传递)的类型,因为它用在 LDRB 指令(加载字节)中。
然而,v2 仍然是一个简单的 int,因为对其进行的第一个操作是一个简单的算术 SUB(减法)。
现在,经过一番思考,很明显 v2 和 result 也是字节指针,而减法只是指针数学(因为指针只是 CPU 级别的数字)。
我们可以通过将两个变量的类型更改为相同的 unsigned __int8 *
(或等效的 unsigned char *
)来解决问题。
为此,请将光标放在变量上并按 Y,或使用上下文菜单中的“Set lvar type”。
或者,您可以使用第一行中函数名称的快捷方式直接编辑函数原型,而不是先固定局部变量,然后再固定参数。
在这种情况下,第一个参数的类型将自动传播到局部变量中,您无需手动更改它(用户提供的类型优先于猜测的类型)。
原文始发于微信公众号(二进制磨剑):IDA 技巧(42) 反编译中的重命名与类型修复
- 左青龙
- 微信扫一扫
- 右白虎
- 微信扫一扫
评论