开发IDA pro图形界面插件
1、 基于IDA SDK实现图形界面(GUI)插件
2、 调用native Windows API的IDA GUI插件
3、 使用MFC设计IDA GUI插件
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
图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]《加密与解密》第二版 段钢 编著