之前提到IDA可以将一长串的数组数据声明变成一行数组声明,简化反汇编代码,对于结构体,IDA也同样支持通过各种设置工具来改善结构体代码的可读性。

这篇文章的目标是将[edx+10h]之类的结构体元素访问 变成 [edx+struct_filed5]之类。

只要发现一个程序正操纵某种数据结构,你就需要确定:你是否希望将结构体的字段名称合并到反汇编代码清单中,或者你是否理解分散在代码清单中的所有数字偏移量。

如果是C标准库或者IDA能够确定的已知结构体,IDA会自动将数字偏移量转换成更加符号化的字段名称,但如果是自定义的结构体,就需要我们手动帮助IDA进行识别。

IDA之所以在分析阶段无法识别结构体,可能源于两个原因。首先,虽然IDA了解某个结构体的布局,但它并没有足够的信息,能够判断程序确实使用了结构体。其次,程序中的结构体可能是一种IDA对其一无所知的非标准结构体。在这两种情况下,问题都可以得到解决,且首先从Structures窗口下手。

创建一个新的结构体(或Union)

在IDA Structures窗口(默认展示,如果没有可以在View -> Open SubViews里打开)中,列举了当前反汇编文件的所有已知结构体,并且在注释中也提示了我们如何在该窗口中添加/删除/编辑一个结构体:

00000000 ; Ins/Del : create/delete structure 或者 Edit -> Add struct type

