OllyDbg插件



第一章 初探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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值