1. 找到”我的文档”目录
2. 在我的文档中找到vs版本对应的文件夹
3. 把模板复制到”我的文档”\Visual studio 20XX\Templates\ProjectTemplates\
4. 打开VS,新建一个项目
5. 修改项目属性:
调试工具的插件是一项特别重要的扩展功能,本篇本章总结了简单的插件编写流程。
- 开发工具 VS2015
- 调试工具Ollydbg2.01
- 用到的工具 源代码放到附件
Ollydbg插件其实是一个导出有指定函数的DLL文件,按照指定名称,导出的函数会在Ollydbg执行到某一阶段或触发某个事件时主动调用。
Ollydbg插件其实是一个导出有指定函数的DLL文件,按照指定名称,导出的函数会在Ollydbg执行到某一阶段或触发某个事件时主动调用。
ODBG2_Pluginquery() 是一个必选的导出函数,其余函数可以不导出.。
ODBG2_Pluginquery() 是一个必选的导出函数,其余函数可以不导出.。
ODBG2_Pluginquery() 是一个必选的导出函数,其余函数可以不导出.。
ODBG2_Pluginquery()://判断插件所需要的API版本,如果不能满足则卸载此插件
ODBG2_Plugininit()://当插件通过版本检测后准备加载时,OllyDBG会调用此函数
ODBG2_Pluginoptions()://打开插件对话框时,OllyDBG调用此函数,并派发消息
ODBG2_Pluginreset()://当重新加载程序或打开新程序时,OllyDBG会调用此函数
ODBG2_Pluginuddrecord()://当加载UDD文件或遇到插件预先保存的数据,OllyDBG会针对每条记录分别调用此函ODBG2_Pluginanalyse()://分析模块时,在分析结束后OllyDBG会调用此函数,给插件以机会使之能做一些额外的分析操作ODBG2_Pluginmainloop(NULL)://OllyDBG会周期性地调用此函数
ODBG2_Pluginmainloop()://任意事件传递过来时都会传递给此函数
ODBG2_Pluginexception()://事件是EXCEPTION_DEBUG_EVENT则调用此函数
ODBG2_Plugintempbreakpoint()://插件请求设置的临时断点事件会调用此函数
ODBG2_Pluginnotify()://一些其他的重要事件发生时,OllyDBG会调用此函数
ODBG2_Plugindump()://当OllyDBG重绘其他转储窗口时会调用此函数,插件可以借此机会修改这些窗口的字体或外ODBG2_Pluginmenu()://在点击窗口主菜单或点击右键以期望弹出菜单时,OllyDBG将调用此函数,并将函数返回的数据添加的将要弹出的菜单中
ODBG2_Pluginsaveudd()://当Windows从内存中卸载模块时,OllyDBG会调用此函数,以便插件能将相关数据保存到UDD文件中
ODBG2_Pluginclose()://当用户关闭调试时,OllyDBG在关闭前会调用此函数
ODBG2_Plugindestroy()://当OllyDBG将要终止时,它会在退出前调用一次此
ODBG2_Pluginquery()://判断插件所需要的API版本,如果不能满足则卸载此插件
ODBG2_Plugininit()://当插件通过版本检测后准备加载时,OllyDBG会调用此函数
ODBG2_Pluginoptions()://打开插件对话框时,OllyDBG调用此函数,并派发消息
ODBG2_Pluginreset()://当重新加载程序或打开新程序时,OllyDBG会调用此函数
ODBG2_Pluginuddrecord()://当加载UDD文件或遇到插件预先保存的数据,OllyDBG会针对每条记录分别调用此函ODBG2_Pluginanalyse()://分析模块时,在分析结束后OllyDBG会调用此函数,给插件以机会使之能做一些额外的分析操作ODBG2_Pluginmainloop(NULL)://OllyDBG会周期性地调用此函数
ODBG2_Pluginmainloop()://任意事件传递过来时都会传递给此函数
ODBG2_Pluginexception()://事件是EXCEPTION_DEBUG_EVENT则调用此函数
ODBG2_Plugintempbreakpoint()://插件请求设置的临时断点事件会调用此函数
ODBG2_Pluginnotify()://一些其他的重要事件发生时,OllyDBG会调用此函数
ODBG2_Plugindump()://当OllyDBG重绘其他转储窗口时会调用此函数,插件可以借此机会修改这些窗口的字体或外ODBG2_Pluginmenu()://在点击窗口主菜单或点击右键以期望弹出菜单时,OllyDBG将调用此函数,并将函数返回的数据添加的将要弹出的菜单中
ODBG2_Pluginsaveudd()://当Windows从内存中卸载模块时,OllyDBG会调用此函数,以便插件能将相关数据保存到UDD文件中
ODBG2_Pluginclose()://当用户关闭调试时,OllyDBG在关闭前会调用此函数
ODBG2_Plugindestroy()://当OllyDBG将要终止时,它会在退出前调用一次此
将附件中的模板导入到VS文件目录下。
1. 找到”我的文档”目录
2. 在我的文档中找到vs版本对应的文件夹
3. 把模板复制到”我的文档”\Visual studio 20XX\Templates\ProjectTemplates\
4. 打开VS,新建一个项目
5. 修改项目属性:
1. 导出一个必选的函数
pentry(int)
ODBG2_Pluginquery(int ollydbgversion, /*OD自身的版本号*/
ulong *features,/*保留*/
wchar_t pluginname[SHORTNAME],/*插件的名字,需要函
数内部自己填充*/
wchar_t pluginversion[SHORTNAME])/*插件的版本号,
需要函数内部自己填充,版本号没有要求*/
{
// 初始化插件的名字和版本号.
wcscpy_s(pluginname, SHORTNAME, L"第一个OD插件");
wcscpy_s(pluginversion, SHORTNAME, L"0.1");
return PLUGIN_VERSION;// 返回当前使用的API版本
}
pentry(int)
ODBG2_Pluginquery(int ollydbgversion, /*OD自身的版本号*/
ulong *features,/*保留*/
wchar_t pluginname[SHORTNAME],/*插件的名字,需要函
数内部自己填充*/
wchar_t pluginversion[SHORTNAME])/*插件的版本号,
需要函数内部自己填充,版本号没有要求*/
{
// 初始化插件的名字和版本号.
wcscpy_s(pluginname, SHORTNAME, L"第一个OD插件");
wcscpy_s(pluginversion, SHORTNAME, L"0.1");
return PLUGIN_VERSION;// 返回当前使用的API版本
}
2. 给OD添加菜单需要导出一个函数
/*!
* \brief ODBG2_Pluginmenu [OD插件可选导出函数]
* 点击窗口主菜单或点击右键以期望弹出菜单时,OllyDBG将调用此函数,并将
函数返回的数据添加到将要弹出的菜单中
* \param wchar_t * type 准备弹出菜单的窗口的名字,以PWM_xxx系列宏来表
示
* \return 返回需要添加的菜单结构体数组, 数组必须以一个全0的元素为结
尾.
* PWM_ATTACH ‐进程附加区
* PWM_BPHARD ‐ 硬件断点区
* PWM_BPMEM ‐ 内存断点区
* PWM_BPOINT ‐ INT3 断点区
* PWM_DISASM ‐ 反汇编窗口
* PWM_DUMP ‐ 所有的dump区(除了反汇编去和栈区)
* PWM_INFO ‐ 寄存器信息菜单
* PWM_LOG ‐ 日志窗口
* PWM_MAIN ‐ 主菜单
* PWM_MEMORY ‐ 内存窗口
* PWM_MODULES ‐ 模块窗口
* PWM_NAMELIST ‐ 标签列表窗口
* PWM_PATCHES ‐ 补丁列表窗口
* PWM_PROFILE ‐ Profile window
* PWM_REGISTERS ‐ 寄存器窗口
* PWM_SEARCH ‐ 搜索控件
* PWM_SOURCE ‐ 源代码窗口
* PWM_SRCLIST ‐ 源代码列表窗口
* PWM_STACK ‐ CPU栈信息面板
* PWM_THREADS ‐ 线程窗口
* PWM_TRACE ‐ Run跟踪窗口
* PWM_WATCH ‐ 监视窗口
* PWM_WINDOWS ‐ list of windows owned by the debugged
application
*/
pentry(t_menu *) ODBG2_Pluginmenu(wchar_t *type)
{
// 菜单数组必须以全0元素结尾
static t_menu menu[2] = { 0 };
menu[0].name = L"第一个插件的菜单";
menu[0].index = 100;
// Lambda函数:
// [] + () + {}
// [] : 捕获列表
// () : 参数列表
// {} : 函数体
// () 和 {} 之间 ‐> 数据类型 表示函数的返回值类型
// int MENUFUNC(struct t_table*,wchar_t*,ulong,int);
menu[0].menufunc =
[](struct t_table*, wchar_t*, ulong id, int model)‐>int {
if (model == MENU_VERIFY) {
return MENU_NORMAL;
}
switch (id)
{
case 100: {
MessageBox(0, L"菜单被点击", 0, 0);
}break;
case 101:
MessageBox(0, L"反汇编窗口菜单被点击", 0, 0);
break;
default:
break;
}
return MENU_ABSENT;
};
static t_menu menu2[2] = { 0 };
menu2[0].name = L"xxxx";
menu2[0].index = 101;
menu2[0].menufunc = menu[0].menufunc;
// 判断调用当前函数的时候, 弹出菜单的位置是否是主菜单
// 如果是才返回菜单, 否则就不返回了.
if (wcscmp(type, PWM_MAIN) == 0) {
return menu;
}
else if (wcscmp(type, PWM_DISASM) == 0) {
return menu2;
}
return NULL;
}
/*!
* \brief ODBG2_Pluginmenu [OD插件可选导出函数]
* 点击窗口主菜单或点击右键以期望弹出菜单时,OllyDBG将调用此函数,并将
函数返回的数据添加到将要弹出的菜单中
* \param wchar_t * type 准备弹出菜单的窗口的名字,以PWM_xxx系列宏来表
示
* \return 返回需要添加的菜单结构体数组, 数组必须以一个全0的元素为结
尾.
* PWM_ATTACH ‐进程附加区
* PWM_BPHARD ‐ 硬件断点区
* PWM_BPMEM ‐ 内存断点区
* PWM_BPOINT ‐ INT3 断点区
* PWM_DISASM ‐ 反汇编窗口
* PWM_DUMP ‐ 所有的dump区(除了反汇编去和栈区)
* PWM_INFO ‐ 寄存器信息菜单
* PWM_LOG ‐ 日志窗口
* PWM_MAIN ‐ 主菜单
* PWM_MEMORY ‐ 内存窗口
* PWM_MODULES ‐ 模块窗口
* PWM_NAMELIST ‐ 标签列表窗口
* PWM_PATCHES ‐ 补丁列表窗口
* PWM_PROFILE ‐ Profile window
* PWM_REGISTERS ‐ 寄存器窗口
* PWM_SEARCH ‐ 搜索控件
* PWM_SOURCE ‐ 源代码窗口
* PWM_SRCLIST ‐ 源代码列表窗口
* PWM_STACK ‐ CPU栈信息面板
* PWM_THREADS ‐ 线程窗口
* PWM_TRACE ‐ Run跟踪窗口
* PWM_WATCH ‐ 监视窗口
* PWM_WINDOWS ‐ list of windows owned by the debugged
application
*/
pentry(t_menu *) ODBG2_Pluginmenu(wchar_t *type)
{
// 菜单数组必须以全0元素结尾
static t_menu menu[2] = { 0 };
menu[0].name = L"第一个插件的菜单";
menu[0].index = 100;
// Lambda函数:
// [] + () + {}
// [] : 捕获列表
// () : 参数列表
// {} : 函数体
// () 和 {} 之间 ‐> 数据类型 表示函数的返回值类型
// int MENUFUNC(struct t_table*,wchar_t*,ulong,int);
menu[0].menufunc =
[](struct t_table*, wchar_t*, ulong id, int model)‐>int {
if (model == MENU_VERIFY) {
return MENU_NORMAL;
}
switch (id)
{
case 100: {
MessageBox(0, L"菜单被点击", 0, 0);
}break;
case 101:
MessageBox(0, L"反汇编窗口菜单被点击", 0, 0);
break;
default:
break;
}
return MENU_ABSENT;
};
static t_menu menu2[2] = { 0 };
menu2[0].name = L"xxxx";
menu2[0].index = 101;
menu2[0].menufunc = menu[0].menufunc;
// 判断调用当前函数的时候, 弹出菜单的位置是否是主菜单
// 如果是才返回菜单, 否则就不返回了.
if (wcscmp(type, PWM_MAIN) == 0) {
return menu;
}
else if (wcscmp(type, PWM_DISASM) == 0) {
return menu2;
}
return NULL;
}
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!
最后于 2018-10-27 11:45
被Jabez编辑
,原因: