第一章 初探OllyDbg1插件 官网http://www.ollydbg.de/给出了关于插件开发的信息。OllyDbg1.10的插件开发包在http://www.ollydbg.de/plug11.zip。该压缩包包含以下文件: │ Bookmark.c OllyDbg书签插件源码,该插件支持调试程序时设置10个书签 │ Cmdexec.c OllyDbg命令行插件,该插件支持输入命令进行调试 │ Cmdline.rtf 命令行插件的帮助文件 │ Command.c │ Ollydbg.def OllyDbg定义文件,某些编译器用之生成输入链接库ollydbg.lib │ Plugin.h 插件公共头文件 │ Plugins.hlp 插件编写说明 (Win8.1打不开hlp的解决方法http://www.microsoft.com/zh-cn/download/details.aspx?id=40899) │ ├─Bc55 Borland C++系列编译器工程 │ BOOKMARK.MAK │ CMDLINE.BPR │ CMDLINE.CPP │ CMDLINE.MAK │ OLLYDBG.LIB │ SAMPLE.BPR │ SAMPLE.CPP │ └─Vc50 Visual C++系列编译器工程,这也是本文所使用的开发环境 BOOKMARK.DSP BOOKMARK.DSW BOOKMARK.MAK CMDLINE.DSP CMDLINE.DSW CMDLINE.MAK OLLYDBG.LIB 一、基本原理 OllyDbgv1.10是OllyDbg1系列的最终版本,作者已停止开发,转而开发v2.0版本,新版本和1.xx版本是不兼容的,插件也是如此。对于1.xx版本,插件大体上通用,这几个版本的改动有: l t_reg和t_bpoint结构体扩展 l 新选项“总在最前”需要插件窗口特殊支持 l Browsefilename支持保存文件对话框 插件是提供附加功能的DLL文件,位于OllyDbg目录下。OllyDbg启动时会逐个加载所有可用的DLL文件,检查名为_ODBG_Plugindata和_ODBG_Plugininit的入口点(输出函数),如果存在并且插件版本号兼容,OllyDbg会注册插件并在插件子菜单增加相应项。插件可以在反汇编、转储、堆栈、内存、模块、线程、断点、监视、参考、界面窗口、运行跟踪窗口增加菜单项和监视全局/局部快捷键。插件可以是MDI窗口;可以在.udd文件中写入模块相关的自定义数据;可以访问和修改ollydbg.ini的数据结构以描述调试信息。插件使用多个回调函数和OllyDbg通信,可以调用170+个插件API函数。插件接口不是面向对象的。 插件API函数不是线程安全的,没有实现临界区,插件创建的新线程不能调用这些函数,否则可能导致OllyDbg和程序崩溃。 二、编译 请将编译器按如下设置以便插件和OllyDbg通信,plugin.h会检查这些设置: 通过名称输出所有导出函数,而非序数
l 如果使用C++编译器则需要禁用导出函数的名称修饰(使用extern “C”)
l 强制所有API函数和导出函数使用C格式调用_cdecl
l 强制所有结构体按字节对齐
l 默认字符类型为unsigned型
编译自定义插件会用到plugin.h ollydbg.lib,需要复制到工程目录中。现在以VS2010为例介绍如何编写无任何功能的插件。首先建立一个Windows动态链接库的空项目,在工程属性中,选C/C++ -> 命令行,右侧“其它选项”加入“/J”。之后向工程添加helloworld.cpp,内容如下:
#include
<windows.h>
#include
"lugin.h"
HINSTANCE
hinst=
NULL
;
BOOL
WINAPI
DllEntryPoint(
HINSTANCE
hi
,
DWORD
reason
,
LPVOID
reserved
)
{
//DLL
入口点
if
(
reason
==
DLL_PROCESS_ATTACH
)
hinst=
hi
;
return
1;
}
extc
int
_export
cdecl
ODBG_Plugininit
(
int
ollydbgversion
,
HWND
hw
,
ulong
*
features
)
{
MessageBox
(
NULL
,
"HelloWorld"
,
"HelloWorld"
,
MB_OK
);
return
0;
}
extc
int
_export
cdecl
ODBG_Plugindata
(
char
shortname
[32])
{
//
用于插件菜单中显示插件名
strcpy(
shortname
,
"HelloWorld"
);
return
PLUGIN_VERSION
;
}编译得到的dll放到ollydbg根目录下,启动ollydbg就可以看到弹出对话框,同时插件菜单栏多了一项“Hello Wolrd”。
使用dumpbin或depends工具查看ollydbg.exe输出表,可以看到700+个函数,这些就是插件API函数。为何exe会导出函数呢?早在《理论科普:如何让exe输出函数之输出函数自导自演》
http://www.0xaa55.com/forum.php?mod=viewthread&tid=777&extra=中我已介绍了这种情况,这里是一个应用实例。ollydbg这样使用是用于制作插件,将如设置断点、反编译等一些相对独立的模块,抽取出来,可供第三方调用。
调用OllyDbg-API:欲调用OllyDbg导出函数(例如FuncA),首先在源文件中包含Plugin.h,并在调用之前增加代码“#pragmacomment(lib,"ollydbg.lib")”,同时将插件开发包Vc50目录下的ollydbg.lib拷贝到工程目录中。此外OllyDbg作者写的Plugin.h不适用于VS系列编译器,由于ollydbg.exe实际导出符号为下划线版本(_FuncA),而plugin.h声明的是无下划线形式,因此直接编译会出现链接问题,而作者仅对ODBG系列函数作出调整而未对OllyDbg-API声明作出相应调整,因此所有用到的OllyDbg-API都需要进行手工调整,先找到Plugin.h中这样的代码段:
#define
ODBG_Plugindata
_ODBG_Plugindata
#define
ODBG_Plugininit
_ODBG_Plugininit
#define
ODBG_Pluginmainloop
_ODBG_Pluginmainloop
#define
ODBG_Pluginsaveudd
_ODBG_Pluginsaveudd
#define
ODBG_Pluginuddrecord
_ODBG_Pluginuddrecord
#define
ODBG_Pluginmenu
_ODBG_Pluginmenu
#define
ODBG_Pluginaction
_ODBG_Pluginaction
#define
ODBG_Pluginshortcut
_ODBG_Pluginshortcut
#define
ODBG_Pluginreset
_ODBG_Pluginreset
#define
ODBG_Pluginclose
_ODBG_Pluginclose
#define
ODBG_Plugindestroy
_ODBG_Plugindestroy
#define
ODBG_Paused
_ODBG_Paused
#define
ODBG_Pausedex
_ODBG_Pausedex
#define
ODBG_Plugincmd
_ODBG_Plugincmd
在其后加入自己的声明,如:
#define
Plugingetvalue
_Plugingetvalue
#define
Getstatus
_Getstatus
这样方可正常编译链接。
生成ollydbg.lib:ollydbg.lib可以由插件根目录存在ollydbg.def文件手动生成,这里会用到VS编译器自带工具lib.exe,命令如下:lib/MACHINE:X86 /DEFllydbg.def
调试:写插件本身具有难度,然而调试OllyDbg运行插件似乎就更难了。然而我却不以为然,将OllyDbg拷贝到生成dll的目录中(前提是该版本OllyDbg读取插件的目录为自身根目录),设置工程属性=>调试=>命令,将拷贝后的OllyDbg文件路径写入该处,调试即可在DLL源码中断下。
三、使用MFC开发OllyDbg1插件上面介绍的是使用MSVC的Windows DLL工程的情况,而这里介绍如何结合MFC进行插件开发。经我测试,VS2010及之后的MFC,由于内部使用的ATL和/J编译指令冲突,因此无法编译,而VC6版本可以很好地编译。下面是开发步骤,以test为例:
1. 新建名为test的MFC DLL工程
2. 在自动生成的StdAfx.h文件末尾加入 #inclue “Plugin.h” 同时将Plugin.h拷入工程目录
3. 在test.cpp中添加ODBG_***导出函数
4. 在调用OllyDbg导出函数之前,加入#pragma comment(lib,"ollydbg.lib")
四、插件生命周期 OllyDbg所规定的插件输出函数,其实正好反映了插件的生命周期,类似于窗口的生命周期,它与消息机制相关。下面通过实例得到插件生命周期:
#include
<windows.h>
#include
"lugin.h"
extc
int
_export
cdecl
ODBG_Plugindata
(
char
shortname
[32])
{
//
插件检测
strcpy(
shortname
,
"
菜单显示项
"
);
MessageBox
(
NULL
,
"ODBG_Plugindata"
,
""
,
MB_OK
);
return
PLUGIN_VERSION
;
}
extc
int
_export
cdecl
ODBG_Plugininit
(
int
ollydbgversion
,
HWND
hw
,
ulong
*
features
)
{
//
插件初始化
MessageBox
(
NULL
,
"ODBG_Plugininit"
,
""
,
MB_OK
);
return
0;
}
extc
int
_export
cdecl
ODBG_Pluginmenu
(
int
origin
,
char
data
[4096],
void
*
item
)
{
//
初始化菜单项
MessageBox
(
NULL
,
"ODBG_Pluginmenu"
,
""
,
MB_OK
);
return
0;
}
extc
int
_export
cdecl
ODBG_Pluginclose
(
void
)
{
//
用户关闭
OllyDbg
时触发
MessageBox
(
NULL
,
"ODBG_Pluginclose"
,
""
,
MB_OK
);
return
0;
}
extc
void
_export
cdecl
ODBG_Plugindestroy
(
void
)
{
//OllyDbg
退出时触发
MessageBox
(
NULL
,
"ODBG_Plugindestroy"
,
""
,
MB_OK
);
}
结果为: ODBG_Plugindata=> ODBG_Plugininit => ODBG_Pluginmenu => ODBG_Pluginclose => ODBG_Plugindestroy |
OllyDbg插件
最新推荐文章于 2023-05-31 17:23:45 发布