1.重新设置函数类型

写一个简单的代码做测试:

[cpp] view plaincopy
  1. int fun(int a, double b)
  2. {
  3. return 0;
  4. }
  5. int _tmain(int argc, _TCHAR* argv[])
  6. {
  7. int c = fun(1, 2);
  8. return 0;
  9. }

release生成,去掉pdb,由于fun内部没有任何操作,所以IDA是无法通过类型传播来得到正确的函数参数和数据类型的,默认,IDA会生成如下函数:

为此我们来修正下它,参看下调用处的汇编

[cpp] view plaincopy
  1. 008 sub     esp, 8          ; 参看标识1可知此处开始压参,此处压了8,结合下面,为double
  2. 010 fld     ds:dbl_4020E8
  3. 010 fstp    [esp+0Ch+var_C]
  4. 010 push    1               ; 此处压最左参数int
  5. 014 call    sub_401000      ; 此处堆栈是偏移0x14,0x14-0xc = 0x8处,标识1
  6. 014 add     esp, 0Ch        ; 加0xc!说明是c调用,调用者平衡

从而,使用Edit▶Functions▶Set Function Type命令,或者在函数名称上右击鼠标并在上下文菜单中选择SetFunction Type(或使用热键Y)来设置函数的类型

F5反汇编一下:

最后,IDA会向新修改的函数的所有调用方传播这些信息,从而改进对此处显示的所有相关函数调用的附加说明

2.创建数组结构

示例1.局部数组

先逐步分析:

修正函数

对应逆向代码如下

[cpp] view plaincopy
  1. void *sub_401000()
  2. {
  3. void *result; // eax@1
  4. int i; // [sp+0h] [bp-194h]@1
  5. int array_int[100]; // [sp+4h] [bp-190h]@1
  6. array_int[0] = 0;
  7. result = memset(&array_int[1], 0, 0x18Cu);
  8. array_int[20] = 15;
  9. for ( i = 0; i < 100; ++i )
  10. {
  11. result = (void *)i;
  12. array_int[i] = i;
  13. }
  14. return result;
  15. }

示例2.全局数组

[cpp] view plaincopy
  1. .text:00401000 sub_401000      proc near               ; CODE XREF: _main+3p
  2. .text:00401000
  3. .text:00401000 var_4           = dword ptr -4
  4. .text:00401000
  5. .text:00401000                 push    ebp
  6. .text:00401001                 mov     ebp, esp
  7. .text:00401003                 push    ecx
  8. .text:00401004                 mov     [ebp+var_4], 2
  9. .text:0040100B                 mov     dword_403018, 0Ah
  10. .text:00401015                 mov     dword_40301C, 14h
  11. .text:0040101F                 mov     dword_403020, 1Eh
  12. .text:00401029                 mov     eax, [ebp+var_4]
  13. .text:0040102C                 mov     dword_403018[eax*4], 28h
  14. .text:00401037                 mov     esp, ebp
  15. .text:00401039                 pop     ebp
  16. .text:0040103A                 retn

先逐步分析:

[cpp] view plaincopy
  1. .text:0040102C                 mov     dword_403018[eax*4], 28h ; 暗示dword_406018为dword数组

基于IDA分配的哑名,我们知道,全局数组由从地址00403018开始的12个字节组成。在编译过程中,编译器使用了固定索引(0、1、2)来计算数组中对应元素的具体地址(00403018、0040301c和00403020),所以跳转到地址00403018

创建数组结构

要创建数组,首先选择数组中的第一个元素(这里我们选择的是dword_403018)

1.在创建数组之前,首先要保证第一个元素的大小更改为适当的值(使用D键切换,由Option—>Setup Data Types选中项来决定轮换),即确认数组中元素的大小

2.然后通过Edit▶Array命令打开如图所示的“创建数组”对话框

•Array element Width(数组元素宽度)。这个值表示各数组元素的大小(这里为1字节),它由你在打开对话框时选择的数据值的大小决定。

•Maximum possible size(最大可能大小)。这个值由自动计算得出,它决定在遇到另一个已定义的数据项之前,可包含在数组中的元素(不是字节)的最大数目。你可以指定一个更大的值,但这需要随后的数据项为未定义数据项,以将它们吸收到数组中。

•Number of elements(元素数量)。你可以在这里指定数组的具体大小。数组占用的总字节数可通过“元素数量×数组元素宽度”计算得出。

•Items on a line(行中的项目)。指定在每个反汇编行显示的元素的数量。通过它可以减少显示数组所需的空间。

•Element width(元素宽度)。这个值仅用于格式化。当一行显示多个项目时,它控制列宽。

•Use“dup”construct(使用重复结构)。这个选项可将相同的数据值合并起来,用一个重复说明符组合成一项。

•Signed elements(有符号元素)。表示将数据显示为有符号还是无符号的值。

•Display indexes(显示索引)。使数组索引以常规注释的形式显示。如果你需要定位大型数组中的特定数据,可以使用这个选项。选择该选项还将启用Indexes单选按钮,这样就可以选择每个索引值的显示格式。

