- 献词
- 致谢
- 前言
- 第一部分 IDA 简介
- 第 1 章 反汇编简介
- 第 2 章 逆向与反汇编工具
- 第 3 章 IDA Pro 背景知识
- 第二部分 IDA 基本用法
- 第 4 章 IDA 入门
- 第 5 章 IDA 数据显示窗口
- 第 6 章 反汇编导航
- 第 7 章 反汇编操作
- 第 8 章 数据类型与数据结构
- 第 9 章 交叉引用与绘图功能
- 第 10 章 IDA 的多种面孔
- 第三部分 IDA 高级应用
- 第 11 章 定制 IDA
- 第 12 章 使用 FLIRT 签名来识别库
- 第 13 章 扩展 IDA 的知识
- 第 14 章 修补二进制文件及其他 IDA 限制
- 第四部分 扩展 IDA 的功能
- 第 15 章 编写 IDA 脚本
- 第 16 章 IDA 软件开发工具包
- 第 17 章 IDA 插件体系结构
- 第 18 章 二进制文件与 IDA 加载器模块
- 第 19 章 IDA 处理器模块
- 第五部分 实际应用
- 第 20 章 编译器变体
- 第 21 章 模糊代码分析
- 第 22 章 漏洞分析
- 第 23 章 实用 IDA 插件
- 第六部分 IDA 调试器
- 第 24 章 IDA 调试器
- 第 25 章 反汇编器/ 调试器集成
- 第 26 章 其他调试功能
- 附录 A 使用 IDA 免费版本 5.0
- 附录 B IDC/SDK 交叉引用
26.3 Appcall
调试器的 Appcall 特性有效地扩展了 IDC 或 IDAPython 通过脚本调用活动进程中的任何函数的功能。上述功能的用途非常广泛,包括将额外的内存映射到进程地址空间中(通过调用 VirtualAlloc
或类似函数),以及将新库注入到所调试的进程中(通过调用 LoadLibrary
,或通过调用进程中的函数来执行你宁愿手动执行的任务,如解码数据块或计算散列值)。
要使用 Appcall,必须将你要调用的函数加载到所调试进程的地址空间中,并且 IDA 必须了解或获知该函数的原型,以便正确编列或解列参数。保存当前调试器线程的状态(与该线程有关的所有注册)后,你所作的任何 Appcall 调用将置于该线程中。Appcall 完成后,IDA 将恢复线程状态,调试器也将恢复执行,好像 Appcall 从未发生一样。
下面我们来看一个示例,该示例使用 Appcall 将一个 4096 字节的内存块分配到当前(Windows)进程地址空间中。在本例中,我们希望调用的 Windows API 函数名为 VirtualAlloc
,其原型如下所示:
LPVOID WINAPI VirtualAlloc(LPVOID lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect);
如果以 C 语言编写代码,使用 Appcall 调用 VirtualAlloc
函数的代码如下所示:
VirtualAlloc(NULL, 4096, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
解析所有常量后,此函数调用最终变为:
VirtualAlloc(0, 4096, 0x3000, 4);
如前所述,在调试 Windows 进程时,IDA 会将函数所属的库的名称作为每个库函数的名称的前缀。因此,激活调试器后, VirtualAlloc
将被命名为 kernel32_VirtualAlloc
,如下面的代码所示:
kernel32.dll:766B2FB6 ; ====== S U B R O U T I N E ======== kernel32.dll:766B2FB6 kernel32.dll:766B2FB6 ; Attributes: bp-based frame kernel32.dll:766B2FB6 kernel32.dll:766B2FB6 kernel32_VirtualAlloc proc near
由于 IDA 的类型库对名为 kernel32_VirtualAlloc
的函数一无所知,所以不会显示任何类型信息。由于 Appcall 需要了解函数的类型签名,因此我们需要使用 Set Function Type
命令将相关信息添加到数据库中。只要我们指定的签名允许 IDA 将参数正确传送给所调用的函数,就不需要具体的类型签名了。在本例中,我们提供了以下签名:
kernel32.dll:766B2FB6 ; Attributes: bp-based frame kernel32.dll:766B2FB6 kernel32.dll:766B2FB6 ; int __stdcall kernel32_VirtualAlloc(int, int, int, int) kernel32.dll:766B2FB6 kernel32_VirtualAlloc proc near
现在,我们已经作好准备,可以使用 Appcall 为我们的进程分配更多内存。使用 IDC 可以轻松完成这个任务,因为我们只需要调用 VirtualAlloc
,就像调用 IDC 函数一样。在 IDA 命令行中输入函数调用,并使用 Message
函数显示结果,将生成以下输出:
IDC>Message("%x\n", kernel32_VirtualAlloc(0, 4096, 0x3000, 4)); 3c0000
结果,一个 4096 字节的新内存块分配给了地址 0x3c0000
处的进程。要在 IDA 中显示这个新内存块,我们必须使用 Debugger ▶Refresh 内存命令,或等候 IDA 执行刷新及其他调试器操作。
在 Python 中执行 Appcall 的语法会略有不同,需要用到在 idaapi
模块中定义的 Appcall 变量。但是,你仍然需要提供命名函数与类型签名。以 Python 编写的、使用 Appcall 调用 VirtualAlloc
函数的代码如下所示:
Python>Message("%x\n" % Appcall.kernel32_VirtualAlloc(0, 4096, 0x3000, 4)) 3d0000
有关 Appcall 及其用法的其他信息与示例,请参阅 Hex-Rays 博客1 。
1. 参见 http://www.hexblog.com/?p=113 。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论