IDA C++ Plug-in 浅尝

admin 2020年12月23日00:10:06评论247 views字数 5974阅读19分54秒阅读模式


IDA C++ Plug-in 浅尝



0x00 相关






ida 的c++插件的实质就是一个动态链接库,即Windows 的DLL文件,Linux 的SO文件和Mac的dylib文件。与普通动态链接库相比,IDA 的C++插件需要导出一个类型为plugin_t导出名称为PLUGIN的结构体变量。


0x01 环境






os : Windows 10 x64

SDK : ida sdk 75

ide : Microsoft Visual Studio 2017


0x02 细节






前面说到,ida 的C++ 插件必须导出plugin_t PLUGIN结构体变量,其详细定义如下:

//头文件 loader.hpp
class plugin_t
{

public:
  int version;                   //接口版本填充 IDP_INTERFACE_VERSION 就好
  int flags;                     //加载条件标志
  plugmod_t *(idaapi *init)(void);  //初始化函数,首次加载插件时调用
  void (idaapi *term)(void);  //销毁函数,卸载插件时调用,可置NULL
  bool (idaapi *run)(size_t arg);  //激活函数,当ida中激活该插件时调用
  const char *comment;    //非本文非关键
  const char *help;     //非本文非关键
  const char *wanted_name;   //插件名称,在Edit->Plugs 中显示的名称
  const char *wanted_hotkey;  //插件激活快捷键
};
  • version:指示接口版本,填充 IDP_INTERFACE_VERSION

  • flags:加载条件标志,可选项有以下几个,该值可以是多个标志的集合,一般来说填0就够了,但该标志可以控制插件加载时机。
#define PLUGIN_MOD  0x0001      //插件会修改数据库,当处理器模式不允许修改时,比应该使用该标志
#define PLUGIN_DRAW 0x0002      //加载插件后。ida重新分析所有内容
#define PLUGIN_SEG  0x0004      //当前地址属于某一个程序段时加载
#define PLUGIN_UNL  0x0008      //该插件运行一次run函数后就被卸载
#define PLUGIN_HIDE 0x0010      //插件不会出现在菜单栏
#define PLUGIN_DBG  0x0020      //调试插件
#define PLUGIN_PROC 0x0040      //当选中一个处理器模式时,加载该插件并且驻留,直到退出处理器模式时卸载该插件
#define PLUGIN_FIX  0x0080      //当ida启动时加载插件,直到ida退出时,卸载插件
#define PLUGIN_MULTI    0x0100  //插件可以使用多个idb文件
#define PLUGIN_SCRIPTED 0x8000  //脚本插件,不使用,由ida 设置

注:当使用PLUGIN_PROC标志时,插件会获得较早的加载时机

  • init:初始化函数,在此可以做一些资源的初始化操作,判断是否加载该插件等,其返回值有三个选择:
#define PLUGIN_SKIP  nullptr          //不加载插件
#define PLUGIN_OK    ((plugmod_t *)1) //用户使用菜单或快捷键时加载插件
#define PLUGIN_KEEP  ((plugmod_t *)2) //加载插件并驻留内存
  • term:销毁函数,卸载插件时调用此函数
  • run:激活函数,当用户使用菜单或快捷键激活插件时调用
  • wanted_name:插件名称,在Edit->Plugs 中显示的名称
  • wanted_hotkey:插件激活快捷键

对于插件的激活,这里分为两种的:一种是主动的菜单或快捷键激活,另一种是被动的事件通知

  1. 第一种是由用户选择调用时机,使用菜单或快捷键激活调用run函数快捷键和在Edit->Plugs中显示的名称在PLUGIN中指定

  2. 第二种是回调函数通知方式,当需要捕捉某个特定时机时,被注册的回调函数被激活使用hook_to_notification_point注册回调,使用unhook_from_notification_point删除回调

