飘云阁

 找回密码
 加入我们

QQ登录

只需一步,快速开始

查看: 1314|回复: 3

[其它] [IDA使用技巧]#04: 更多选择功能!

[复制链接]
  • TA的每日心情
    开心
    2019-3-15 11:00
  • 签到天数: 262 天

    [LV.8]以坛为家I

    发表于 2024-2-28 10:46:49 | 显示全部楼层 |阅读模式
    翻译:梦幻的彼岸
    上一篇文章中,我们介绍了 IDA 中选择功能的基本用法。本周,我们将再介绍几个受选择影响的操作示例。
    固件/原始二进制分析
    在反汇编原始二进制文件时,IDA 并不总能检测到代码片段,您可能需要通过反复试验才能在整个加载范围内找到代码,这可能是一个耗时的过程。在这种情况下,以下简单方法可用于初步侦查:
    • 转到数据库的起始位置 (Ctrl + PgUp);
    • 开始选择 (Alt +L);
    • 转到结尾 (Ctrl + PgDn)。您还可以转到您认为可能是代码区域结束的特定点(例如,在一大段零或 FF 字节之前);
    • 选择 "Edit[编辑]">"Code[代码 ]"或按 C 键。您将看到一个对话框,询问要执行的具体操作:
    • 如果确定所选范围内大部分是指令,请单击 "Force[强制]";如果指令之间可能存在数据,请单击 "Analyze[分析]"。
    • 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(结构偏移)键,就会弹出一个新的对话框:
    你可以选择哪个寄存器作为基础,应用哪种结构,甚至选择要转换的具体指令。
    选择 rax和 EFI_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 没有在 1BC8 处自动创建字符串,因为它以一个非 ASCII 字符开头。但是,如果我们选择字符串的字节并按 A(转换为字符串),字符串还是会创建:

    Creating structures from data根据数据创建结构
    当处理二进制文件中的结构化数据时,此操作很有用。让我们考虑一个具有大约以下条目布局的表:

    struct copyentry { void *source; void *dest; int size; void* copyfunc;};
    虽然可以在 "结构 "窗口中手动创建这样的结构,但通常先格式化数据,然后再创建 描述数据的结构会更方便。创建完四个数据项后,选中它们并从右键菜单中选择 "Create struct from selection[从选中项创建结构]":
    IDA 将创建一个代表所选数据项的结构,然后可用于格式化程序中或反汇编中的其他项,以便更好地理解使用这些数据的代码。
    扩展:“entries[项]”可能是指程序或反汇编中需要分析或理解的各个数据点或记录。这些“entries[项]”可以是程序的不同部分、内存地址、指令或其他相关信息,这些信息对于理解代码如何与特定数据交互非常重要。

    PYG19周年生日快乐!
  • TA的每日心情
    擦汗
    2024-10-20 00:03
  • 签到天数: 217 天

    [LV.7]常住居民III

    发表于 2024-2-28 17:57:06 | 显示全部楼层
    表哥,图片挂了
    PYG19周年生日快乐!
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    6 小时前
  • 签到天数: 1781 天

    [LV.Master]伴坛终老

    发表于 2024-2-29 00:31:33 | 显示全部楼层
    感谢分享,学习了!
    PYG19周年生日快乐!
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 登录 | 加入我们

    本版积分规则

    快速回复 返回顶部 返回列表