首页
社区
课程
招聘
[分享]给Ollydbg写了个管理所有插件的右键菜单的插件 vOllyMenuMgr
发表于: 2013-7-27 02:41 2501

[分享]给Ollydbg写了个管理所有插件的右键菜单的插件 vOllyMenuMgr

2013-7-27 02:41
2501
Ollydbg插件菜单管理插件 vOllyMenuMgr 1.0 by cexer

1.插件说明:
Ollydbg 插件装多了之后,右键菜单变得越来越长,要在其中寻找某个功能越来越不方便,其实其中有很多根本在右键中不会使用的功能,所以写了这个插件,只启用那些需要的菜单。


2.使用方法:
2.1 文件安装
将以下三个文件,复制到 Ollydbg 的 plugin 目录之后重启 Ollydbg:
    vOllyMenuMgr.dll    插件核心程序
    vOllyMenuMgr.xml    插件配置文件
    vOllyMenuMgr_readme.txt     插件的帮助文件,即本文件   

2.2 菜单说明
安装成功之后,主菜单会出现 vOllyMenuMgr 菜单,其中子菜单功能如下:
    Settings    打开配置界面。
    Reload      手动修改配置文件之后,需要调用这个重新载入 vOllyMenuMgr.xml。
    Console     打开或关闭控制台窗口,方便观察菜单调用情况。
    Help        用默认文本编辑器打开本帮助文件。
    About       显示本插件关于窗口。

3.配置方法
可以在菜单中选择 vOllyMenuMgr.dll->Settings 进行配置,也可手动配置,方法如下:
在 vOllyMenuMgr.xml 中配置为启用的插件菜单才会弹出,配置格式:
在 "vOllyMenuMgr/MenuConfig" 结点/修改:
    <Plugin name="插件名称">
        <菜单类型1>启用标志</菜单类型1>
        <菜单类型2>启用标志</菜单类型2>
        <菜单类型3>启用标志</菜单类型3>     
    </Plugin>

3.1 插件名称
插件名称即 plugins 主菜单下显示的名称(去掉前面的序号)。

3.2 启用标志
启用标记使用0或1
    1 启用
    0 禁用
未在配置文件中配置的插件默认为禁用。

3.3 菜单类型
菜单类型为 Ollydbg 定义的菜单类型
官方文档包含的,调试中确认会调用的菜单:
名称 类型ID 类型说明
PM_MAIN 0 主菜单栏下的菜单
PM_DUMP 10 任意Dump窗口菜单
PM_MODULES 11 模块窗口菜单
PM_MEMORY 12 内存窗口菜单
PM_THREADS 13 线程窗口菜单
PM_BREAKPOINTS 14 断点窗口菜单
PM_REFERENCES 15 参考窗口菜单
PM_RTRACE 16 运行跟踪窗口菜单
PM_WATCHES 17 监视窗口菜单
PM_WINDOWS 18 窗口列表菜单
PM_DISASM 31 反汇编窗口右键菜单
PM_CPUDUMP 32 CPU Dump窗口菜单
PM_CPUSTACK 33 CPU栈右键菜单


未在官方文档包含的,调试中发现的会调用的菜单:
名称 类型ID 类型说明
PM_HANDLES 21 句柄窗口菜单
PM_PATCHES 20 Ollydbg自身修改的代码菜单


调试中发现比较意外,不会调用菜单的窗口:
名称 类型ID 类型说明
- - 日志窗口
PM_CPUREGS 34 寄存器窗口


3.4 注意:
未在配置文件中配置的插件默认为禁用。

4 实现原理
第一步 先定位菜单函数的调用位置
第二步 将该位置的代码Hook,调用自定义函数
第三步 在自定义函数中根据配置文件禁用、启用菜单

4.1 定位菜单函数的调用位置
用VC自己随便写个插件DLL,其中实现 ODBG_Plugininit 函数,在这个函数开头加个断点,然后将插件放到 Ollydbg 的 plugin 目录,使用 Ollydbg 作为宿主程序,在VC中启动调试。函数断下之后,VC切到反汇编模式,单步执行完本函数,可以回到 Ollydbg 中调用插件ODBG_Plugininit 的地方。

