首页
社区
课程
招聘
[原创]新版IDA SDK的变化
发表于: 2022-4-16 00:35 16224

[原创]新版IDA SDK的变化

2022-4-16 00:35
16224

相信大多数人都阅读过神书《IDA Pro权威指南》,但是这本书是基于比较老版的IDA,里面讲的许多概念和代码都无法在最新的IDA上使用。本文打算以IDA7.5为基础讲讲其中编写IDA处理器模块的变化,如果你打算编写IDA模块,这篇文章希望对你有所帮助。如有错误,欢迎指正。

IDA7.6、IDA SDK7.6、Visual studio

模块:IDA二次开发的功能之一,分为加载器、处理器和插件。
加载器:用于分析文件结构,处理文件数据,为后面处理器作准备。常见的有PE文件加载器和ELF文件加载器。
处理器:提供二进制文件的反汇编功能,包含函数识别、分支处理、代码着色等任何跟处理器相关的功能
插件:开发者可以使用插件定制任何功能,著名的有hex-rays开发的F5插件。
脚本:IDA二次开发的功能之一,作为插件的补充,可以使用IDC或python开发。插件能够调用大部分的SDK API并且拥有大量的封装函数,使其非常容易开发。

IDA从7.5开始支持多idb加载和处理,如果你需要使用IDA的idb功能,你可能需要使用set_module_data、clr_module_data、get_module_data这三个函数与你的模块进行绑定。

IDA模块支持事件处理机制,处理器模块导出的LPH中的u_ana、u_emu等回调函数在新版IDA SDK中已被删除,取而代之的是一个notify的回调函数,在该函数中可以处理IDA消息(例如ev_ana_insn和ev_emu_insn)。

IDA从7.4开始把所有的脚本函数统一规范化了,如果你使用python进行IDA脚本开发,需要注意这点,否则你可能发现你的脚本在7.3上能运行而在7.4上无法运行。IDA官网提供了函数的映射关系Porting from IDAPython 6.x-7.3, to 7.4

处理器模块导出LPH相比旧版sdk已经少了很多字段,但该结构体仍然有26个字段需要初始化,这是一个非常繁琐的工作。幸运的是,大多数时候,某些字段不会用到,我们只需要初始化其中几个关键的字段即可。

新版的sdk推荐以下形式创建一个处理器模块,注意SET_MODULE_DATA需要使用一个名称为data_id作为全局变量并且该名称不能改变。

新版sdk的plugin_t为了兼容旧版插件无太大变化,但其中一些成员变量已经不再使用。

新版sdk中plugin_t的init函数一般来说很简单,只需要返回一个plugmod_t类的实例指针即可。以下是一个init函数的参考。

旧版sdk中plugin_t的init、term和run函数分别对应plugmod_t类的构造函数、析构函数和纯虚函数run。
在编写插件时,需要编写一个类继承plugmod_t类并实现run函数,然后将该类的实例指针在init中返回。以下为继承类的参考。

//[*]表示必须设置的字段
struct processor_t
{
    int32  version;    //[*]必须为IDP_INTERFACE_VERSION
    int32  id;    //[*]自定义的处理器模块必要大于0x8000
    uint32  flag;    //以PR_开头的flag组合,根据需要添加,可以设置为0
    uint32  flag2;    //以PR2_开头的flag组合,根据需要添加,可以设置为0
    int32  cnbits;    //[*]代码段中1个字节有多少个bit可用,设置为8即可
    int32  dnbits;    //[*]非代码段中1个字节有多少个bit可用,设置为8即可
    const char *const *  psnames;    //[*]处理器模块的短名称,最多9个字符,数组以NULL指针结尾
    const char *const *  plnames;    //[*]处理器模块的长名称,长度不限,数组以NULL指针结尾
    const asm_t *const *  assemblers ;    //汇编清单,可以设置为{ NULL },数组以NULL指针结尾
    hook_cb_t *  _notify;    //[*]事件通知的回调函数,在该函数中处理IDA发出的各种事件,包括ev_ana_insn、ev_emu_insn、ev_out_insn、ev_out_operand,上述四个事件分别对应旧版SDK的4个回调函数
    const char *const *  reg_names;    //[*]寄存器名称数组
    int32 regs_num;    //[*]寄存器名称数组的元素个数
    int32 reg_first_sreg;    //第一个段寄存器的序号,可以设置为rVcs
    int32 reg_last_sreg;    //最后一个段寄存器的序号,可以设置为rVds
    int32 segreg_size;    //段寄存器大小,单位为字节,可以设置为0
    int32 reg_code_sreg;    //代码段寄存器,可以设置为rVcs
    int32 reg_data_sreg;    //数据段寄存器,可以设置为rVds
    const bytes_t *codestart;  //代码/函数开始的特征码,可以设置为NULL
    const bytes_t *retcodes;    //代码/函数结束的特征码,可以设置为NULL
    int32   instruc_start;    //[*]指令枚举的第一个数
    int32   instruc_end;    //[*]指令枚举的最后一个数,枚举最后一个数设置为XXX_LAST,
    const instruc_t *instruc;     //[*]定义指令的汇编输出和操作数属性,要与指令枚举一一对应
    size_t tbyte_size;    //长浮点(long double)类型的大小,单位为字节,可以设置为0
    char real_width[4];    //浮点数中小数点后位数,用于浮点数显示时保留多少位,可以设置为{0}
    int32 icode_return;    //返回指令的指令码(指令枚举),可以设置为非指令枚举中的元素,一般设置为XXX_NULL(指令枚举的第一个元素)
    void *unused_slot;    //预留,设置为NULL
};
//[*]表示必须设置的字段
struct processor_t
{
    int32  version;    //[*]必须为IDP_INTERFACE_VERSION
    int32  id;    //[*]自定义的处理器模块必要大于0x8000
    uint32  flag;    //以PR_开头的flag组合,根据需要添加,可以设置为0
    uint32  flag2;    //以PR2_开头的flag组合,根据需要添加,可以设置为0
    int32  cnbits;    //[*]代码段中1个字节有多少个bit可用,设置为8即可
    int32  dnbits;    //[*]非代码段中1个字节有多少个bit可用,设置为8即可
    const char *const *  psnames;    //[*]处理器模块的短名称,最多9个字符,数组以NULL指针结尾
    const char *const *  plnames;    //[*]处理器模块的长名称,长度不限,数组以NULL指针结尾
    const asm_t *const *  assemblers ;    //汇编清单,可以设置为{ NULL },数组以NULL指针结尾
    hook_cb_t *  _notify;    //[*]事件通知的回调函数,在该函数中处理IDA发出的各种事件,包括ev_ana_insn、ev_emu_insn、ev_out_insn、ev_out_operand,上述四个事件分别对应旧版SDK的4个回调函数
    const char *const *  reg_names;    //[*]寄存器名称数组
    int32 regs_num;    //[*]寄存器名称数组的元素个数
    int32 reg_first_sreg;    //第一个段寄存器的序号,可以设置为rVcs
    int32 reg_last_sreg;    //最后一个段寄存器的序号,可以设置为rVds
    int32 segreg_size;    //段寄存器大小,单位为字节,可以设置为0
    int32 reg_code_sreg;    //代码段寄存器,可以设置为rVcs
    int32 reg_data_sreg;    //数据段寄存器,可以设置为rVds
    const bytes_t *codestart;  //代码/函数开始的特征码,可以设置为NULL
    const bytes_t *retcodes;    //代码/函数结束的特征码,可以设置为NULL
    int32   instruc_start;    //[*]指令枚举的第一个数
    int32   instruc_end;    //[*]指令枚举的最后一个数,枚举最后一个数设置为XXX_LAST,
    const instruc_t *instruc;     //[*]定义指令的汇编输出和操作数属性,要与指令枚举一一对应
    size_t tbyte_size;    //长浮点(long double)类型的大小,单位为字节,可以设置为0
    char real_width[4];    //浮点数中小数点后位数,用于浮点数显示时保留多少位,可以设置为{0}
    int32 icode_return;    //返回指令的指令码(指令枚举),可以设置为非指令枚举中的元素,一般设置为XXX_NULL(指令枚举的第一个元素)
    void *unused_slot;    //预留,设置为NULL
};
int data_id; //for SET_MODULE_DATA
static ssize_t idaapi notify(void *, int msgid, va_list)
{
  if ( msgid == processor_t::ev_get_procmod )
    return size_t(SET_MODULE_DATA(tms6_t));
  return 0;
}
int data_id; //for SET_MODULE_DATA
static ssize_t idaapi notify(void *, int msgid, va_list)
{
  if ( msgid == processor_t::ev_get_procmod )
    return size_t(SET_MODULE_DATA(tms6_t));
  return 0;
}

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

收藏
免费 3
支持
分享
最新回复 (3)
雪    币: 3785
活跃值: (3947)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
2
感谢分享!
2022-4-16 14:59
0
雪    币: 29
活跃值: (1719)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
跟老版本相比,没有什么太大的变化,无非就是舍弃了一些多余的设计和api,扩展的一些更细节的东西,其实我觉得最主要的变化就是现在支持用python3写插件了,这个是最爽的。
2022-4-16 19:50
0
雪    币: 10868
活跃值: (7767)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
4
xiaomajia 跟老版本相比,没有什么太大的变化,无非就是舍弃了一些多余的设计和api,扩展的一些更细节的东西,其实我觉得最主要的变化就是现在支持用python3写插件了,这个是最爽的。
以前的IDA也能用python2写脚本呀,最主要脚本函数大改了,以前我的7.0脚本都要在7.6上重写
2022-4-17 23:19
0
游客
登录 | 注册 方可回帖
返回
//