00000000 ; D/A/* : create structure member (data/ascii/array)

00000000 ; N : rename structure or structure member

00000000 ; U : delete structure member

注意:只有当一个字段是结构体中的最后一个字段时,使用U键才能删除该字段。对于所有其他字段,按下U键将取消该字段的定义,这样做仅仅删除了该字段的名称,并没有删除分配给该字段的字节。

为了创建一个新的结构体,你必须首先在Structure name(结构体名称)字段中指定结构体的名称。前两个复选框用于决定新结构体在Structures窗口中的显示位置,或者是否在窗口中显示新结构体。第三个复选框Creat union(创建联合),指定你定义的是否为C风格联合结构体(Union和结构体的区别在于union中字段相互重叠,因此总大小等于其中最大字段的大小)。

此外还有一个按钮「add standard structure」,用于添加标准结构体。IDA内置了大量的各种库和API函数有关的数据结构,IDA会尝试确定与二进制文件有关的编译器和平台,并加载适当的结构体模板。单击这个按钮,IDA将显示与当前编译器(在分析阶段检测出来)和文件格式有关的结构体主列表。这个结构体主列表中还包含通过解析C头文件添加到数据库中的结构体。

编辑结构体成员

为了给新结构体添加字段,你必须利用字段创建命令D、A和数字键盘上的星号键(*),需要注意的是D快捷键还可用于为当前光标所所在的字段调整数据大小。所以推荐的创建结构体的步骤为:

  1. 在结构体定义的最后一行(包含ends的那一行)按下D键,这时候,IDA会在结构体末尾添加一个新字段,默认的字段名称为filed_N,N为结构体开头到字段开头的数字偏移量。

  2. 如果需要修改字段大小,可以重复按D,循环数据转盘上的数据类型,或者通过Options->Setup Data Types来指定一个在数据转盘上不存在的大小,如果是数组,右键名称然后选择Array。

  3. 如果要更改字段名称,使用N或者右键然后Rename

如果知道结构体的大小,而不了解它的布局,你需要创建两个字段。第一个字段为一个数组,它的大小为结构体的大小减去1个字节(size-1);第二个字段应为1个字节。创建第二个字段后,取消第一个(数组)字段的定义。这样,结构体的大小被保留下来,随后,当你进一步了解该结构体的布局后,你可以回过头来定义它的字段及其大小。

此外,在你定义和编辑结构体时,IDA会有一些提示:

  • 一个字段的字节偏移量以一个8位十六进制值在Structures窗口的左侧显示。

  • 每次你添加或删除一个结构体字段,或更改一个现有字段的大小时,结构体的新大小都会在结构体定义的第一行反映出来。

  • 你必须对一个结构体定义中的所有字段进行适当的对齐。如果你需要填补字节,那么你必须负责添加这些字节。填补字节最好作为适当大小的哑字段添加。

  • 分配到结构体中间的字节只有在取消关联字段的定义后才能删除,使用Edit▶Shrink Struct Type(缩小结构体类型)即可删除被取消定义的字节。

  • 你也可以在结构体的中间添加新的字节:选择新字节后面的一个字段,然后使用Edit▶Expand Struct Type(扩大结构体类型)在选中的字段前插入一定数量的字节。

通过重复应用这些步骤(添加字段,设置字段大小,添加填补字节等),就可以完成IDA结构体定义的创建。接下来就可以利用这些定义好的结构体改善反汇编代码。

使用结构体模版

前面提到这篇文章的目标是将[edx+10h]之类的结构体元素访问 变成 [edx+struct_filed5]之类。

此时有了结构体定义之后,就可以右键10h,选择Structure Offset(结构体偏移量)选项,然后就可以进行格式化了,如果有多个结构体中字段匹配上了偏移量,则会有多个选择。

如果是栈变量或者全局变量,则可以直接将栈和全局变量格式化为整个结构体,首先打开栈帧的详细视图(双击函数栈帧中的变量),然后使用ALT+Q(Edit->Struct Var)命令显示一组已知的结构体并选择对应想要格式化的结构体即可。如果是全局变量,则选择要格式化的全局变量或者表示结构体开头部分的地址,再使用ALT+Q(Edit->Struct Var)即可。

重新格式化之后,IDA认识到,任何对分配给var_18的24个字节块的内存引用,都必须引用该结构体中的一个字段。如果IDA发现这样一个引用,它会尽一切努力,将这个内存引用与结构体变量中的一个已定义的字段关联起来。

导入结构体

IDA能够解析C(而非C++)数据声明,以及整个C头文件,并自动为在这些声明或头文件中定义的结构体创建对应的IDA结构体。如果你碰巧拥有你正进行逆向工程的二进制文件的源代码,或者至少是头文件,那么,你就可以让IDA直接从源代码中提取出相关结构体,从而节省大量时间。

解析C结构体声明

如果我们已经有某个结构体的声明代码,那可以直接在View▶Open Subviews▶Local Types(查看▶打开子窗口▶本地类型)窗口中,输入我们的结构体声明代码,例如:

注意,IDA解析器使用4字节的默认结构体成员对齐方式。如果你的结构体需要其他对齐方式,你可以包括该对齐方式,IDA认可使用pragma pack指令来指定所需的结构体成员对齐方式。

添加到Local Types(本地类型)窗口中的数据类型不会立即在Structures(结构体)窗口中出现。有两种方法可以将本地类型声明添加到Structures窗口中。最简单的方法是在相关本地类型上单击鼠标右键,并选择Synchronize to idb。或者,由于每个新类型均被添加到标准结构体列表中,因而也可将新类型导入到Structures窗口中即add standard structure。

解析C头文件

要解析头文件,可以使用File▶Load File▶Parse C Header File(文件▶加载文件▶解析C头文件)选择你想要解析的头文件。如果一切正常,IDA会通知你Compilation successful(编译完成)。如果解析器遇到任何问题,IDA将会在输出窗口中显示错误消息。

IDA会将所有被成功解析的结构体添加到当前数据库的标准结构体列表末尾,此时同样需要手动从标准结构体列表中添加到Structures窗口中。如果新结构体的名称与现有结构体的名称相同,IDA会用新结构体布局覆盖原有结构体定义。

一般而言,要最大限度地提高成功解析一个头文件的几率,你需要使用标准C数据类型,并尽可能地减少使用include文件,从而最大程度地简化结构体定义。记住,在IDA中创建结构体时,正确布局最为重要。正确的布局更多地取决于每个字段的正确大小和结构体的正确对齐,而不只是对每个字段都使用正确的类型。

IDA TIL文件(Type Library)

IDA中的所有数据类型和函数原型信息都存储在TIL文件中。IDA拥有存储在/til目录中的许多主要编译器和API的类型库信息。Types窗口(View▶Open subview▶Type Libraries)列出了当前加载的.til文件,并可用于加载你想要使用的其他.til文件。IDA将根据在分析阶段发现的二进制文件属性,自动加载类型库。正常情况下,一般不需要直接处理.til文件。

IDA还利用.til文件存储你在Structures窗口中手动创建的或者通过解析C头文件获得的任何自定义结构体定义。这些结构体存储在一个与创建它们的数据库有关的专用.til文件中。该文件的名称与其相关数据库的名称相同,扩展名为.til。

例如,如果数据库名为some_file.idb,则相应的类型库文件则为some_file.til。

.idb文件实际上是一个归档文件(类似于.tar文件),用于保存不使用的数据库组件。打开一个数据库时,其组件文件(.til文件为其中之一)将被提取出来,成为IDA中的运行文件。

在其他数据库中共享til文件

有两种共享方法。第一种方法有些不太正规,即将.til文件由打开的数据库复制到另一个目录中,然后再通过Types窗口,在任何其他数据库中打开这个.til文件。第二种是一种正式的方法,即从一个数据库中提取出自定义类型信息,生成一段IDC脚本,用于在任何其他数据库中重建自定义结构体。使用File▶Produce File▶Dump Type. into to IDC File(文件▶生成文件▶转储类型信息到IDC文件)命令可生成该脚本。但是,与第一种方法不同的是,这种方法只能转储Structures窗口中列出的结构体,但并不转储通过解析C头文件得到的结构体(而复制.til文件却可以转储这类结构体)。

new 一个结构体数组_每天一个IDA小技巧(四):结构体识别相关推荐

  1. NumPy-快速处理数据--ndarray对象--多维数组的存取、结构体数组存取、内存对齐、Numpy内存结构...

    本文摘自<用Python做科学计算>,版权归原作者所有. 上一篇讲到:NumPy-快速处理数据--ndarray对象--数组的创建和存取 接下来接着介绍多维数组的存取.结构体数组存取.内存 ...

  2. 已知一个二维数组A 表示一个矩阵,求AT。 其中,AT 表示矩阵的转置。矩阵转置的含义:表示把一个矩阵行列互换。

    已知一个二维数组A 表示一个矩阵,求AT. 其中,AT 表示矩阵的转置.矩阵转置的含义:表示把一个矩阵行列互换. //传入需要验证的数组,在main里面调用该方法public static void ...

  3. android 打开移动开关,教你一个让安卓手机运行更流畅的小技巧:打开这个开关即可...

    原标题:教你一个让安卓手机运行更流畅的小技巧:打开这个开关即可 安卓用户对于"系统优化"这个词一定不会陌生,因为Android系统越用越卡的毛病难以解决,必须进行优化才能保持流畅. ...

  4. 炒菜机器人煎鸡蛋视频_我的生活小技巧,今天才发现鹅油那么好用,炸鸡蛋炸豆腐都挺好...

    #头条公开课# #微头条日签# 我的生活小技巧,今天才发现鹅油那么好用,炸鸡蛋炸豆腐都挺好 原创/快乐人生 我的生活小技巧(一)红烧鹅"炼鹅油" 昨天买了一个鹅,太肥太肥,厚厚的皮 ...

  5. stm32串口发送数据的配置,以及通过串口发送结构体数组总是多一个00字节的问题

    最近用stm32编写串口发送程序,在硬件方面需要做如下准备: 1.stm32开发板,这里我的是stm32f030f4p4开发板,单片机的串口发送的引脚为PA9-TX,PA10-RX. 2.为了调试串口 ...

  6. java长度为100的数组_产生一个int数组,长度为100,并向其中随机插入1-100,不重复...

    #define RANDOM(X) (rand() % X + 1) int main() { //标志数组 int book[] = {}; int result[] = {}; //默认的随机数种 ...

  7. C++_结构体中const使用场景_结构体_毕业设计案例_使用结构体数组_随机数种子---C++语言工作笔记027

    然后我们再看const符号,在结构体中的应用 首先我们新建一个结构体.student 然后定义一个结构体变量,并初始化 然后我们再写个方法,去打印这个结构体变量 可以看到我们用的是传值

  8. python 结构体数组_关于python:将结构化数组转换为常规NumPy数组

    我认为答案将非常明显,但目前看不到. 如何将记录数组转换回常规ndarray? 假设我有以下简单的结构化数组: x = np.array([(1.0, 4.0,), (2.0, -1.0)], dty ...

  9. python 结构体数组_将结构数组从Python传递给C

    [更新:问题已解决!参见文章底部] 我需要允许Python开发人员将一组打包数据(在这种情况下)通过API插入到API中,这是通过Python C API手动暴露的一系列C++接口.我的初步印象是使用 ...

最新文章

  1. 【iOS数据持久化】偏好设置(UserDefaults)
  2. 编写程序python输入任意大的自然数、输出各位数字之和_兰理工Python第一次上机作业源码...
  3. 深度学习核心技术精讲100篇(六十四)-特征选择原理及应用实战案例
  4. python中的set类型
  5. mysql建立软链接_MySQL(一)安装
  6. Synopsys Mentor Candence
  7. 弹性力学经典解法与有限元法的不同特点
  8. python暴力破解rar压缩文件
  9. 网站备案需要买服务器吗,域名备案需要购买服务器吗
  10. 地震勘探原理(五)之地震勘探的野外工作
  11. 旅游评论情感分析(2)---前期调查总结
  12. 【计算机网络】网络层:路由器的构成
  13. 沈剑架构师训练营,最新金九银十JAVA面试合集
  14. 说明白正反向代理,以及Nginx和Gunicorn
  15. 机器视觉引导定位系统,工业视觉定位检测
  16. SAP FI 系列 (030) - 特别总账标记
  17. CSS | 关于Spirit
  18. Win11搜索栏无法使用怎么办?
  19. java content-length_java向服务器post请求时首部字段content-length的计算方法
  20. 备战一年,终于斩获腾讯T3,我坚信成功是可以复制的

热门文章

  1. ubuntu修改登陆用户名称_修改ubuntu的用户名(注意用户名和主机名的区别)
  2. 新时达二代操作器刷写数据线_布袋除尘器的脉冲振动特点及安装操作
  3. 2020南大计科考研实记(受难三跨)
  4. ajax传递参数给springmvc
  5. Android源码学习(3) Handler之MessageQueue
  6. python 之 字符编码 和 中文显示
  7. CSS基础学习 19.CSS hack
  8. 如何处理HTML5新标签的浏览器兼容问题?
  9. Salesforce 数据备份和恢复小知识
  10. (2.19)备份与还原--备份的原理与总结