IDA 技巧(53) IDA switch 分析

admin 2024年9月13日11:11:03评论15 views字数 2672阅读8分54秒阅读模式

IDA支持大多数流行编译器生成的 switch 模式,通常您不需要担心这些模式。然而,您可能会偶尔遇到由不常见或非常新的编译器版本生成的代码,或者代码的某些特性可能会阻止IDA识别该模式,这时您可能需要帮助IDA,告知它有关 switch 的信息,以便能够呈现适当的函数图,并使反编译器能够生成良好的伪代码。

switch 模式组件

常见的 switch 模式通常由以下组件构成:

  1. 间接跳转
    这是执行跳转到处理该 switch 案例的目标块的指令;通常涉及某个寄存器保存地址值。
  2. 跳转表
    一个值的表,包含目标块的直接地址或允许计算这些地址的其他值(例如,从某个基址的偏移量)。它必须具有特定的固定大小(元素数量),并且值可以通过移位值进行缩放。有些 switch 可能使用两个表,第一个表包含指向第二个表的索引,第二个表则包含地址。
  3. 输入寄存器
    包含用于确定目标块的初始值的寄存器。最常见的是,它用于索引跳转表。

switch 公式

标准 switch 假定使用以下计算来确定目标地址:

target = base +/- (table_element << shift)

如果不使用,baseshift可以设置为零。

示例

以下是来自ARM64固件的代码片段。

IDA 技巧(53) IDA switch 分析

ARM64 switch 示例

间接跳转用红色矩形突出显示。以下是相同代码的文本格式:

__text:FFFFFF8000039F88 STP X22, X21, [SP,#-0x10+var_20]!
__text:FFFFFF8000039F8C STP X20, X19, [SP,#0x20+var_10]
__text:FFFFFF8000039F90 STP X29, X30, [SP,#0x20+var_s0]
__text:FFFFFF8000039F94 ADD X29, SP, #0x20
__text:FFFFFF8000039F98 MOV X19, X0
__text:FFFFFF8000039F9C BL sub_FFFFFF80000415E4
__text:FFFFFF8000039FA0 B.HI loc_FFFFFF800003A01C
__text:FFFFFF8000039FA4 MOV W20, #0
__text:FFFFFF8000039FA8 ADR X9, byte_FFFFFF8000048593
__text:FFFFFF8000039FAC NOP
__text:FFFFFF8000039FB0 ADR X10, loc_FFFFFF8000039FC0
__text:FFFFFF8000039FB4 LDRB W11, [X9,X8]
__text:FFFFFF8000039FB8 ADD X10, X10, X11,LSL#2
__text:FFFFFF8000039FBC BR X10

我们可以看到,在间接分支中使用的寄存器(X10)是某种计算的结果,因此它可能是一个 switch 模式。然而,由于代码是使用尺寸优化编译的(范围检查被移动到一个从多个地方使用的单独函数中),IDA无法自动匹配该模式。让我们看看是否可以识别上述标准 switch 的组件。

该公式与指令ADD X10, X10, X11,LSL#2相匹配(用C语法表示为:X10 = X10+(X11<<2))。我们可以看到,表元素(X11)在添加到基址(X10)之前被移位了2。X11的值来自于之前使用LDRB(加载字节)从X9的表中获取的W11,并使用索引X8。因此:

  1. 间接跳转:是的,BR X10指令位于FFFFFF8000039FBC
  2. 跳转表:是的,位于byte_FFFFFF8000048593。此外,我们有一个基址loc_FFFFFF8000039FC0移位值为2。它包含八个元素(可以通过视觉检查或从使用7作为最大允许值的范围检查推断得出)。
  3. 输入寄存器:是的,X8用于索引表(我们也可以使用W8,它是X8的32位部分,并由范围检查函数使用)。

现在我们有了所有信息,可以通过将光标放在间接分支上并调用编辑 > 其他 > 指定 switch 习语来指定模式...

IDA 技巧(53) IDA switch 分析

指定 switch 对话框

值可以用C语法(0x…)或标签的方式指定,这得益于表达式评估功能。一旦确认对话框,我们可以观察到 switch 被很好地标记,并且函数图也更新以包含新可达节点。

IDA 技巧(53) IDA switch 分析

更新的 switch 图

我们还可以使用“列出来自...的交叉引用”(Ctrl-J)查看间接跳转的目标列表。

IDA 技巧(53) IDA switch 分析

交叉引用列表

其他选项

我们的示例相当简单,但在某些情况下,您可以利用对话框中的其他选项。

  1. 存在单独的值表:  当使用两级表时,即table_element = jump_table[value_table[input_register]];而不是默认的table_element = jump_table[input_register];

  2. 带符号跳转表元素:  当表元素使用符号扩展指令加载时,例如在ARM上使用LDRSBLDRSW,或在x86上使用movsx

  3. 减去表元素:  如果值是从基址中减去而不是添加(公式中使用负号)。

  4. 表元素是指令:  “跳转表”包含指令而不是数据值。这在某些架构中使用,可以使用指令指针的增量值执行相对跳转。

    例如,传统的ARM跳转使用直接的PC操作:

    CMP             R3, #7 ;  switch  ;  switch 8个案例           
    ADDLS PC, PC, R3,LSL#2 ; switch 跳转

通常在这种情况下表“元素”是固定大小的分支,指向实际的目标。

可选值

某些值可以默认省略,但您也可以填写它们以更完整地映射到原始代码:

  1. switch 的输入寄存器:如果您只需要交叉引用以获得适当的函数流图,则可以省略,但如果您希望反编译器正确解析和表示 switch ,则必须指定。
  2. 第一个(最低)输入值:  输入寄存器对应于跳转表的条目0的值。在上面的示例中,我们可以看到范围检查计算W8 = W1 - 1,因此我们可以指定最低值为1(这也会将目标地址的注释更新为1到8,而不是0到7)。
  3. 默认跳转地址:  当输入范围检查失败时执行的地址(在我们的示例中 - B.HI指令的目标)。可以使列表和/或反编译更整洁,但否则并不是严格要求的。

有关支持的 switch 模式的更多详细信息,请参见switch_info_t结构和SDK中的uiswitch插件源代码。如果您遇到无法通过标准公式处理的 switch ,您还可以考虑编写自定义跳转表处理器。

更多文章

添加小助手微信加入交流群: OxCSorder

立即关注【二进制磨剑】公众号

👉👉👉【IDA 技巧合集】👈👈👈
👉👉👉【Github 安全项目合集】👈👈👈

原文始发于微信公众号(二进制磨剑):IDA 技巧(53) IDA switch 分析

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年9月13日11:11:03
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   IDA 技巧(53) IDA switch 分析https://cn-sec.com/archives/3162101.html

发表评论

匿名网友 填写信息