使用 VS2012 开发 IDA GUI 插件 WIN32 SDK 和 内置函数 AskUsingForm_c

1. 执行菜单的File->New->Project… (Ctrl-Shift-N)打开新建工程窗口。 

2. 展开左侧的Visual C++项目模板分支,然后选择右侧的Win32 Project条目,输入工程名称,然后点击确定。

3.出现Win32Application Wizard

4. 使用默认设置

5. 生成的文件夹及文件

6. VS 解决方案资源管理器视图

7. 运行结果

8. 修改项目属性 - 选择所有配置 

常规 将目标文件扩展名修改为.plw 配置类型 动态库(.dll)

C/C++->常规 附加包含目录添加ida sdk include目录,例如 D:\IDA64\IDASDK64\Include 

C/C++->预处理器,添加__NT__;__IDP__字段到预处理器定义中。 

C/C++->代码生成,关闭安全检查

连接器->输入,将 ida.lib 添加到附加依赖项中。C:\IDA64\idasdk64\lib\x86_win_vc_32\ida.lib

 

连接器->命令行添加/EXPORT:PLUGIN 

生成事件->后期生成事件,将生成的文件复制到 ida 插件目录

xcopy /c /d /r /y "$(TargetPath)" "D:\IDA64\plugins\"

 8. 新建配置用于调试 EXE

修改配置属性 -

常规 将目标文件扩展名修改为.exe 配置类型 应用程序(.exe)

连接器->命令行删除 /EXPORT:PLUGIN 

生成事件->后期生成事件,删除 copy /c /d /r /y "$(TargetPath)" "D:\IDA64\plugins\"

 

C/C++->预处理器,添加_DEBUG_EXE 字段到预处理器定义中。 

8. 添加新文件 ida_plug_main.cpp

 

ida_plug_main.cpp

#include "stdafx.h"

int __stdcall IDAP_init ( void )
{
  // Do checks here to ensure your plug-in is being used within
  // an environment it was written for. Return PLUGIN_SKIP if the
  // checks fail, otherwise return PLUGIN_KEEP.
  return ( PLUGIN.flags & PLUGIN_UNL ) ? PLUGIN_OK : PLUGIN_KEEP;
}

void __stdcall IDAP_term ( void )
{
  // Stuff to do when exiting, generally you'd put any sort
  // of clean-up jobs here.
  return;
}

// The plugin can be passed an integer argument from the plugins.cfg
// file. This can be useful when you want the one plug-in to do
// something different depending on the hot-key pressed or menu
// item selected.
void __stdcall IDAP_run ( int arg )
{
  // The "meat" of your plug-in
  msg ( "ida plug-in run!\n" );
}

// There isn't much use for these yet, but I set them anyway.
char IDAP_comment[]   = "ida plug-in template";
char IDAP_help[]    = "ida plug-in template";

// The name of the plug-in displayed in the Edit->Plugins menu. It can
// be overridden in the user's plugins.cfg file.
char IDAP_name[]    = "ida plug-in template";

// The hot-key the user can use to run your plug-in.
char IDAP_hotkey[]  = "Ctrl-Alt-X";

// The all-important exported PLUGIN object
plugin_t PLUGIN =
{
  IDP_INTERFACE_VERSION,  // IDA version plug-in is written for
  PLUGIN_UNL,     // Flags (see below)
  IDAP_init,      // Initialisation function
  IDAP_term,      // Clean-up function
  IDAP_run,       // Main plug-in body
  IDAP_comment,   // Comment unused
  IDAP_help,      // As above unused
  IDAP_name,      // Plug-in name shown in
  IDAP_hotkey     // Hot key to run the plug-in
};

 

修改 "stdafx.h" 文件, 添加 ida sdk 头文件

// stdafx.h : 标准系统包含文件的包含文件,
// 或是经常使用但不常更改的
// 特定于项目的包含文件
//

#pragma once

#include "targetver.h"

#define WIN32_LEAN_AND_MEAN             //  从 Windows 头文件中排除极少使用的信息
// Windows 头文件:
#include <windows.h>

// C 运行时头文件
#include <stdlib.h>
#include <malloc.h>
#include <memory.h>
#include <tchar.h>


// TODO: 在此处引用程序需要的其他头文件
#include <ida.hpp>

#include <idp.hpp>
#include <loader.hpp>
#include <kernwin.hpp>

#include <area.hpp>
#include <segment.hpp>
#include <funcs.hpp>
#include <lines.hpp>
#include <srarea.hpp>

