返回介绍

17.5 扩展 IDC

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

到现在为止,我们已经介绍了主要用于操纵数据库或从数据库中提取信息的插件。本节将提供一个扩展 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 技术交流群。

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

发布评论

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