找回密码
 立即注册→加入我们

QQ登录

只需一步,快速开始

搜索
热搜: 下载 VB C 实现 编写
查看: 12054|回复: 1

OllyDbg插件深入分析一

[复制链接]
发表于 2014-12-30 15:04:23 | 显示全部楼层 |阅读模式

欢迎访问技术宅的结界,请注册或者登录吧。

您需要 登录 才可以下载或查看,没有账号?立即注册→加入我们

×
本帖最后由 元始天尊 于 2015-1-2 23:44 编辑

第一章 初探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 WINAPIDllEntryPoint(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
回复

使用道具 举报

 楼主| 发表于 2014-12-31 15:41:52 | 显示全部楼层
本帖最后由 元始天尊 于 2015-1-2 23:42 编辑

附录一 OllyDbg1输出函数 按字母排序:

   1    000054EFC _Addsorteddata
   2    10005A60C _Addtolist
   3    20007F284 _Analysecode
164    300031AD8 _Animate
   4    4000054AC _Assemble
180    500077D8C _Attachtoactiveprocess
   5    60005A474 _Broadcast
   6    700076224 _Browsefilename
   7    800054B20 _Calculatecrc
   8    900015E60 _Checkcondition
   9    A00008208 _Compress
  10    B00053154 _Createdumpwindow
  11    C0005B1F0 _Createlistwindow
181    D0009F260 _Createpatchwindow
126    E0008E720 _Createprofilewindow
165    F0008DD10 _Creatertracewindow
  12   1000054D98 _Createsorteddata
166   11000795C8 _Createthreadwindow
167   120007A2D8 _Createwatchwindow
168   1300098E28 _Createwinwindow
  13   140007D6B0 _Decodeaddress
127   150000BE78 _Decodeascii
  14   1600015C4C _Decodecharacter
  15   1700092E04 _Decodefullvarname
  16   180000C2C8 _Decodeknownargument
  17   1900064C38 _Decodename
  18   1A0005DFE0 _Decoderange
  19   1B0007E2A8 _Decoderelativeoffset
  20   1C000789E0 _Decodethreadname
128   1D0000C0A4 _Decodeunicode
  21   1E00008480 _Decompress
  22   1F000558D0 _Defaultbar
  23   2000019518 _Deletebreakpoints
169   2100008C08 _Deletehardwarebreakbyaddr
  24   22000089EC _Deletehardwarebreakpoint
  25   2300064FC8 _Deletenamerange
  26   2400055414 _Deletenonconfirmedsorteddata
129   250008AD78 _Deleteruntrace
  27   2600055224 _Deletesorteddata
  28   2700055308 _Deletesorteddatarange
130   2800079844 _Deletewatch
  29   290006395C _Demanglename
  30   2A 00054CD8 _Destroysorteddata
  31   2B00015F48 _Disasm
  32   2C0007E940 _Disassembleback
  33   2D0007EB0C _Disassembleforward
  34   2E0006498C _Discardquicknames
170   2F0004CF54 _Dumpbackup
  35   300005401C _Error
  36   3100097724 _Expression
  37   320007099C _Findallcommands
175   3300070BE8 _Findalldllcalls
131   34000710E4 _Findallsequences
  38   350005DF00 _Finddecode
  39   360005DF58 _Findfileoffset
  40   370005DE80 _Findfixup
118   380001ABCC _Findhittrace
  41   390006512C _Findimportbyname
  42   3A00064F04 _Findlabel
  43   3B00065074 _Findlabelbyname
  44   3C00061A48 _Findmemory
  45   3D0005DE18 _Findmodule
  46   3E000649C0 _Findname
  47   3F00064E5C _Findnextname
132   400001E510 _Findnextproc
119   410008BAB4 _Findnextruntraceip
133   420001E4AC _Findprevproc
120   430008BA24 _Findprevruntraceip
134   440001E3DC _Findprocbegin
135   450001E454 _Findprocend
  48   460006FE04 _Findreferences
  49   4700055510 _Findsorteddata
  50   48000555C8 _Findsorteddataindex
  51   4900055568 _Findsorteddatarange
  52   4A0007053C _Findstrings
136   4B0000B0A8 _Findsymbolicname
  53   4C00078978 _Findthread
137   4D00097700 _Findunknownfunction
  54   4E0003192C _Flash
176   4F0007D568 _Followcall
  55   500009763C _Get3dnow
138   5100041210 _Get3dnowxy
  56   5200091A44 _Getaddressfromline
  57   530009765C _Getasmfindmodel
139   540003E674 _Getasmfindmodelxy
  58   550009307C _Getbprelname
  59   5600019D78 _Getbreakpointtype
184   5700019D9C _Getbreakpointtypecount
  60   580002D564 _Getcputhreadid
  61   590001E5E0 _Getdisassemblerrange
  62   5A000975F4 _Getfloat
  63   5B000975CC _Getfloat10
140   5C0003D684 _Getfloat10xy
141   5D0003D7A8 _Getfloatxy
  64   5E000976CC _Gethexstring
142   5F000403D8 _Gethexstringxy
  65   60000975B0 _Getline
  66   61000918F0 _Getlinefromaddress
143   620003D234 _Getlinexy
  67   6300097588 _Getlong
144   640003D090 _Getlongxy
  68   650009761C _Getmmx
145   6600040FF4 _Getmmxxy
  69   6700019E20 _Getnextbreakpoint
146   6800008458 _Getoriginaldatasize
147   690001E558 _Getproclimits
177   6A0003D198 _Getregxy
  70   6B0007393C _Getresourcestring
121   6C0008BF8C _Getruntraceprofile
122   6D0008BB3C _Getruntraceregisters
  71   6E000557DC _Getsortedbyselection
  72   6F00091D00 _Getsourcefilelimits
  73   70000972A4 _Getstatus
148   7100055DB0 _Gettableselectionxy
  74   720009767C _Gettext
149   730003EAFC _Gettextxy
150   74000799A0 _Getwatch
  75   7500034A14 _Go
  76   760006207C _Guardmemory
171   7700008F54 _Hardbreakpoints
  77   78000612E4 _Havecopyofmemory
  78   7900031768 _Infoline
151   7A00034494 _Injectcode
  79   7B00063EFC _Insertname
152   7C000798D0 _Insertwatch
153   7D0007F02C _Isfilling
178   7E0007EFE4 _Isprefix
  80   7F00047224 _Isretaddr
154   800007ECD8 _Issuspicious
  81   8100054800 _IstextA
  82   8200054840 _IstextW
186   8300060914 _Listmemory
  83   84000976A4 _Manualbreakpoint
  84   85000976F4 _Mergequicknames
  85   8600031630 _Message
123   870001AC34 _Modifyhittrace
  86   88000541CC _Newtablewindow
155   890007731C _OpenEXEfile
  87   8A00055ECC _Painttable
  88   8B000972AC _Plugingetvalue
  89   8C00097154 _Pluginreadintfromini
  90   8D000971E0 _Pluginreadstringfromini
  91   8E00096D4C _Pluginsaverecord
  92   8F00097004 _Pluginwriteinttoini
  93   90000970B4 _Pluginwritestringtoini
  94   910007E820 _Print3dnow
  95   920007E5CC _Printfloat10
  96   930007E450 _Printfloat4
  97   940007E510 _Printfloat8
156   950007E88C _Printsse
  98   9600031820 _Progress
  99   9700064304 _Quickinsertname
100   980005470C _Quicktablewindow
157   9900061684 _Readcommand
101   9A0006130C _Readmemory
102   9B0001E5CC _Redrawdisassembler
103   9C0005413C _Registerotclass
104   9D00096F2C _Registerpluginclass
158   9E00078854 _Restoreallthreads
159   9F00078788 _Runsinglethread
124   A00008B9F8 _Runtracesize
125   A10008C188 _Scrollruntracewindow
105   A20005A2D0 _Selectandscroll
172   A30002DF84 _Sendshortcut
106   A400097754 _Setbreakpoint
185   A500019560 _Setbreakpointext
107   A60002D618 _Setcpu
160   A70002DEA4 _Setdisasm
173   A800046E58 _Setdumptype
108   A900008690 _Sethardwarebreakpoint
109   AA000192D8 _Setmembreakpoint
174   AB0008C040 _Settracecondition
182   AC0008C110 _Settracecount
183   AD0008C13C _Settracepauseoncommands
110   AE00095554 _Showsourcefromaddress
111   AF00055630 _Sortsorteddata
161   B00008B86C _Startruntrace
162   B100054884 _Stringtotext
112   B200034290 _Suspendprocess
113   B30005835C _Tablefunction
179   B400019F1C _Tempbreakpoint
114   B500096FE4 _Unregisterpluginclass
115   B60005A5EC _Updatelist
116   B700071594 _Walkreference
163   B80007160C _Walkreferenceex
117   B900061728 _Writememory
187   BA00001059 __GetExceptDLLinfo
188   BB000B0128 ___CPPdebugHook
回复 赞! 靠!

使用道具 举报

本版积分规则

QQ|Archiver|小黑屋|技术宅的结界 ( 滇ICP备16008837号 )|网站地图

GMT+8, 2024-11-23 16:13 , Processed in 0.052141 second(s), 24 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表