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

时间:2023-03-10 06:43:39
使用 VS2012 开发 IDA GUI 插件 WIN32 SDK 和 内置函数 AskUsingForm_c

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

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

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

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

3.出现Win32Application Wizard

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

4. 使用默认设置

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

5. 生成的文件夹及文件

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

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

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

7. 运行结果
使用 VS2012 开发 IDA GUI 插件 WIN32 SDK 和 内置函数 AskUsingForm_c

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

8. 新建配置用于调试 EXE

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

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

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

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

修改配置属性 -

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

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

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

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

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

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

8. 添加新文件 ida_plug_main.cpp

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

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

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。尝试重新安装该程序以解决此问题。

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

复制 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 >

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

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

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

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

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

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

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

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

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

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

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

                 ida_plugin_template_0                     ida_plugin_template    Ctrl-Alt-
ida_plugin_template_1 ida_plugin_template Ctrl-Alt-

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

#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 :
case :
_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 ; 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, , ) ) != )
{
if ( bRet == - )
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 = ;
wcex.cbWndExtra = ;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon ( hInstance,
MAKEINTRESOURCE ( IDI_IDA_PLUGIN_TEMPLATE ) );
wcex.hCursor = LoadCursor ( NULL, IDC_ARROW );
wcex.hbrBackground = ( HBRUSH ) ( COLOR_WINDOW + );
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, , CW_USEDEFAULT, ,
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 ( ); // WM_QUIT, wParam = 0
break; default:
return DefWindowProc ( hWnd, message, wParam, lParam );
} return ;
} // “关于”框的消息处理程序。
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 :
_tWinMain ( NULL, ( HINSTANCE ) hIdaMainWindow, ( LPWSTR ) arg, SW_SHOWNORMAL );
break; case :
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 = ;
ushort btnIndex, bitIndex1;
int ok = AskUsingForm_c ( dialog1, &btnIndex, &bitIndex1, &bitMask, &bitMask1 );
}

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