•Create as array(创建为数组)。不选择这个选项似乎有悖于本对话框的目的,该选项默认处于选中状态。如果你只希望指定一定数量的连续项目,而不是将它们组合成一个数组,即可取消该选项。


•Items on a line(行中的项目)。指定在每个反汇编行显示的元素的数量。通过它可以减少显示数组所需的空间。•Array element Width(数组元素宽度)。这个值表示各数组元素的大小(这里为1字节),它由你在打开对话框时选择的数据值的大小决定。   •Maximum possible size(最大可能大小)。这个值由自动计算得出,它决定在遇到另一个已定义的数据项之前,可包含在数组中的元素(不是字节)的最大数目。你可以指定一个更大的值,但这需要随后的数据项为未定义数据项,以将它们吸收到数组中。   •Number of elements(元素数量)。你可以在这里指定数组的具体大小。数组占用的总字节数可通过“元素数量×数组元素宽度”计算得出。基于IDA分配的哑名,我们知道,全局数组由从地址0040B720开始的12个字节组成。在编译过程中,编译器使用了固定索引(0、1、2)来计算数组中对应元素的具体地址(0040B720、0040B724和0040B728)

示例3.栈分配的数组

编译器几乎以完全相同的方式处理栈分配的数组和全局分配的数组。

[cpp] view plaincopy
  1. sub_401000 proc near
  2. var_10= dword ptr -10h
  3. var_C= dword ptr -0Ch
  4. var_8= dword ptr -8
  5. var_4= dword ptr -4
  6. push    ebp
  7. mov     ebp, esp
  8. sub     esp, 10h
  9. mov     [ebp+var_10], 2
  10. mov     [ebp+var_C], 10
  11. mov     [ebp+var_8], 20
  12. mov     [ebp+var_4], 30
  13. mov     eax, [ebp+var_10]
  14. mov     [ebp+eax*4+var_C], 40
  15. mov     esp, ebp
  16. pop     ebp
  17. retn

先逐步分析:

[cpp] view plaincopy
  1. mov     [ebp+eax*4+var_C], 40 ; 暗示var_C为int数组

双击var_C,使用array分配:

[cpp] view plaincopy
  1. push    ebp
  2. mov     ebp, esp
  3. sub     esp, 10h
  4. mov     [ebp+var_10], 2
  5. mov     [ebp+var_C], 10
  6. mov     [ebp+var_C+4], 20
  7. mov     [ebp+var_C+8], 30
  8. mov     eax, [ebp+var_10]
  9. mov     [ebp+eax*4+var_C], 40 ; 暗示var_C为int数组

其代码如下:

[cpp] view plaincopy
  1. int L_array[3];
  2. int idx = 2;
  3. L_array[0] = 10;
  4. L_array[1] = 20;
  5. L_array[2] = 30;
  6. L_array[idx] = 40;

示例4.堆分配的数组

处理堆分配的数组的主要区别在于,它必须根据内存分配函数返回的地址值,生成对数组的所有引用

[cpp] view plaincopy
  1. push    ebp
  2. mov     ebp, esp
  3. sub     esp, 0Ch
  4. push    0Ch             ; unsigned int
  5. call    ??2@YAPAXI@Z    ; operator new(uint)
  6. add     esp, 4
  7. mov     [ebp+var_C], eax
  8. mov     eax, [ebp+var_C]
  9. mov     [ebp+var_8], eax
  10. mov     [ebp+var_4], 2
  11. mov     ecx, [ebp+var_8]
  12. mov     dword ptr [ecx], 0Ah
  13. mov     edx, [ebp+var_8]
  14. mov     dword ptr [edx+4], 14h
  15. mov     eax, [ebp+var_8]
  16. mov     dword ptr [eax+8], 1Eh
  17. mov     ecx, [ebp+var_4]
  18. mov     edx, [ebp+var_8]
  19. mov     dword ptr [edx+ecx*4], 28h
  20. mov     esp, ebp
  21. pop     ebp
  22. retn

先逐步分析:

[cpp] view plaincopy
  1. call    ??2@YAPAXI@Z    ; operator new(uint)
  2. add     esp, 4
  3. mov     [ebp+var_C], eax ; eax保存了new的堆指针
  4. mov     eax, [ebp+var_C]
  5. mov     [ebp+var_8], eax ; var_8保存了new的堆指针
  6. mov     [ebp+var_4], 2  ; var_4 = 2
  7. mov     ecx, [ebp+var_8] ; ecx保存了new的堆指针
  8. mov     dword ptr [ecx], 0Ah ; new的堆指针(int[0]=0a)
  9. mov     edx, [ebp+var_8] ; edx保存了new的堆指针
  10. mov     dword ptr [edx+4], 14h ; int[1]=0x14
  11. mov     eax, [ebp+var_8] ; eax保存了new的堆指针
  12. mov     dword ptr [eax+8], 1Eh ; int[2]=0x1e
  13. mov     ecx, [ebp+var_4] ; ecx=2
  14. mov     edx, [ebp+var_8] ; edx保存了new的堆指针
  15. mov     dword ptr [edx+ecx*4], 28h ; int[2]=0x28

其代码如下:

[cpp] view plaincopy
  1. int *heap_array = new int[3];
  2. int idx = 2;
  3. heap_array[0] = 10;
  4. heap_array[1] = 20;
  5. heap_array[2] = 30;
  6. heap_array[idx] = 40;

9.IDA-重新设置函数类型、创建数组结构相关推荐

  1. numpy的基本使用 附python代码详细讲解(numpy函数,创建数组,常用属性,索引切片,数组的复制,修改维度,数组的分割、拼接、转置)

    目录 使用array创建数组 使用arange创建数组 Numpy中的随机数创建 ndarray对象的常用属性 其他方式创建数组 索引和切片(一位数组.二维数组) 数组的复制 修改数组的维度 数组的拼 ...

  2. 函数类型和函数指针类型

    在C语言中,函数也是一种类型,可以定义指向函数的指针.我们知道,指针变量的内存单元存放一个地址值,而函数指针存放的就是函数的入口地址(位于.text段).下面看一个简单的例子: #include &l ...

  3. c语言函数返回值类型必须,C++中函数类型与定义的函数返回值类型必须相同么?...

    C++中函数类型与定义的函数返回值类型必须相同么?以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! C++中函数类型与定义 ...

  4. 【Android FFMPEG 开发】OpenSLES 播放音频 ( 创建引擎 | 输出混音设置 | 配置输入输出 | 创建播放器 | 获取播放/队列接口 | 回调函数 | 开始播放 | 激活回调 )

    文章目录 I . FFMPEG 播放视频流程 II . OpenSLES 播放音频流程 III . OpenSLES 播放参考 Google 官方示例 IV . OpenSL ES 播放代码 ( 详细 ...

  5. 变量是否在数组内c语言,函数内创建的数组在调用后,是否就不存在

    函数内创建的数组在调用后,是不是就不存在 本帖最后由 test_lockxxx 于 2014-04-23 09:31:06 编辑 第1种写法: char *getABC() { char str[10 ...

  6. ts定义数组类型_TS的对象类型、数组类型、函数类型

    对象类型 基础使用 在 TypeScript 中,我们使用接口(Interfaces)来定义对象的类型. 简单例子: interface Person { name: string; age: num ...

  7. php创建数组教程,PHP中使用array函数新建一个数组

    PHP 中的数组实际上是一个有序映射.映射是一种把 values 关联到 keys 的类型.此类型在很多方面做了优化,因此可以把它当成真正的数组,或列表(向量),散列表(是映射的一种实现),字典,集合 ...

  8. R语言使用dplyr聚合统计分组数据、ggplot2可视化分组线图、使用geom_line函数自定义设置线条类型、粗细、颜色(Change line types + colors by groups)

    R语言ggplot2可视化分组线图.使用geom_line函数自定义设置线条类型.宽度(粗细.).颜色(Change line types by groups.Change line types + ...

  9. python 创建空的numpy数组_数据分析-NumPy内置函数创建数组

    微信公众号:yale记 关注可了解更多的教程问题或建议,请公众号留言. 背景介绍 今天学习使用numpy的内置函数arange().ones().zeros().linspace() 等内置函数创建数 ...

最新文章

  1. vue开发页面自适应_vue-cli 【flexible】屏幕字体自适应布局及配置
  2. 第21章:MongoDB-聚合操作--聚合管道--$geoNear
  3. [JSOI2008 Prefix火星人]
  4. 斜堆学习笔记+复杂度证明
  5. WebSocket小叙
  6. Log4j未平,Logback 又起,再爆漏洞。
  7. MySQL 的主从原理和复制过程简述
  8. Bailian4069 买手机【序列处理+排序】
  9. 安装IBM Data Studio Client
  10. 苏教版六年级上册计算机教案,苏教版六年级数学上册最新全册教案
  11. 【Linux】快速入门法宝~你值得拥有
  12. 各位大神,有没有类似于百度云软件开始时的设置向导的例子呀
  13. UnityHub 无需登录 傻瓜教程 一键搞定
  14. Rockchip基于RK3566/RK3568 WiFi AP6256调试笔记
  15. (最全干货分享)渗透测试全流程归纳总结之二
  16. 壁纸 | iOS 14 内置这几张壁纸,你喜欢吗?
  17. nacosk8s部署_k8s部署nacos - osc_vh89klm7的个人空间 - OSCHINA - 中文开源技术交流社区...
  18. matlab计算PN序列的本原多项式
  19. java中正则表达式隐藏中文汉字
  20. 怎样将swf格式的视频转换成mp4格式呢

热门文章

  1. 函数的参数-在函数内部使用方法修改可变参数会影响外部实参
  2. 字符串-拆分和拼接字符串
  3. Direct交换器-编写生产者
  4. Spring Schedule定时关单快速入门
  5. 特定SQL的查询优化
  6. 类型上限_类型或可成为影视市场下一红利点__枫筹网
  7. 1984年王安微型计算机,王安简:今年中科大少年班最小的学生
  8. Python文本处理几种方法
  9. python 导入numpy 导致多进程绑定同一个CPU问题解决方法
  10. 使用TortoiseGit操作分支的创建与合并