- 献词
- 致谢
- 前言
- 第一部分 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 交叉引用
17.5 扩展 IDC
到现在为止,我们已经介绍了主要用于操纵数据库或从数据库中提取信息的插件。本节将提供一个扩展 IDC 脚本语言功能1 的例子。如第 16 章所述,IDC 在 IDA API 的基础上运行,因此毫不奇怪,必要时我们可以使用 API 来增强 IDC 的功能。
1. 注意现在没有办法通过编程在已编译的插件中扩展 IDAPython API 。
在第 15 章和第 16 章中,你了解到,IDC 全局数组实际上是一个功能有限的网络节点。我们提到,在 IDC 中,你可以通过提供一个名称而收到一个数组 ID,从而创建全局数组。在 IDC 内部,你提供的名称获得字符串前缀“ $ idc_array
”,你收到的数组 ID 实际上是一个网络节点索引值。如何扩展 IDC 以访问 IDA 数据库中的网络节点呢?通过将索引作为 IDC 中的数组 ID,我们已经能够访问已知索引的任何网络节点。因此,我们只需要能够访问已知其名称的网络节点就行了。当前,IDA 阻止我们这样做,因为它在我们提供的每一个网络节点名称前加上了“ $ idc_array
”前缀。要解决这个问题,首先进入 SDK 和 set_idc_func_ex
函数。
set_idc_func_ex
函数在 expr.hpp 中定义,可用于创建一个新的 IDC 函数,并将它的行为与 C++ 实现对应起来。 set_idc_func_ex
函数的原型如下所示:
typedef error_t (idaapi *idc_func_t)(idc_value_t *argv, idc_value_t *res); bool set_idc_func_ex(const char *idc_name, idc_func_t idc_impl, const char *args, int extfunc_flags);
注意,为了简化代码,这里引入了 idc_func_t
数据类型。这个数据类型并不在 SDK 中定义。 set_idc_func_ex
的参数指定我们正创建的新 IDC 函数的名称( idc_name
)、一个指向 C++ 函数(实施我们新建的 IDC 函数的行为)的指针( idc_impl
),还有一个以零结束的字符数组,这些字符指定新 IDC 函数的参数类型和列表( args
)。
下面的函数可用作插件的初始化函数。它通过创建我们正在设计的新 IDC 函数来完成扩展过程。
int idaapi init(void) { ➋ static const char idc_str_args[] = { VT_STR2, 0 }; ➊ set_idc_func_ex("CreateNetnode", idc_create_netnode, idc_str_args, 0); return PLUGIN_KEEP; }
这个函数创建新 IDC 函数 CreateNetnode
,并将它与我们的实现函数 idc_create_
netnode
(➊)关联起来。新 IDC 函数的参数是一个字符串类型的参数 VT_STR2
(➋)。
真正实现 CreateNetnode
的行为的函数如下所示:
/* * native implementation of CreateNetnode. Returns the id of the new netnode * this id can be used with all of the existing IDC Array functions. */ static error_t idaapi idc_create_netnode(idc_value_t *argv, idc_value_t *res) { ➊ res->vtype = VT_LONG; //result type is a netnode index ➋ if (argv[0].vtype == VT_STR2) { //verify we have the proper input type ➌ netnode n(argv[0].c_str(), 0, true); //create the netnode ➍ res->num = (nodeidx_t)n; //set the result value } else { ➎ res->num = -1; //If the user supplies a bad argument we fail } return eOk; }
这个函数的两个参数分别表示输入参数数组( argv
),其中包含提交给 CreateNetnode
的所有参数(这里应该只有一个),还有一个输出参数( res
),它用于接收我们正在执行的 IDC 函数的结果。SDK 数据类型 idc_value_t
代表一个 IDC 值。这个数据类型中的字段指明这个值所代表的数据的当前类型以及这个值的当前内容。这个函数首先指定 CreateNetnode
返回一个长( VT_LONG
)值(➊)。由于 IDC 变量没有类型,我们必须指明这个变量在任何给定的时刻所保存的值的类型。接下来,该函数验证 CreateNetnode
的调用方是否提供了一个字符串类型的参数 VT_STR (➋)。如果调用方提供了一个有效的参数,则使用提供的名称创建一个网络节点(➌)。得到的网络节点索引号将以 CreateNetnode
函数结果的形式返回给调用方(➍)。在这个例子中,结果的类型是整数值,因此,这个结果将存储在 res->num
字段中。如果结果类型是一个字符串,那么,需要调用 res->set_string
来设置该结果的字符串值。如果用户没有提供字符串参数,这个函数将无法完成任务,并返回无效的网络节点索引 1(➎)。
使用下面的函数和 PLUGIN 结构体完成插件的创建过程:
void idaapi term(void) {} //nothing to do on termination void idaapi run(int arg) {} //nothing to do and no way to activate plugin_t PLUGIN = { IDP_INTERFACE_VERSION, //this plugin loads at IDA startup, does not get listed on the Edit>Plugins menu //and modifies the database ➊ PLUGIN_FIX | PLUGIN_HIDE | PLUGIN_MOD, // plugin flags init, // initialize term, // terminate. this pointer may be NULL. run, // invoke plugin "", // long comment about the plugin "", // multiline help about the plugin "", // the preferred short name of the plugin "" // the preferred hotkey to run the plugin };
这个插件的特殊之处在于,它在 IDA 启动时加载( PLUGIN_FIX
),并且一直对用户隐藏它的行踪,因为它并没有添加到 Edit ▶Plugins 菜单( PLUGIN_HIDE
,➊)中。该插件一直驻留在内存中,可供所有数据库使用。它的所有初始化任务都在 init
函数中进行,因此,插件的 run
方法基本上无事可做。
安装这个插件后,IDC 程序员就可以使用网络节点名称访问 IDA 数据库中的任何已命名网络节点,如下面的例子所示:
auto n, val; n = CreateNetnode("$ imports"); //no $ idc_array prefix will be added val = GetArrayElement(AR_STR, n, 0); //get element zero
有关使用 SDK 与 IDC 交互的更多信息,请参阅 expr.hpp 头文件。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论