返回介绍

8.5 使用标准结构体

发布于 2024-10-11 21:05:43 字数 5949 浏览 0 评论 0 收藏 0

如前所述,IDA 能够识别大量与各种库和 API 函数有关的数据结构。最初创建一个数据库时,IDA 会尝试确定与二进制文件有关的编译器和平台,并加载适当的结构体模板。当 IDA 在反汇编代码清单中操纵结构体时,它会在 Structures 窗口中添加相应的结构体定义。因此,Structures 窗口中显示的是应用于当前二进制文件的已知结构体的子集。除了创建自定义结构体外,你还可以从 IDA 的已知结构体列表中提取出其他标准结构体,并将其添加到 Structures 窗口中。

要添加一个新结构体,首先,在 Structures 窗口中按下 INSERT 键。在图 8-3 的 Create structure/ union 对话框中,包含一个 Add standard structure(添加标准结构体)按钮。单击这个按钮,IDA 将显示与当前编译器(在分析阶段检测出来)和文件格式有关的结构体主列表。这个结构体主列表中还包含通过解析 C 头文件添加到数据库中的结构体。选择结构体对话框如图 8-13 所示,该对话框用于选择添加到 Structures 窗口中的结构体。

图 8-13 选择标准结构体

你可以利用搜索功能,根据部分文本匹配来定位结构体。该对话框还允许你进行前缀匹配。如果你知道某个结构体名称的前几个字符,只需输入这几个字符(它们将出现在对话框底部的状态栏上),列表窗口将跳转到第一个与这个前缀匹配的结构体。选择一个结构体,该结构体及任何嵌套结构体都将添加到 Structures 窗口中。

下面举例说明如何使用标准结构体。假如你想要分析一个 Windows PE 二进制文件的文件头。默认情况下,在创建后,文件头不会立即加载到数据库中。但是,如果你在最初创建数据库时选择 Manual load(手动加载)选项,就可以将文件头加载到数据库中。加载文件头可确保只有与这些头部有关的数据类型才出现在数据库中。多数情况下,文件头不会以任何形式被格式化,因为通常程序并不会直接引用它们自己的文件头。因此,分析器也没有必要对文件头应用结构体模板。

对一个 PE 二进制文件进行一番研究后,你会发现,PE 文件的开头部分是一个名为 IMAGE_DOS_HEADER 的 MS-DOS 头部结构体。另外, IMAGE_DOS_HEADER 中的数据指向一个 IMAGE_NE_HEADER 结构体的位置。它详细说明了 PE 二进制文件的内存布局。选择加载 PE 头部,你将看到类似于下面的未格式化的反汇编代码清单。了解 PE 文件结构的读者会发现,文件的前两个字节是我们熟悉的 MS-DOS 幻数 MZ

HEADER:00400000 __ImageBase     db  4Dh ; M  
HEADER:00400001                 db  5Ah ; Z  
HEADER:00400002                 db  90h ; É  
HEADER:00400003                 db    0  
HEADER:00400004                 db    3  
HEADER:00400005                 db    0  
HEADER:00400006                 db    0  
HEADER:00400007                 db    0  
HEADER:00400008                 db    4  
HEADER:00400009                 db    0  
HEADER:0040000A                 db    0  
HEADER:0040000B                 db    0  
HEADER:0040000C                 db 0FFh  
HEADER:0040000D                 db 0FFh  
HEADER:0040000E                 db    0  
HEADER:0040000F                 db    0

格式化这个文件时,你需要一些 PE 文件参考文档帮助你了解每一种数据类型。通过使用结构体模板,IDA 可以将这些字节格式化成一个 IMAGE_DOS_HEADER 结构体,使这些数据更加有用。第一步是根据上面的详细说明,添加标准的 IMAGE_DOS_HEADER 结构体(你可以在打开 IMAGE_NT_HEADER 结构体的同时添加该结构体)。第二步是使用 Edit▶ Struct Var (ALT+Q),将从 _ImageBase 开始的字节转换成一个 IMAGE_DOS_HEADER 结构体。这样,即得到下面的格式化代码:

HEADER:00400000 __ImageBase IMAGE_DOS_HEADER  5A4Dh, 90h, 3, 0, 4, 0, 0FFFFh, 0, 0B8h, \
HEADER:00400000                               0, 0, 0, 40h, 0, 0, 0, 0, 0, 80h  
HEADER:00400040 db 0Eh

如你所见,文件的前 64 (0x40 )个字节已被折叠成一个数据结构,其类型也在反汇编代码清单中注明。但是,除非你对这个特殊的结构体非常熟悉,否则,你仍然无法清楚了解其中每个字段的意义。不过,我们可以展开结构体,使操作更进一步。打开一个结构体的数据项时,IDA 会使用结构体定义中对应的字段名称,对每个字段进行注释。使用数字键盘上的加号键可以打开折叠后的结构体。打开后的结构体如下所示:

HEADER:00400000 __ImageBase     dw 5A4Dh                ; e_magic  
HEADER:00400000                 dw 90h                  ; e_cblp  
HEADER:00400000                 dw 3                    ; e_cp  
HEADER:00400000                 dw 0                    ; e_crlc  
HEADER:00400000                 dw 4                    ; e_cparhdr  
HEADER:00400000                 dw 0                    ; e_minalloc  
HEADER:00400000                 dw 0FFFFh               ; e_maxalloc  
HEADER:00400000                 dw 0                    ; e_ss  
HEADER:00400000                 dw 0B8h                 ; e_sp  
HEADER:00400000                 dw 0                    ; e_csum  
HEADER:00400000                 dw 0                    ; e_ip  
HEADER:00400000                 dw 0                    ; e_cs  
HEADER:00400000                 dw 40h                  ; e_lfarlc  
HEADER:00400000                 dw 0                    ; e_ovno  
HEADER:00400000                 dw 4 dup(0)             ; e_res  
HEADER:00400000                 dw 0                    ; e_oemid  
HEADER:00400000                 dw 0                    ; e_oeminfo  
HEADER:00400000                 dw 0Ah dup(0)           ; e_res2  
HEADER:00400000              ➊  dd 80h                  ; e_lfanew  
HEADER:00400040                 db  0Eh

然而, IMAGE_DOS_HEADER 的字段并没有特别有意义的名称,因此,我们在查阅 PE 文件参考文献后才知道:➊处的 e_lfanew 字段表示文件偏移量,在该位置可找到 IMAGE_NT_HEADER 结构体。应用前面讨论的所有步骤,在地址 00400080 (数据库中的第 0x80 字节)处创建一个 IMAGE_NT_ HEADER 结构体,将得到如下所示的格式化后的结构体(仅显示一部分代码):

HEADER:00400080        dd 4550h                ; Signature  
HEADER:00400080        dw 14Ch                 ; FileHeader.Machine  
HEADER:00400080     ➊  dw 5                    ; FileHeader.NumberOfSections  
HEADER:00400080        dd 4789ADF1h            ; FileHeader.TimeDateStamp  
HEADER:00400080        dd 1400h                ; FileHeader.PointerToSymbolTable  
HEADER:00400080        dd 14Eh                 ; FileHeader.NumberOfSymbols  
HEADER:00400080        dw 0E0h                 ; FileHeader.SizeOfOptionalHeader  
HEADER:00400080        dw 307h                 ; FileHeader.Characteristics  
HEADER:00400080        dw 10Bh                 ; OptionalHeader.Magic  
HEADER:00400080        db 2                    ; OptionalHeader.MajorLinkerVersion  
HEADER:00400080        db 38h                  ; OptionalHeader.MinorLinkerVersion  
HEADER:00400080        dd 800h                 ; OptionalHeader.SizeOfCode  
HEADER:00400080        dd 800h                 ; OptionalHeader.SizeOfInitializedData  
HEADER:00400080        dd 200h                 ; OptionalHeader.SizeOfUninitializedData
HEADER:00400080        dd 1000h                ; OptionalHeader.AddressOfEntryPoint  
HEADER:00400080        dd 1000h                ; OptionalHeader.BaseOfCode  
HEADER:00400080        dd 2000h                ; OptionalHeader.BaseOfData  
HEADER:00400080      ➋ dd 400000h              ; OptionalHeader.ImageBase  

可见,这里的字段名称更有意义。我们立即发现,该文件由 5 个部分(➊)构成,应该是在虚拟地址 00400000 (➋)被加载到内存中。使用数字键盘上的减号键,可以将打开状态的结构体恢复到折叠状态。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文