IDA 技巧(4) More selection!

admin 2024年4月7日10:00:23评论5 views字数 4912阅读16分22秒阅读模式

More selection!

如果没有看过上一篇 tips,建议先看看上一篇,了解一下 “选择” 是什么!

固件/原始二进制分析

在反汇编原始二进制文件时,IDA并不总是能够检测到代码片段,可能需要你手动尝试和试错来在整个加载范围中找到代码,这可能是一个耗时的过程。

在这种情况下,以下简单方法可能对初步寻找代码片段有用:

  1. 前往起始地址(IDA 反汇编视图的最顶端)(Ctrl+PgUp)
  2. 开始选中(锚点选择,见上一篇 tips)(Alt + L)
  3. 前往结束地址(IDA 反汇编视图的最底端)(Ctrl+PgDn)你也可以前往任何你想结束的位置,比如在一堆 0xFF 的前面。
  4. 点击菜单项【Edit】→ 【Code】 或快捷键 C,你将看见一个对话框,询问你更加具体的操作,如下图

IDA 技巧(4) More selection!

  1. 点击 “Force”,如果选择的范围里大部分都是指令。或者 “Analyse”,如果选择的范围里指令之间有数据。
  2. IDA 会分析你选择的区间,并尝试将未定义的数据转换成指令。如果选定区域确实有有效的代码,你可能会看到函数被添加到函数窗口中(可能包括一些误报)。

结构体偏移

另一个“选择”的有用应用是对多个指令应用结构偏移。例如,让我们考虑一个来自UEFI模块的函数:

.text:0000000000001A64 sub_1A64        proc near               ; CODE XREF: sub_15A4+EB↑p
.text:0000000000001A64                                         ; sub_15A4+10E↑p
.text:0000000000001A64
.text:0000000000001A64 var_28          = qword ptr -28h
.text:0000000000001A64 var_18          = qword ptr -18h
.text:0000000000001A64 arg_20          = qword ptr  28h
.text:0000000000001A64
.text:0000000000001A64                 push    rbx
.text:0000000000001A66                 sub     rsp, 40h
.text:0000000000001A6A                 lea     rax, [rsp+48h+var_18]
.text:0000000000001A6F                 xor     r9d, r9d
.text:0000000000001A72                 mov     rbx, rcx
.text:0000000000001A75                 mov     [rsp+48h+var_28], rax
.text:0000000000001A7A                 mov     rax, cs:gBS
.text:0000000000001A81                 lea     edx, [r9+8]
.text:0000000000001A85                 mov     ecx, 200h
.text:0000000000001A8A                 call    qword ptr [rax+50h]
.text:0000000000001A8D                 mov     rax, cs:gBS
.text:0000000000001A94                 mov     r8, [rsp+48h+arg_20]
.text:0000000000001A99                 mov     rdx, [rsp+48h+var_18]
.text:0000000000001A9E                 mov     rcx, rbx
.text:0000000000001AA1                 call    qword ptr [rax+0A8h]
.text:0000000000001AA7                 mov     rax, cs:gBS
.text:0000000000001AAE                 mov     rcx, [rsp+48h+var_18]
.text:0000000000001AB3                 call    qword ptr [rax+68h]
.text:0000000000001AB6                 mov     rax, [rsp+48h+var_18]
.text:0000000000001ABB                 add     rsp, 40h
.text:0000000000001ABF                 pop     rbx
.text:0000000000001AC0                 retn
.text:0000000000001AC0 sub_1A64        endp

如果我们知道 gBS 是指向 EFI_BOOT_SERVICES 的指针,我们就可以将对它的访问(在调用指令中)转换为结构偏移。()

我们可以手动为每个访问执行此操作,但这很繁琐。

在这种情况下,选择功能就非常有用。如果我们选择访问结构的指令并按下 T 键(结构偏移),将会弹出一个新对话框:

IDA 技巧(4) More selection!

你可以选择将哪个寄存器用作基寄存器,应用哪种结构,甚至可以选择要转换的具体指令。

