• 开发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]《加密与解密》第二版 段钢 编著

  • 相关阅读:
    [CF1398E] Two Types of Spells
    [CF1399E2] Weights Division (hard version)
    [CF1400E] Clear the Multiset
    Review 2020.10.29
    Review 2020.10.11
    [CF1409F] Subsequences of Length Two
    [CF1413E] Solo mid Oracle
    [2020CCPC威海C] Rencontre
    [2020CCPC威海B] Labyrinth
    phpredis实现简单的消息队列
  • 原文地址:https://www.cnblogs.com/maifengqiang/p/2196716.html
Copyright © 2020-2023  润新知