//相关事件枚举值
enum hook_type_t
{
  HT_IDP,         ///< Hook to the processor module.
                  ///< The callback will receive all processor_t::event_t events.
  HT_UI,          ///< Hook to the user interface.
                  ///< The callback will receive all ::ui_notification_t events.
  HT_DBG,         ///< Hook to the debugger.
                  ///< The callback will receive all ::dbg_notification_t events.
  HT_IDB,         ///< Hook to the database events.
                  ///< These events are separated from the ::HT_IDP group
                  ///< to speed things up (there are too many plugins and
                  ///< modules hooking to the ::HT_IDP). Some essential events
                  ///< are still generated in th ::HT_IDP group:
                  ///< make_code, make_data
                  ///< This list is not exhaustive.
                  ///< A common trait of all events in this group: the kernel
                  ///< does not expect any reaction to the event and does not
                  ///< check the return code. For event names, see ::idb_event.
  HT_DEV,         ///< Internal debugger events.
                  ///< Not stable and undocumented for the moment
  HT_VIEW,        ///< Custom/IDA views notifications.
                  ///< Refer to ::view_notification_t
                  ///< for notification codes
  HT_OUTPUT,      ///< Output window notifications.
                  ///< Refer to ::msg_notification_t
                  ///< (::view_notification_t)
  HT_GRAPH,       ///< Handling graph operations
                  ///< (::graph_notification_t)
  HT_IDD,         ///< Hook to the debugger plugin.
                  ///< The callback will receive all debugger_t::event_t events.
  HT_LAST
};

//hook_to_notification_point和unhook_from_notification_point定义如下
idaman bool ida_export hook_to_notification_point(
        hook_type_t hook_type,  //事件
        hook_cb_t *cb,    //回调函数
        void *user_data = NULL)
;
idaman int ida_export unhook_from_notification_point(
        hook_type_t hook_type,  //事件
        hook_cb_t *cb,    //回调函数
        void *user_data = NULL)
;
grcode_dblclicked

插件除了能够调用IDA SDK中的接口函数外,也能够调用平台相关的API(eg. Windows - MessageBox)


0x03 环境设置






  1. 创建动态链接库项目

IDA C++ Plug-in 浅尝


2.设置包含SDK 头文件

IDA C++ Plug-in 浅尝


3.设置包含SDK 库文件
IDA C++ Plug-in 浅尝

4.设置预处理器定义,因为是Windows 64bit 环境插件,所以设置__IDP__;__X64__;__NT__,其他平台设置参考pro.h头文件
IDA C++ Plug-in 浅尝

5.设置函数默认调用约定为__stdcall
IDA C++ Plug-in 浅尝


0x04 完整代码






#include "pch.h"
#include "ida.hpp"
#include "idp.hpp"
#include "loader.hpp"

#pragma comment(lib, "ida.lib")
define __EA64__

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )

{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

ssize_t idaapi hook_func(void *user_data, int notification_code, va_list va)
{
 if (notification_code == view_notification_t::view_click)
 {
  msg("Current address is : 0x%pn", get_screen_ea());
 }
 return 0;
}
plugmod_tIDAP_init(void)
{
 hook_to_notification_point(HT_VIEW, hook_func, NULL);
 msg("==================code by MinL@Syclover==================n");
 return PLUGIN_KEEP;
}

void IDAP_term(void)
{
 msg("==================code by MinL@Syclover==================n");
 unhook_from_notification_point(HT_OUTPUT, hook_func, NULL);
}

bool IDAP_run(size_t arg)
{
 msg("Current address is : 0x%pn", get_screen_ea());
 msg("IDA Plug is running!n");
 return TRUE;
}

char IDAP_comment[] = "This is my test plug-in";
char IDAP_help[] = "MinL plugin";
char IDAP_name[] = "MinL plugin";
char IDAP_hotkey[] = "Ctrl-Alt-l";

//导出变量
//#define ida_module_data __declspec(dllexport)
ida_module_data plugin_t PLUGIN =
{
 IDP_INTERFACE_VERSION,
 0
 IDAP_init,  
 IDAP_term,   
 IDAP_run,   
 IDAP_comment,  
 IDAP_help,   
 IDAP_name,
 IDAP_hotkey
};

整体功能十分简单,在output window 输出在view 中选定的地址,使用了两种方式激活插件,一是设置快捷键为Ctrl-Alt-l,二是安装了事件通知回调

效果如下:

IDA C++ Plug-in 浅尝


参考






  • 《IDA Pro权威指南 第2版 》 17章节
  • SDK 官方文档
    https://www.hex-rays.com/products/ida/support/sdkdoc/index.html
  • SDK 下载链接
    https://bbs.pediy.com/thread-261011-1.htm


IDA C++ Plug-in 浅尝
IDA C++ Plug-in 浅尝

三叶草小组公众号

微信号 : 三叶草小组Syclover

新浪微博:@三叶草小组Syclover

IDA C++ Plug-in 浅尝


点击原文链接查看更多〜IDA C++ Plug-in 浅尝

本文始发于微信公众号(三叶草小组Syclover):IDA C++ Plug-in 浅尝

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2020年12月23日00:10:06
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   IDA C++ Plug-in 浅尝https://cn-sec.com/archives/214786.html

发表评论

匿名网友 填写信息