#include <ua.hpp>
#include <xref.hpp>
#include <offset.hpp>
#include <bytes.hpp>
#include <name.hpp>
#include <enum.hpp>
#include <struct.hpp>

 

 现在通过VS2012调试 ida_plugin_template.exe, 提示 : 无法启动此程序,因为计算机中丢失 IDA.WLL。尝试重新安装该程序以解决此问题。 

复制 D:\IDA64 文件夹中的 ida.wll 到 ida_plugin_template.exe 所在文件夹 D:\workspace_c++\ida_sdk_projects\ida_plugin_template\DebugExe 即可调试

ida_plugin_template.plw 也可以被 ida 加载 < Ctrl-Alt-X >

 

ida 输出 //  msg ( "ida plug-in run!\n" );

在 ida_plug_main.cpp 源代码中设置断点, 然后使用 VS2012 工具 - 附加到进程...

选择 idaq.exe 即可调试 ida_plugin_template.plw

现在再次调用插件, 会在设置的断点处停下来, 等待调试

 

修改   ida_plug_main.cpp  和 ida_plugin_template.cpp 使插件显示 GUI 窗口

同时修改 D:\IDA64\plugins\plugins.cfg 可是传入不同的参数给插件

                 ida_plugin_template_0                     ida_plugin_template    Ctrl-Alt-0    0
                 ida_plugin_template_1                     ida_plugin_template    Ctrl-Alt-1    1

  

#include "stdafx.h"

int __stdcall IDAP_init ( void )
{
  // Do checks here to ensure your plug-in is being used within
  // an environment it was written for. Return PLUGIN_SKIP if the
  // checks fail, otherwise return PLUGIN_KEEP.
  return ( PLUGIN.flags & PLUGIN_UNL ) ? PLUGIN_OK : PLUGIN_KEEP;
}

void __stdcall IDAP_term ( void )
{
  // Stuff to do when exiting, generally you'd put any sort
  // of clean-up jobs here.
  return;
}

void __stdcall IDAP_run ( int arg );


// There isn't much use for these yet, but I set them anyway.
char IDAP_comment[]   = "ida plug-in template";
char IDAP_help[]    = "ida plug-in template";

// The name of the plug-in displayed in the Edit->Plugins menu. It can
// be overridden in the user's plugins.cfg file.
char IDAP_name[]    = "ida plug-in template";

// The hot-key the user can use to run your plug-in.
char IDAP_hotkey[]  = "Ctrl-Alt-X";

// The all-important exported PLUGIN object
plugin_t PLUGIN =
{
  IDP_INTERFACE_VERSION,  // IDA version plug-in is written for
  PLUGIN_UNL,     // Flags (see below)
  IDAP_init,      // Initialisation function
  IDAP_term,      // Clean-up function
  IDAP_run,       // Main plug-in body
  IDAP_comment,   // Comment unused
  IDAP_help,      // As above unused
  IDAP_name,      // Plug-in name shown in
  IDAP_hotkey     // Hot key to run the plug-in
};

//------------------------------------------------------------------------------------- BOOL CALLBACK EnumIdaMainWindow ( HWND hwnd, LPARAM lParam ) { WINDOWINFO winInfo; DWORD dwIdaProcessId
= * ( ( DWORD* ) lParam ); DWORD dwProcessId; GetWindowThreadProcessId ( hwnd, &dwProcessId ); winInfo.cbSize = sizeof ( WINDOWINFO ); GetWindowInfo ( hwnd, &winInfo ); if ( dwProcessId == dwIdaProcessId && GetParent ( hwnd ) == NULL && winInfo.dwStyle & WS_VISIBLE ) { * ( ( HWND * ) lParam ) = hwnd; return FALSE; // stop EnumWindow() } return TRUE; }
//------------------------------------------------------------------------------------ HWND GetIdaMainWindow (
void ) { DWORD dwIdaProcessId = GetCurrentProcessId(); if ( !EnumWindows ( EnumIdaMainWindow, ( LPARAM ) &dwIdaProcessId ) ) { return ( HWND ) dwIdaProcessId; } return NULL; } HWND GetIdaMainWindow ( void ); int APIENTRY _tWinMain ( _In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPTSTR lpCmdLine, _In_ int nCmdShow ); // The plugin can be passed an integer argument from the plugins.cfg // file. This can be useful when you want the one plug-in to do // something different depending on the hot-key pressed or menu // item selected. void __stdcall IDAP_run ( int arg ) { // The "meat" of your plug-in msg ( "ida plug-in run!\n" );
HWND hIdaMainWindow
= GetIdaMainWindow(); if ( hIdaMainWindow == NULL ) return; switch ( arg ) { case 0: case 1: _tWinMain ( NULL, ( HINSTANCE ) hIdaMainWindow, ( LPWSTR ) arg, SW_SHOWNORMAL ); break; default: break; } }

 