经过反复测试,发现只有1个地方调用 ODBG_Plugininit:
004969BA |. 890424 |mov dword ptr [esp], eax
004969BD |. 54 |push esp
004969BE |. 8B15 7C3B4D00 |mov edx, dword ptr [4D3B7C]
004969C4 |. 52 |push edx
004969C5 |. 6A 6E |push 6E
004969C7 |. FFD7 |call edi ; ODBG_Plugininit


在 Ollydbg 中打开另一个 Ollydbg 进行调试,定位到这个函数中,一路读下去可以理出:
插件信息数组,保存在 0x004F0AB4
插件总数,保存在 0x004F55B4
插件信息的结构:
#pragma pack(push,1)
struct vOllyPlugin
{
BYTE unkownbytes0[4];
char filename[0x104]; // @ 0x4
char pluginname[0x20]; // @ 0x108
BYTE unkownbytes1[0x108]; // @ 0x128

TODBG_Pluginmainloop fmainloop; // @ 0x230
TODBG_Pluginmenu fmenu; // @ 0x234
TODBG_Pluginaction factoin; // @ 0x238
TODBG_Pluginshortcut fshortcut; // @ 0x23C
TODBG_Pluginsaveudd fsaveudd; // @ 0x240
TODBG_Pluginuddrecord fuddrecord; // @ 0x244
TODBG_Pluginreset freset; // @ 0x248
TODBG_Paused fpaused; // @ 0x24C
TODBG_Pausedex fpausedex; // @ 0x250
TODBG_Plugincmd fcmd; // @ 0x254
};
#pragma pack(pop)


其中的函数类型,根据插件SDK文档确定:
typedef int (cdecl *TODBG_Plugininit)( int ollydbgversion, HWND hw, ulong *features );
typedef int (cdecl *TODBG_Plugindata)( char *shortname );
typedef void (cdecl *TODBG_Pluginaction)( int origin, int action, void *item );
typedef void (cdecl *TODBG_Pluginmainloop)( DEBUG_EVENT *debugevent );
typedef int (cdecl *TODBG_Pluginshortcut)( int origin, int ctrl, int alt, int shift, int key, void *item );
typedef void (cdecl *TODBG_Pluginsaveudd)( t_module *pmod, int ismainmodule );
typedef int (cdecl *TODBG_Pluginuddrecord)( t_module *pmod, int ismainmodule, ulong tag, ulong size, void *data );
typedef void (cdecl *TODBG_Pluginreset)();
typedef int (cdecl *TODBG_Paused)( int reason, t_reg *reg );
typedef int (cdecl *TODBG_Pausedex)( int reason, int extdata, t_reg *reg, DEBUG_EVENT *debugevent );
typedef int (cdecl *TODBG_Plugincmd)( int reason, t_reg *reg, char *cmd );
typedef int (cdecl *TODBG_Pluginmenu)( int origin, char data[4096], void *item );


根据这些信息,可以定位到任意插件的 ODBG_Pluginmenu 的地址,随便选择一个,在这个地址上另硬件访问断点,可以定位到所有调用菜单函数的地方。经过反复测试,发现只有两个地方调用菜单函数:
00496A19 |. FF93 34020000 |call dword ptr [ebx+234]


00496553 |. FF96 34020000 |call dword ptr [esi+234]


其中 00496A19 位于刚才发现的插件加载函数中,调用参数中的 origin 总是 PM_MAIN,可以确定这儿是在将插件菜单添加到主菜单(并且后面经过确认,主菜单只在此调用一次),因此要 Hook 的位置是 00496553,这里的 esi 包含了当前插件的信息首地址(对应 vOllydbgPlugin 结构)。

4.2 Hook 菜单调用函数
首先按插件SDK的要求,写一个 Hook 函数:
int cdecl replacement_of_0x96553( int origin, char data[4096], void *item )
{
// 取得插件信息结构地址
vOllyPlugin* plugin = NULL;
__asm { MOV plugin, esi }

// 调用自定义函数
return vOllyMenuMgr_plugin_menu( plugin, origin, data, item );
}

然后在 ODBG_Plugininit 中 Hook 00496553:
bool hook_0x96553()
{
base_address = (unsigned char*)GetModuleHandleA( NULL );
plugin_arary = (vOllyPlugin*)( base_address + 0xF0AB4 );
plugin_count = (int*)( base_address + 0xF55B4 );
hook_address = m_base_address + 0x96553;
hook_succeeded = false;

unsigned char* hook = (unsigned char*)&replacement_of_0x96553;
const char* code_old = "\xFF\x96\x34\x02\x00\x00";

DWORD protect_old = 0;
VirtualProtect( hook_address, 6, PAGE_EXECUTE_READWRITE, &protect_old );
if( memcmp( hook_address, code_old, 6 ) == 0 )
{
unsigned char* call = hook_address;
*call = 0xE8; call += 1;
*( (ptrdiff_t*)call ) = hook - call - 4; call += 4;
*call = 0x90; call += 1;

hook_succeeded = true;
}
VirtualProtect( hook_address, 6, protect_old, &protect_old );

return hook_succeeded;
}

extc int _export cdecl ODBG_Plugininit( int ollydbgversion, HWND hw, ulong * features )
{
if( hook_0x96553() )
// ...
else
// ...
}


还得在 ODBG_Plugindestroy 中完成 Unhook:
bool unhook_0x96553()
{
// 这里最好是判断字节比较安全,以防该处代码,又被其它程序修改了。
if( hook_succeeded )
{
unsigned char* code = (unsigned char*)hook_address;
const char* old_code = "\xFF\x96\x34\x02\x00\x00";

DWORD protect_old = 0;
VirtualProtect( code, 6, PAGE_EXECUTE_READWRITE, &protect_old );
vmemcpy( code, old_code, 6 );
VirtualProtect( code, 6, protect_old, &protect_old );

hook_succeeded = false;
}
}

extc void _export cdecl ODBG_Plugindestroy()
{
if( unhook_0x96553() )
// ...
else
// ...
}


5.3 在自宝岛函数中根据配置文件进行菜单调用
然后在 vOllyMenuMgr_plugin_menu 中,就可以根据配置,做对菜单进行选择性的调用了。

4 BUG
此程序未经过长期测试,使用中有问题请自行研究,或者:
发送邮件到cexer@qq.com,或者看雪(www.pediy.com)论坛联系 andy00

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

上传的附件:
收藏
免费 0
支持
分享
最新回复 (12)
雪    币: 5153
活跃值: (3387)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
广告位出租~~~~~
2013-7-27 03:04
0
雪    币: 81
活跃值: (40)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
3
这个好,沙发位出租
2013-7-27 03:56
0
雪    币: 1844
活跃值: (35)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
4
顶一下,看看效果
2013-7-27 09:06
0
雪    币: 67
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
有新意的插件  还真需要
2013-7-27 09:20
0
雪    币: 90
活跃值: (91)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
弱弱地问下,6楼可以出租吗?
2013-7-27 09:59
0
雪    币: 341
活跃值: (85)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
7
广告位出租。
2013-7-27 10:03
0
雪    币: 1344
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
mms
8
8楼先占着,看情况低价出售
2013-7-27 10:32
0
雪    币: 1042
活跃值: (495)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
我一般是加常用的插件,其他的一概扔掉。
2013-7-27 11:48
0
雪    币: 114
活跃值: (180)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
不错,谢谢楼主分享。
2013-7-27 12:03
0
雪    币: 3529
活跃值: (1857)
能力值: ( LV6,RANK:93 )
在线值:
发帖
回帖
粉丝
11
广告一个:holyshit toolbar可以直接调用某个插件的menu点击功能,你只需用鼠标左键点击,不再需要右键菜单弹出并且找对应menu了。
2013-7-27 12:03
0
雪    币: 370
活跃值: (15)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
12
加精前顶一下
2013-7-27 12:50
0
雪    币: 707
活跃值: (1301)
能力值: ( LV9,RANK:190 )
在线值:
发帖
回帖
粉丝
13
射精前顶一下 !(我不是复制楼上的回复)
2013-7-27 17:05
0
游客
登录 | 注册 方可回帖
返回
//