选择 raxEFI_BOOT_SERVICES 后,我们得到了一个看起来很整洁的列表:

.text:0000000000001A64 sub_1A64        proc near               ; CODE XREF: sub_15A4+EB↑p
.text:0000000000001A64                                         ; sub_15A4+10E↑p
.text:0000000000001A64
.text:0000000000001A64 Event           = qword ptr -28h
.text:0000000000001A64 var_18          = qword ptr -18h
.text:0000000000001A64 Registration    = qword ptr  28h
.text:0000000000001A64
.text:0000000000001A64                 push    rbx
.text:0000000000001A66                 sub     rsp, 40h
.text:0000000000001A6A                 lea     rax, [rsp+48h+var_18]
.text:0000000000001A6F                 xor     r9d, r9d        ; NotifyContext
.text:0000000000001A72                 mov     rbx, rcx
.text:0000000000001A75                 mov     [rsp+48h+Event], rax ; Event
.text:0000000000001A7A                 mov     rax, cs:gBS
.text:0000000000001A81                 lea     edx, [r9+8]     ; NotifyTpl
.text:0000000000001A85                 mov     ecx, 200h       ; Type
.text:0000000000001A8A                 call    [rax+EFI_BOOT_SERVICES.CreateEvent]
.text:0000000000001A8D                 mov     rax, cs:gBS
.text:0000000000001A94                 mov     r8, [rsp+48h+Registration] ; Registration
.text:0000000000001A99                 mov     rdx, [rsp+48h+var_18] ; Event
.text:0000000000001A9E                 mov     rcx, rbx        ; Protocol
.text:0000000000001AA1                 call    [rax+EFI_BOOT_SERVICES.RegisterProtocolNotify]
.text:0000000000001AA7                 mov     rax, cs:gBS
.text:0000000000001AAE                 mov     rcx, [rsp+48h+var_18] ; Event
.text:0000000000001AB3                 call    [rax+EFI_BOOT_SERVICES.SignalEvent]
.text:0000000000001AB6                 mov     rax, [rsp+48h+var_18]
.text:0000000000001ABB                 add     rsp, 40h
.text:0000000000001ABF                 pop     rbx
.text:0000000000001AC0                 retn
.text:0000000000001AC0 sub_1A64        endp

强制字符串常量

当一些代码引用字符串时,IDA通常足够智能地检测到它,并将引用的字节转换为文字项。然而,在某些情况下,自动转换不起作用,例如:

  • 字符串包含非ASCII字符;
  • 字符串没有以空字符结尾。

一个常见的例子是 Linux 内核,它使用特殊的字节序列来标记内核消息的不同类别。

例如,考虑 joydev.ko 模块中的这个函数:

IDA 技巧(4) More selection!

IDA没有在1BC8处自动创建字符串,因为它以一个非ASCII字符开头。然而,如果我们选择字符串的字节并按下快捷键(转换为字符串),字符串仍然会被创建:

IDA 技巧(4) More selection!

从数据创建结构体

当处理二进制文件中的结构化数据时,这个动作非常有用。我们考虑一个表,其条目大致有如下布局:

struct copyentry {
 void *source;
 void *dest;
 int size;
 void* copyfunc;
};

虽然这样的结构体总是可以在结构体窗口中手动创建,但通常先格式化数据再创建描述它的结构体更容易。

创建四个数据项后,选择它们,从上下文菜单中选择 “Create struct from selection”:

IDA 技巧(4) More selection!

IDA 将创建一个代表所选数据项的结构体,然后可以使用它来格式化程序中的其他条目,或在反汇编中更好地理解与这些数据交互的代码。

IDA 技巧(4) More selection!

原文始发于微信公众号(二进制磨剑):IDA 技巧(4) More selection!

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年4月7日10:00:23
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   IDA 技巧(4) More selection!https://cn-sec.com/archives/2634313.html

发表评论

匿名网友 填写信息