// ida_plugin_template.cpp : 定义应用程序的入口点。
//

#include "stdafx.h"
#include "ida_plugin_template.h"

#define MAX_LOADSTRING 100

// 全局变量:
HINSTANCE hInst;                // 当前实例
TCHAR szTitle[MAX_LOADSTRING];          // 标题栏文本
TCHAR szWindowClass[MAX_LOADSTRING];      // 主窗口类名

// 此代码模块中包含的函数的前向声明:
ATOM        MyRegisterClass ( HINSTANCE hInstance );
BOOL        InitInstance ( HINSTANCE, int );
LRESULT CALLBACK  WndProc ( HWND, UINT, WPARAM, LPARAM );
INT_PTR CALLBACK  About ( HWND, UINT, WPARAM, LPARAM );

HWND hIdaMainWindow = NULL;                                                       
int idaArg;                                                                       

int APIENTRY _tWinMain (
  _In_ HINSTANCE hInstance,
  _In_opt_ HINSTANCE hPrevInstance,
  _In_ LPTSTR    lpCmdLine,
  _In_ int       nCmdShow )
{
  UNREFERENCED_PARAMETER ( hPrevInstance );
  UNREFERENCED_PARAMETER ( lpCmdLine );
  // TODO: 在此放置代码。
  //
#ifndef _DEBUG_EXE
  
//
  if ( hInstance == NULL )
  {
    hInstance = GetModuleHandle ( L"ida_plugin_template.plw" );
    
    if ( hInstance == NULL )
      return 0;
      
    idaArg = ( int ) lpCmdLine;
    hIdaMainWindow = ( HWND ) hPrevInstance;
  }
  
#endif

MSG msg; HACCEL hAccelTable; // 初始化全局字符串 LoadString ( hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING ); LoadString ( hInstance, IDC_IDA_PLUGIN_TEMPLATE, szWindowClass, MAX_LOADSTRING ); MyRegisterClass ( hInstance ); // 执行应用程序初始化: if ( !InitInstance ( hInstance, nCmdShow ) ) return FALSE; hAccelTable = LoadAccelerators ( hInstance, MAKEINTRESOURCE ( IDC_IDA_PLUGIN_TEMPLATE ) ); // 主消息循环: // retrieves a message other than WM_QUIT BOOL bRet; while ( ( bRet = GetMessage ( &msg, NULL, 0, 0 ) ) != 0 ) { if ( bRet == - 1 ) break; if ( !TranslateAccelerator ( msg.hwnd, hAccelTable, &msg ) ) { TranslateMessage ( &msg ); DispatchMessage ( &msg ); } } // retrieves the WM_QUIT message // or hWnd is an invalid window handle or lpMsg is an invalid pointer. // return ( int ) msg.wParam; // WM_QUIT wParam } // // 函数: MyRegisterClass() // // 目的: 注册窗口类。 // ATOM MyRegisterClass ( HINSTANCE hInstance ) { WNDCLASSEX wcex; wcex.cbSize = sizeof ( WNDCLASSEX ); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = WndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hIcon = LoadIcon ( hInstance, MAKEINTRESOURCE ( IDI_IDA_PLUGIN_TEMPLATE ) ); wcex.hCursor = LoadCursor ( NULL, IDC_ARROW ); wcex.hbrBackground = ( HBRUSH ) ( COLOR_WINDOW + 1 ); wcex.lpszMenuName = MAKEINTRESOURCE ( IDC_IDA_PLUGIN_TEMPLATE ); wcex.lpszClassName = szWindowClass; wcex.hIconSm = LoadIcon ( wcex.hInstance, MAKEINTRESOURCE ( IDI_SMALL ) ); return RegisterClassEx ( &wcex ); } // // 函数: InitInstance(HINSTANCE, int) // // 目的: 保存实例句柄并创建主窗口 // // 注释: // // 在此函数中,我们在全局变量中保存实例句柄并 // 创建和显示主程序窗口。 // BOOL InitInstance ( HINSTANCE hInstance, int nCmdShow ) { HWND hWnd; hInst = hInstance; // 将实例句柄存储在全局变量中 hWnd = CreateWindow ( szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,
hIdaMainWindow,
NULL, hInstance, NULL );
if ( !hWnd )
  {
    return FALSE;
  }
  
  ShowWindow ( hWnd, nCmdShow );
  UpdateWindow ( hWnd );
  return TRUE;
}

