开发IDA pro图形界面插件


1、  基于IDA SDK实现图形界面(GUI)插件
2、  调用native Windows API的IDA GUI插件
3、  使用MFC设计IDA GUI插件

引用:
运行环境:Windows 2000,IDA pro 5.2,Visual C++ 6.0


1、  基于IDA SDK接口实现图形界面(GUI)插件

最早看到一份介绍编写IDA GUI插件的文章(见参考资料[1]),当时不太懂,只大约记得作者提到了可以实现IDA GUI插件,后来随着对IDA插件接口的有了一些认识,又使用了一些插件,例如Pedram Amini的pGraph,很简洁,也相当实用,如图1-1: 
  


          图 1-1
经过分析其源代码,发现他使用的IDA SDK里面提供的UI(user interface)函数来实现,即AskUsingForm_c函数,该函数弹出一个对话框,而对话框的外观形式,就由此函数的第一个参数form(const char *类型)指定。
那么又如何使用form参数,进行界面设计呢?IDA SDK里的kernwin.hpp中,有关于对form参数的一些描述,头文件中有一段“Format of FORM text strings”的注释,form参数是由一些关键字+格式符组成的字符串,请看附件示例代码(ui_plugin):


int type0=0;
  int type1=1;
  int type;
  const char form[] = "STARTITEM 0\n"
        "IDA GUI Plugin\n"
        "Options\n\n"
        "Type:\n"
            " <Type0:R> <Type1:R>>\n\n\n"
    "\n\n";
  AskUsingForm_c(form, &type);

form参数的第一个关键字,STARTITEM指明了对话框弹出时,焦点停在哪个控件上,0表示第一个控件,其它类推。
第二行表示对话框的标题栏,这里是,IDA GUI Plugin。
第三行就是一个简单的静态字符控件,这里为,Options。
第四行与第三行类似。
第五行," <Type0:R> <Type1:R>>\n\n\n",尖括号表示控件,Type0表示控件显示名称,后加冒号,R表示单选按钮类型控件。

调用AskUsingForm_c函数,记得要加第二个参数type,表示选择了哪个按钮,type返回0表示选择了第一个按钮,1表示第二个,其它类推。对话框外观如图1-2:
 


        图1-2

其它控件的设计,可以参考kernwin.hpp中的“Format of FORM text strings”注释一段,可以看到,编写设计这样的对话框有些繁琐,而且没有可视性,比较简单的对话框,倒还好处理,稍微复杂一些的,可能就不那么好弄了,而且扩展性也有限。那还有其它方式编写IDA GUI插件吗?






2、调用native Windows API的IDA GUI插件
08年,在pediy论坛与BeQuick曾有过一番在IDA插件里调用WIN API的讨论[2],BeQuick想在IDA插件里实现Windows程序的消息泵,经测试,发现完全可行,借用《Programming Windows》一书中的WinMain函数的一般性模板代码,还有Window Procedure(WndProc)的模板代码,如下:

void idaapi run(int arg)
{
    win();

}

int win()
{
    HINSTANCE hInstance = GetModuleHandle("window.Plw");
    HWND     hwnd ;
    MSG      msg ;
    WNDCLASS wndclass ;

    wndclass.style         = CS_HREDRAW | CS_VREDRAW ;
    wndclass.lpfnWndProc   = WndProc ;
    wndclass.cbClsExtra    = 0 ;
    wndclass.cbWndExtra    = 0 ;
    wndclass.hInstance     = hInstance ;
    wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION) ;
    wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;
    wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
    wndclass.lpszMenuName  = szAppName ;
    wndclass.lpszClassName = szAppName  ;
     
    if (!RegisterClass (&wndclass))
    {
         MessageBox (NULL, TEXT ("This program requires Windows NT!"),
                     szAppName, MB_ICONERROR) ;
         return 0 ;
    }
     
    hwnd = CreateWindow (szAppName, TEXT ("Windowing IDA plugin"),
                         WS_OVERLAPPEDWINDOW,
                         300, 200,
                         CW_USEDEFAULT, CW_USEDEFAULT,
                         NULL, NULL, hInstance, NULL) ;
     
    ShowWindow (hwnd, SW_NORMAL) ;
    UpdateWindow (hwnd) ;
     
    while (GetMessage (&msg, NULL, 0, 0))
    {
         TranslateMessage (&msg) ;
         DispatchMessage (&msg) ;
    }

    UnregisterClass(szAppName,hInstance);
    return msg.wParam;
}

Win函数即一般性WinMain函数,稍微有些出入的地方是,因为是插件自己建立窗口,消息泵,所以hInstance模块句柄要显性调用获取,即,
HINSTANCE hInstance = GetModuleHandle("window.Plw");
其中window.plw为编译生成后的插件文件名。

还有一处稍有不同,即:
UnregisterClass(szAppName,hInstance);
反注册窗口类,若没有这行,退出插件窗口,紧接着再打开插件窗口就会出错。

剩下的就是WndProc的编写了,大家都是Win程序员老手,就由各位凭想象力任意发挥了。另外有点要注意的是,菜单的资源ID,要改成wndclass.lpszMenuName对应的字符串,还要添加双引号,比如wndclass.lpszMenuName为MENU,菜单资源ID就要改成“MENU”,含双引号。如图2-1
 


图2-1

这里简单设计了插件窗口的菜单,按钮一类的,详细代码请参考附件示例window
 


图 2-2


3、使用MFC设计IDA GUI插件
微软对Win API进行面向对象封装,进而开发出MFC库,既然插件能调用Win API,那使用MFC行不行呢?于是乎,产生了一个大胆的想法,用MFC来设计IDA GUI插件,并使用MFC的RAD技术设计插件的界面。
首先,让我们建立一个使用Visual C++ 6.0的App Wizard程序向导,建立一个MFC Exe应用程序,命名为,mfcplugin,如图3-1
 名称:  wizard.jpg
查看次数: 728
文件大小:  66.6 KB
图3-1

确定,然后在下一步中,选定Dialog Based,基于对话框模式,如图3-2
 


图3-2

  

下一步Next,去掉3D controls选项(没有太必要3D控件),如图3-3


图3-3

然后Finish,这样就建好了一个基于Dialog模式的MFC应用程序工程,如图3-4:
 


图3-4

接着我们在工程设置里面添加两个IDA插件的预处理定义符(__NT__,__IDP__),Alt+F7快键打开工程设置,选择C/C++选项卡,如图3-5
 


图3-5

在Preprocessor definitions一栏,添加__NT__,__IDP__,再选择Link选项卡,在Object/Library modules一栏中,添加ida.lib。然后修改Output file name一栏中mfcplugin.exe为mfcplugin.plw,在Link选项卡的Project Options中,添加“/dll /export:PLUGIN”

一切设置妥当之后,剩下的就是添加插件实现代码了。首先在stdafx.h中,包含如下IDA SDK提供的头文件:
#include <ida.hpp>
#include <idp.hpp>
#include <expr.hpp>
#include <bytes.hpp>
#include <loader.hpp>
#include <kernwin.hpp>

还有就是那个关键的插件run函数,要如何设计呢?这里还是模仿Visual C++ 6.0附带MFC源代码的WINMAIN.CPP中,AfxWinMain的实现方式,因为大家都知道,一般MFC应用程序,都是从这里开始的,顾名思义,也就是MFC程序的WinMain。稍做了一些添加修改,和前面的那个WIN API设计的插件类似,要获取到插件本身的模块句柄,仍然通过如下显性调用获取模块句柄。
HINSTANCE hInstance = GetModuleHandle("mfcplugin.plw");

插件的其它函数,例如init函数,term函数,还有一些结构的导出,和这个自制的run函数一同添加到mfcplugin.cpp文件最末尾处,

好了,一切就绪后,就实验我们最初的那个想法,使用MFC的RAD技术设计插件界面,在资源编辑中,添加一个Edit Box控件,详细代码请参考mfcplugin

最终效果如图3-6:


图3-6

参考资料 
[1] 《Some ideas about extending the IDA GUI with plugins》

http://www.the-interweb.com/serendipity/index.php?/archives/65-Some-ideas-about-extending-the-IDA-GUI-with-plugins.html

[2] 《关于在IDA插件中调用windows API 以及 实现消息循环机制》

http://bbs.pediy.com/showthread.php?t=62707

[3]《Programming Windows》第五版 Charles Petzold著

[4]《Programing Visual C++》第五版 David J. Kruglinski著
[5]《加密与解密》第二版 段钢 编著

posted @ 2011-09-30 17:09  麦峰强  阅读(3605)  评论(2编辑  收藏  举报