插件编写实战
我们要做一个类似于SharpOD的插件,来帮我们能够调试异常处理函数
也就是我们要写一个Dll进行API Hook
把之前说的跳转改掉
OD的SDK帮我们写好了修改被调试进程的内存修改函数,也就是这里:
Writememory
那时候调用这个函数呢? 以下是插件的回调函数:
利用这个帮助文档,代码示例如下:
// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "pch.h"
#include "Plugin.h"
#pragma comment(lib,"OLLYDBG.LIB")
extc int _export cdecl ODBG_Plugindata(char* shortname)
{
strcpy_s(shortname, 31, "my_od_plugin");
return PLUGIN_VERSION;
}
extc int _export cdecl ODBG_Plugininit(
int ollydbgversion,
HWND hw,
unsigned long* features)
{
return 0;
}
extc int ODBG_Paused cdecl(int reason, t_reg* reg)
{
//拿一下函数在内存的句柄
HMODULE hKernel = GetModuleHandle("Kernelbase.dll");
BYTE* Addr = (BYTE*)GetProcAddress(hKernel, "UnhandledExceptionFilter");
//定位偏移
Addr += 0xA9;
char m_byte = 0x84;
Writememory((void*)&m_byte, (ulong)Addr, 1, MM_SILENT);
return 0;
}
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
同理,我们开发下X96dbg的:
// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "pch.h"
#include "plugin.h"
#include <Windows.h>
#include <process.h>
int pluginHandle;
HWND hwndDlg;
int hMenu;
int hMenuDisasm;
int hMenuDump;
int hMenuStack;
// 导出函数
extern "C" __declspec(dllexport) void CBMENUENTRY(CBTYPE cbType, PLUG_CB_MENUENTRY * info);
extern "C" __declspec(dllexport) void plugsetup(PLUG_SETUPSTRUCT * setupStruct);
extern "C" __declspec(dllexport) bool pluginit(PLUG_INITSTRUCT * initStruct);
extern "C" __declspec (dllexport) void CBINITDEBUG(CBTYPE cbType, PLUG_CB_INITDEBUG * info);
extern "C" __declspec (dllexport) void CBSTOPDEBUG(CBTYPE cbType, PLUG_CB_STOPDEBUG * info);
extern "C" __declspec (dllexport) void CBEXCEPTION(CBTYPE cbType, PLUG_CB_EXCEPTION * info);
extern "C" __declspec (dllexport) void CBDEBUGEVENT(CBTYPE cbType, PLUG_CB_DEBUGEVENT * info);
// 在这里初始化插件数据。
bool pluginInit(PLUG_INITSTRUCT* initStruct)
{
// 返回false以取消加载插件。
return true;
}
// 在此处取消初始化插件数据。
void pluginStop()
{
}
// 在这里做GUI/菜单相关的事情。
void pluginSetup()
{
}
// 菜单被点击回调
void CBMENUENTRY(CBTYPE cbType, PLUG_CB_MENUENTRY* info)
{
// 此菜单用于实现功能,并测试
MessageBox(0, "hello lyshark", 0, 0);
}
PLUG_EXPORT bool pluginit(PLUG_INITSTRUCT* initStruct)
{
// 插件初始化
initStruct->sdkVersion = PLUG_SDKVERSION;
initStruct->pluginVersion = 1;
const char* name = "CheckME -->";
memset(initStruct->pluginName, 0, 128);
memcpy(initStruct->pluginName, name, strlen(name));
return pluginInit(initStruct);
}
PLUG_EXPORT bool plugstop()
{
pluginStop();
return true;
}
PLUG_EXPORT void CBDEBUGEVENT(CBTYPE cbType, PLUG_CB_DEBUGEVENT* info)
{
//拿一下函数在内存的句柄
HMODULE hKernel = GetModuleHandle("Kernelbase.dll");
BYTE* Addr = (BYTE*)GetProcAddress(hKernel, "UnhandledExceptionFilter");
//定位偏移
Addr += 0xA9;
char m_byte = 0x84;
DbgMemWrite((duint)Addr, &m_byte, 1);
return;
}
PLUG_EXPORT void plugsetup(PLUG_SETUPSTRUCT* setupStruct)
{
hwndDlg = setupStruct->hwndDlg;
hMenu = setupStruct->hMenu;
hMenuDisasm = setupStruct->hMenuDisasm;
hMenuDump = setupStruct->hMenuDump;
hMenuStack = setupStruct->hMenuStack;
// 增加二级菜单
char sub_menu[] = { "PowerBy LyShark" };
_plugin_menuaddentry(setupStruct->hMenu, 2, sub_menu);
pluginSetup();
}
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
值得注意的是,x96dbg开发插件如果要调试的话,稍微有点麻烦
首先是输出要改一下后缀,后缀不能是dll,而是要写.dp32
而且输出目录也要改成x96dbg的插件目录
然后把调试的参数改为x96dbg的exe所在路径
这样之后,按下F5才可以断下来
还有值得一提的是x96dbg的回调导出函数,我这该死的中文文档并未提及,我找了半天
extern "C" __declspec ( dllexport ) void CBINITDEBUG ( CBTYPE cbType , PLUG_CB_INITDEBUG * info );
extern "C" __declspec ( dllexport ) void CBSTOPDEBUG ( CBTYPE cbType , PLUG_CB_STOPDEBUG * info );
extern "C" __declspec ( dllexport ) void CBEXCEPTION ( CBTYPE cbType , PLUG_CB_EXCEPTION * info);
extern "C" __declspec ( dllexport ) void CBDEBUGEVENT ( CBTYPE cbType , PLUG_CB_DEBUGEVENT * info );
extern "C" __declspec ( dllexport ) void CBMENUENTRY ( CBTYPE cbType , PLUG_CB_MENUENTRY * info );
这些回调函数是针对调试器插件开发的,在 x96dbg 中用于处理不同类型的调试事件。以下是每个回调函数的作用:
-
CBINITDEBUG
: 当调试器初始化时调用此回调函数。这个回调函数允许插件在调试器启动时执行一些初始化操作,比如注册一些特定的事件处理器或者设置一些调试环境。 -
CBSTOPDEBUG
: 当调试器停止时调用此回调函数。这个回调函数允许插件在调试器停止时执行一些清理工作,比如释放资源或者关闭一些已经打开的文件。 -
CBEXCEPTION
: 当调试器捕获到异常时调用此回调函数。这个回调函数允许插件处理程序中的异常情况,比如访问违规或者除零等。 -
CBDEBUGEVENT
: 当调试器捕获到调试事件时调用此回调函数。这个回调函数允许插件处理各种调试事件,比如断点命中、单步执行、内存访问等。 -
CBMENUENTRY
: 当用户在调试器菜单中选择了插件提供的菜单项时调用此回调函数。这个回调函数允许插件执行与菜单项相关的操作,比如执行特定的分析、跳转到特定的地址等。
他喵的终于断下来了