//
//  函数: WndProc(HWND, UINT, WPARAM, LPARAM)
//
//  目的: 处理主窗口的消息。
//
//  WM_COMMAND  - 处理应用程序菜单
//  WM_PAINT  - 绘制主窗口
//  WM_DESTROY  - 发送退出消息并返回
//
//
LRESULT CALLBACK WndProc ( HWND hWnd, UINT message, WPARAM wParam,
                           LPARAM lParam )
{
  int wmId, wmEvent;
  PAINTSTRUCT ps;
  HDC hdc;
  
  switch ( message )
  {
    case WM_COMMAND:
      wmId    = LOWORD ( wParam );
      wmEvent = HIWORD ( wParam );
      
      // 分析菜单选择:
      switch ( wmId )
      {
        case IDM_ABOUT:
          DialogBox ( hInst, MAKEINTRESOURCE ( IDD_ABOUTBOX ), hWnd, About );
          break;
          
        case IDM_EXIT:
          DestroyWindow ( hWnd );
          break;
          
        default:
          return DefWindowProc ( hWnd, message, wParam, lParam );
      }
      
      break;
      
    case WM_PAINT:
      hdc = BeginPaint ( hWnd, &ps );
      // TODO: 在此添加任意绘图代码...
      EndPaint ( hWnd, &ps );
      break;
      
    case WM_CREATE:                                                            
      if ( hIdaMainWindow )
        EnableWindow ( hIdaMainWindow, FALSE );
        
      break;
      
    case WM_DESTROY:                                                           
      if ( hIdaMainWindow )
        EnableWindow ( hIdaMainWindow, TRUE );
        
      PostQuitMessage ( 0 ); // WM_QUIT, wParam = 0
      break;
      
    default:
      return DefWindowProc ( hWnd, message, wParam, lParam );
  }
  
  return 0;
}

// “关于”框的消息处理程序。
INT_PTR CALLBACK About ( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam )
{
  UNREFERENCED_PARAMETER ( lParam );
  
  switch ( message )
  {
    case WM_INITDIALOG:
      return ( INT_PTR ) TRUE;
      
    case WM_COMMAND:
      if ( LOWORD ( wParam ) == IDOK || LOWORD ( wParam ) == IDCANCEL )
      {
        EndDialog ( hDlg, LOWORD ( wParam ) );
        return ( INT_PTR ) TRUE;
      }
      
      break;
  }
  
  return ( INT_PTR ) FALSE;
}

修改   ida_plug_main.cpp  使用内置的界面显示

 

 

static void __stdcall AskUsingForm ( void );

// The plugin can be passed an integer argument from the plugins.cfg
// file. This can be useful when you want the one plug-in to do
// something different depending on the hot-key pressed or menu
// item selected.
void __stdcall IDAP_run ( int arg )
{
  // The "meat" of your plug-in
  msg ( "ida plug-in run!\n" );
  HWND hIdaMainWindow = GetIdaMainWindow();
  
  if ( hIdaMainWindow == NULL )
    return;
    
  switch ( arg )
  {
    case 0:
      _tWinMain ( NULL, ( HINSTANCE ) hIdaMainWindow, ( LPWSTR ) arg, SW_SHOWNORMAL );
      break;
      
    case 1:
      AskUsingForm();
      break;
      
    default:
      break;
  }
}

static const char *dialog1 = //
  "This is the title\n\n"// dialog title
  "<##Radio Buttons##Radio 1:R>\n"
  "<Radio 2:R>>\n"//ushort* number of selected radio
  "<##Radio Buttons##Radio 1:R>\n"
  "<Radio 2:R>>\n"//ushort* number of selected radio
  "<##Check Boxes##Check 1:C>\n"
  "<Check 2:C>>\n"//ushort* bitmask of checks
  "<##Check Boxes##Check 1:C>\n"
  "<Check 2:C>>\n";//ushort* bitmask of checks

static void __stdcall AskUsingForm ( void )
{
  ushort bitMask, bitMask1 = 0;
  ushort btnIndex, bitIndex1;
  int ok = AskUsingForm_c ( dialog1, &btnIndex, &bitIndex1, &bitMask, &bitMask1 );
}

 

 

posted @ 2013-09-30 09:02  IAmAProgrammer  阅读(1701)  评论(0编辑  收藏  举报