元始天尊 发表于 2014-12-30 15:04:23

OllyDbg插件深入分析一

本帖最后由 元始天尊 于 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版本,插件大体上通用,这几个版本的改动有:
lt_reg和t_bpoint结构体扩展
l新选项“总在最前”需要插件窗口特殊支持
lBrowsefilename支持保存文件对话框
插件是提供附加功能的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格式调用_cdecll 强制所有结构体按字节对齐l 默认字符类型为unsigned型编译自定义插件会用到plugin.h ollydbg.lib,需要复制到工程目录中。
现在以VS2010为例介绍如何编写无任何功能的插件。首先建立一个Windows动态链接库的空项目,在工程属性中,选C/C++ -> 命令行,右侧“其它选项”加入“/J”。之后向工程添加helloworld.cpp,内容如下:
#include <windows.h>#include "Plugin.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) {//用于插件菜单中显示插件名       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 /DEF:ollydbg.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 "Plugin.h" extc int _export cdecl ODBG_Plugindata(char shortname) {//插件检测       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,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
页: [1]
查看完整版本: OllyDbg插件深入分析一