OllyDbg翻译一
这是从ollydbg官网http://www.ollydbg.de/翻译过来的:ollydbg是一个windows下的32位汇编级分析调试器,在没有源码的情况下对于二进制代码的分析能力显得尤为重要。ollydbg是一个共享软件,但是可以自由的下载使用,它的特点如下:
直观的用户界面没有隐藏命令
代码分析 - 跟踪寄存器,识别函数过程,跳转,api调用,开关语句,表,常量和字符串
直接加载并调试dll
目标文件的扫描 - 从目标文件和库中定位函数
允许用户自定义标签注释和功能描述
可以分析Borland格式的调试信息
保存会话中的信息,并更新写回到可执行文件
开放式体系 - 支持第三方插件
无需安装 - 不会再注册表和系统中产生垃圾
调试多线程程序
附加到进程
可配置的反汇编器,支持masm和ideal格式
支持MMX,3DNow!,SSE数据类型和指令,支持Athlon扩展指令
全面支持UNICODE
动态识别ASCII和UNICODE字符串 - 支持Delphi格式的
识别复杂代码的结构,例如call,jump到某个过程
识别超过1900个api和400个c函数调用
由外部帮助文件可获取api函数的上下文帮助
设置条件断点,条件记录断点,内存断点和硬件断点
跟踪程序执行,记录已知函数参数
显示修正
动态跟踪栈帧
支持搜索模糊命令和掩码二进制序列
搜索全部分配的内存
寻找常量和地段标记
查看和修改内存,设置断点,暂停程序执行
将命令汇编成最短二进制形式
从软盘运行
Plugin Development Kit 1.10
ollydbg插件开发
编译
要编译你自己的插件,需要c或c++编译器(有运行库和链接器),插件接口(plugin.h文件)最低兼容以下编译器:
Borland C++ 5.5
Borland C++ Builder 5
Microsoft Visual C++ 5.0
插件开发工具包包括2个全功能插件的源代码:
书签插件,让你为被调试程序设置多达10个书签;命令行插件,实现了命令行接口 。插件都是未文档化的你可以作为模板开发自己的插件,他们都是免费的。
需要如下设置编译器才能使插件和ollydbg正常通信,除了上述那些编译器,plugin.h还按如下规则检查:
通过名称导出函数而非序号
如果你使用c++编译器需要在所有回调函数中禁用名称粉碎(声明为extern "C")
强制使用C格式给api或者回调函数传递参数(声明为cdecl)
对于plugin.h中声明的结构体,强制按1字节对齐
设置默认字符类型为UNSIGNED
记得所有从ollydbg获取的指针都可能是空,忽略这一点是常见错误
使用静态运行库直接链接到你的插件,否则不同版本运行时dll会使ollydbg不稳定。不要把你的插件不必要滴分为若干个dll,如果你需要数据文件且不想让用户修改,试着将这些数据作为资源直接写入你的插件。为了让ollydbg连接你的插件,需要链接ollydbg.lib,一些编译器,如Borland,包含了implib工具可以扫描可执行文件(ollydbg.exe),并产生一个特殊的库记录所有导出函数,另一些编译器例如(vc)可以从def文件(ollydbg.def)生成导入库。类似的产品请阅读他们的文档。
请不要浪费资源,不要输出未使用的回调函数,这样可以是的你的程序更快,ollydbg当前的版本支持多达32个插件。
用vc5从命令行编译插件例子:
1.将bookmar.c,cmdexec.c,command.c,plugin.h,vc50\bookmar.mak,vc50\cmdline.mak,vc50\ollydbg.lib复制到相同目录
2.编辑mak文件
INCLUDE=c:\vc\include
LIBPATH=c:\vc\lib
这样他们就可以指向你的头文件和库文件目录了
3.进入c:\vc\bin,执行
c:\vc\bin\nmake -f bookmark.mak
c:\vc\bin\nmake -f cmdline.mak
4.使用vs编译插件
编译bookmark.dll
1.将bookmark.c, plugin.h, vc50\bookmark.dsp, vc50\bookmark.dsw vc50\ollydbg.lib 复制到同一目录
2.使用vs打开bookmark工程,编译
教程1:运行时跟踪
运行时跟踪技术是在ollydbg1.04首次引入的,这种调试技术基本都很简单。代码是一步步执行的,调试器使用环形缓冲区处理每个命令,寄存器和标志位。当发生异常时可以多次回退到上个命令,分析出错条件。
ollydbg1.06显著提高了运行跟踪的可能性,运行跟踪会系那是修改的寄存器,保留重要的信息和已知函数操作。使用此技术我们可以设置条件暂停运行跟踪,分析跟踪代码,在磁盘里记录跟踪日志克服内存限制,或者比较2个运行实例,调试自修改程序,寻找执行了最后一次的指令,等等
无论如何这个过程都很慢,在500Mhz的处理器上,ollydbg每秒最多可以跟踪2500到5000条指令,要加速跟踪,可以标记代码中一次执行的准线性块
为了让你熟悉跟踪过程我们试着调试一个简单的命令行程序
#include <stdio.h>
void f1(void) { printf("a"); };
void f2(void) { printf("b"); };
void f3(void) { printf("c"); };
void (*f)() = { f1,f2,f3 };
void main(void) {
int i,j,k;
for (i=0; i<100; i++) {
for (j=0; j<1000000; j++) ;// Long code k=i/33;
if (k>3) continue;
f(); // Here error (when i==99)!
};printf("\n");
};
函数f1 f2 f3打印字母a b c,主程序调用每个函数33次,然后打印出新行和结束符,至少理论上是这样(你可能已经看出来哪里错了对吗?PS没看出来的打屁屁)好,我们学一下如何使用运行跟踪产生相同的错误结果。打开编译的程序,几秒后他崩溃了。
http://www.ollydbg.de/Rtr_exc.gif
不,肯定哪里错了,ollydbg是你的实时调试器,选择调试但是反汇编窗口是空的,地址0062001指向空,你一点也不知道哪个命令跳转到这里,我们试着从头开始,Ctrl+F2,然后Ctrl+F11,等待几分钟,命令行仍然是空,可能一些代码花费了太长时间执行?F12暂停跟踪。在可执行模块里选择查看跟踪文件。
http://www.ollydbg.de/Rtr_prof.gif
00401191地址处的一系列命令执行了24000次以上,转到该地址
http://www.ollydbg.de/Rtr_dis1.gif
一个3命令循环执行了1000000次,每秒5000个命令,ollydbg需要10分钟跟踪这个循环。注意,命令序列是准线性的,且没有跳到外面,在弹出的菜单选择“运行跟踪|跳过选择当追踪” 第四列的红线表示在跟踪时排除的命令,当ollydbg遇到排除序列,它会在该块之后设置临时断点,当然,任何返回或者跳转到外面都会使跟踪无效,因此ollydbg会检查这段代码并且要求你确认。继续跟踪,这次很快,20s,ollydbg就报告错误
http://www.ollydbg.de/Rtr_err1.gif
确认了错误以后,打开跟踪窗口,
http://www.ollydbg.de/Rtr_rtra.gif我们现在看到跳转到006210061的是004011AF处的指令CALL EAX,非法地址在调用前已经计算出,双击这一行以便在反汇编器中查看。寄存器和信息都是灰色的,说明他们都不是实际值,
http://www.ollydbg.de/Rtr_dis2.gif
0040A128的地址指向一个包括3个函数指针f1 f2 f3的数组,当这个命令执行最后一次,eax里面是3,已经超出数组边界,前2个命令应该执行边界检查,但是条件是非法的:当eax>3时跳出正常的条件应该是>= 双击错误行,更正条件
http://www.ollydbg.de/Rtr_asm.gif
在你输入了新的指令后,指令变红,表明指令经过修改,再次选中在弹出菜单选择“复制到可执行文件”,这样你的修改就写入文件了
http://www.ollydbg.de/Rtr_file.gif
你所需要的是保存修改的exe,这时exe运行正常,很简单对吗
教程2:加载dll
ollydbg可以调试单独的dll,windows不能直接运行dll,因此ollydbg用一个小程序loaddll.exe打开他们。如果你调试dll,ollydbg会自动解压loaddll.exe并链接库作为参数运行。
有了loaddll,你可以调用调试库输出的函数,我会用MessageBox和wsprintf解释这一用法
例一 MessageBox
http://www.ollydbg.de/Warning.gif
1.加载dll 我们当然选是,ollydbg启动Loaddll,加载库然后暂停在主窗口循环处,这个地址标记为Firstbp,然后ollydbg分析dll显示他的代码
注意windows将dll加载到内存后会自动执行dll启动代码
2.从主菜单里选择“Debug|Call DLL export”,显示的对话框是非模态的,因此你仍然可以使用ollydbg其他功能。你可以打开代码和数据,设置断点,修改内存等。
3.选择你想调用的函数, MessageBox这个名字是通用的,事实上有MessageBoxA和MessageBoxW之分,我们分析第二个。我们选好以后分析器判断出函数以ret 10结束
4.设置堆栈参数数量。在这里不是必需的,因为ollydbg已经知道参数数量了
5.填写参数列表。这个对话框支持多达10个栈参数,参数是任何不适用寄存器的合法表达式。除此之外对话框有2个伪变量,loaddll.exe创建的父窗口句柄Hwnd和loaddll的实例句柄Hinst.为了方便当你第一次使用call export,ollydbg将他们加入历史列表
6.设置寄存器变量。寄存器变量在输出函数中很少使用。
7.选项设置。调用隐藏意味着当函数执行时对话框会隐藏。当函数调用结束,ollydbg会再次打开Call export,调用暂停指的是调试程序执行以后会被暂停运行。如果没什么错误的话,对话框会是这样:
http://www.ollydbg.de/Callexp1.gif
8.通过按下call调用函数。ollydbg自动备份所有转储,验证和计算参数和寄存器,从屏幕移除对话框,然后调用MessageBoxW,会出现如下对话框:
http://www.ollydbg.de/Msgbox.gif
好了,按ok,MessageBoxW会返回,Call export报告成功,注意返回的eax是1,正好是IDOK的数字值,很简单,不是吗?
细节与资源
loaddll.exe是一个压缩的汇编写的win32程序。看看他的源码:
This is the full code of loaddll.exe. It can be compiled using Borland's TASM32 with following commands:
tasm32 -mx -zi -m5 loaddll.asm,,loaddll.lst
tlink32 -v- -c -S:40000 -B:400000 -Tpe -aa -m loaddll,,,import32.lib
brc32 loaddll.rc -feloaddll.exe
LOADDLL.ASM:
P586 ; 32-bit instructions used!
MODEL FLAT,PASCAL
IDEAL ; I really like it!
LOCALS
PUBLICDLL WndProc,Firstbp,Prepatch,CallDLL,Finished;
PUBLICDLL Patcharea,Endpatch
PUBLICDLL Arg1,Arg2,Arg3,Arg4,Arg5,Arg6,Arg7,Arg8,Arg9,Arg10
SEGMENT _DATA1 PARA PUBLIC USE32 'DATA'
; Text below is a keyphrase used by OllyDbg to verify that LoadDll
; is correct. Loads at fixed address 00420000. Never change! Note
; how coward I am: you cannot replace copyright, otherwise this code
; will not work!
DB "DLL Loader (C) 2004 Oleh Yuschuk"
; Link area. Never change the meaning or order of next 32 dwords!
ERRMSG DD 0 ; Pointer to error
HINST DD 0 ; Process instance
HWND DD 0 ; Handle of main window
DLLBASE DD 0 ; Base address of loaded DLL or NULL
DD OFFSET Firstbp ; Address of first breakpoint
DD OFFSET Prepatch ; Address of patch area before call
DD OFFSET Arg1 ; Base of 10 arguments x 1024 bytes
DD OFFSET Finished ; Address of breakpoint after call
DUMMY DD 4 DUP(0) ; Reserved for the future
PROCADR DD 0 ; Address of procedure, starts execution
REGEAX DD 0 ; Register arguments
REGECX DD 0
REGEDX DD 0
REGEBX DD 0
REGESI DD 0
REGEDI DD 0
NARG DD 0 ; Number of arguments to push on stack
ARGLIST DD 10 DUP(0) ; DLL argument list
ESPDIFF DD 0 ; Difference in ESP caused by code
DD 0 ; Reserved for the future
WCLASS = THIS DWORD ; Hand-made WNDCLASS structure
DD 0000002Bh ; CS_HREDRAW|VREDRAW|DBLCLKS|OWNDC
DD WndProc ; Window procedure
DD 0 ; Class extra bytes
DD 0 ; Window extra bytes
WCINST DD 0 ; Instance
WCICON DD 0 ; Icon
HCURS DD 0 ; Cursor
HBGND DD 0 ; Background brush
DD 0 ; No menu
DD CLSNAME ; Class name
MSG = THIS DWORD ; Hand-made MSG structure
DD 0 ; Handle of window
MSGID DD 0 ; Message ID
DD 0 ; wParam
DD 0 ; lParam
DD 0 ; Timestamp
DD 0 ; X coordinate
DD 0 ; Y coordinate
PSTRUCT = THIS DWORD ; Hand-made PAINTSTRUCT structure
DD 0 ; HDC
DD 0 ; fErase
DD 0 ; rcPaint.left
DD 0 ; rcPaint.top
DD 0 ; rcPaint.right
DD 0 ; rcPaint.bottom
DD 0 ; fRestore
DD 0 ; fIncUpdate
DB 32 DUP(0) ; rgbReserved
ORIGESP DD 0 ; Original ESP before call
ORIGEBP DD 0 ; Original EBP before call
EXPESP DD 0 ; Expected ESP after call (C)
WNDNAME DB "OllyDbg DLL Loader",0
CLSNAME DB "LoadDLLClass",0
ICONAME DB "MAINICON",0 ; Green smashed bug - igitt!
E_NONAM DB "Missing DLL name",0 ; Error notifications to OllyDbg
E_NODLL DB "Unable to load DLL",0
E_NPARM DB "Too many parameters",0
ALIGN 16
Arg1 DB 1024 DUP (?) ; Area for 10 memory arguments, 1 k each
Arg2 DB 1024 DUP (?)
Arg3 DB 1024 DUP (?)
Arg4 DB 1024 DUP (?)
Arg5 DB 1024 DUP (?)
Arg6 DB 1024 DUP (?)
Arg7 DB 1024 DUP (?)
Arg8 DB 1024 DUP (?)
Arg9 DB 1024 DUP (?)
Arg10 DB 1024 DUP (?)
ENDS _DATA1
SEGMENT _TEXT1 PARA PUBLIC USE32 'CODE'
EXTRN GetModuleHandleA: PROC
EXTRN GetCommandLineA: PROC
EXTRN LoadIconA: PROC
EXTRN LoadCursorA: PROC
EXTRN GetStockObject: PROC
EXTRN RegisterClassA: PROC
EXTRN CreateWindowExA: PROC
EXTRN DestroyWindow: PROC
EXTRN PostQuitMessage: PROC
EXTRN ShowWindow: PROC
EXTRN Sleep: PROC
EXTRN BeginPaint: PROC
EXTRN EndPaint: PROC
EXTRN DefWindowProcA: PROC
EXTRN LoadLibraryA: PROC
EXTRN PeekMessageA: PROC
EXTRN TranslateMessage: PROC
EXTRN DispatchMessageA: PROC
EXTRN ExitProcess: PROC
; Window procedure of main LoadDLL window.
PROC WndProc
ARG LP:DWORD,WP:DWORD,MS:DWORD,HW:DWORD
PUSH EDX
PUSH EDI
PUSH ESI
MOV EAX,
CMP EAX,0001h ; WM_CREATE
JE RET0
CMP EAX,0002h ; WM_DESTROY
JNE @@080
PUSH 0
CALL PostQuitMessage
JMP RET0
@@080: CMP EAX,000Fh ; WM_PAINT
JNE @@100
PUSH OFFSET PSTRUCT
PUSH
CALL BeginPaint
PUSH OFFSET PSTRUCT
PUSH
CALL EndPaint
JMP RET0
@@100: CMP EAX,0010h ; WM_CLOSE
JNE @@200
PUSH
CALL DestroyWindow
JMP RET0
@@200: ; None of listed above, pass to DefWindowProc().
PUSH
PUSH
PUSH
PUSH
CALL DefWindowProcA
JMP RETA
RET0: XOR EAX,EAX
JMP SHORT RETA
RET1: MOV EAX,1
RETA: POP ESI
POP EDI
POP EDX
RET
ENDP WndProc
START: MOV EBP,ESP ; Here execution begins
PUSH 0
CALL GetModuleHandleA
MOV ,EAX
MOV ,EAX
CALL GetCommandLineA ; Path to LOADDLL is taken into quotes
MOV ESI,EAX
INC ESI ; Skip first quote
@@10: MOV AL, ; Skip path to LOADDLL.EXE
INC ESI
OR AL,AL
JNE @@12
MOV ,OFFSET E_NONAM
JMP ERROR
@@12: CMP AL,'"'
JNE @@10
@@20: MOV AL, ; Skip spaces
CMP AL,' '
JNE @@30
INC ESI
JMP SHORT @@20
@@30: PUSH ESI
CALL LoadLibraryA ; Load DLL
OR EAX,EAX
JNE @@32
MOV ,OFFSET E_NODLL
JMP ERROR
@@32: MOV ,EAX
PUSH OFFSET ICONAME
PUSH
CALL LoadIconA
MOV ,EAX
PUSH 7F88h ; IDC_NO
PUSH 0 ; External resource
CALL LoadCursorA
MOV ,EAX
PUSH 0 ; WHITE_BRUSH
CALL GetStockObject
MOV ,EAX
PUSH OFFSET WCLASS
CALL RegisterClassA
PUSH 0 ; Parameters: none
PUSH ; Instance
PUSH 0 ; Menu: none
PUSH 0 ; Parent window: none
PUSH 100 ; Width
PUSH 200 ; Height
PUSH 80000000h ; CW_USEDEFAULT
PUSH 80000000h ; CW_USEDEFAULT
PUSH 10CF0000h ; WS_OVERLAPPEDWINDOW|WS_VISIBLE
PUSH OFFSET WNDNAME ; Window name
PUSH OFFSET CLSNAME ; Class name
PUSH 0 ; Extended style: none
CALL CreateWindowExA
MOV ,EAX ; Save handle
PUSH 9 ; SW_RESTORE
PUSH EAX
CALL ShowWindow
Firstbp: NOP ; First breakpoint is set here
WINLOOP: CMP ,0; Request to call some function?
JE NOCALL
MOV ,ESP
MOV ,ESP
PUSH 0 ; Security buffer (16 doublewords)
PUSH 0
PUSH 0
PUSH 0
PUSH 0
PUSH 0
PUSH 0
PUSH 0
PUSH 0
PUSH 0
PUSH 0
PUSH 0
PUSH 0
PUSH 0
PUSH 0
PUSH 0
MOV ECX,
JECXZ @@44
CMP ECX,10
JBE @@40
MOV ,OFFSET E_NPARM
JMP ERROR
@@40: MOV EAX,OFFSET ARGLIST
@@42: PUSH ; Push requested number of arguments
ADD EAX,4
LOOP @@42
@@44: MOV ,ESP ; Expected ESP after return (C)
MOV EAX, ; Preset registers
MOV ECX,
MOV EDX,
MOV EBX,
MOV ESI,
MOV EDI,
Prepatch: NOP ; Patch area before call
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
CallDLL: CALL ; Call DLL function
NOP ; Patch area after call
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
MOV ,EAX ; Get modified registers
MOV ,ECX
MOV ,EDX
MOV ,EBX
MOV ,ESI
MOV ,EDI
MOV EAX,ESP
SUB EAX,
MOV ,EAX
MOV EBP,
MOV ESP,
MOV ,0 ; Confirm execution
NOP
Finished: INT 3 ; Pause after execution
NOP
NOCALL: PUSH 0
CALL Sleep ; Be fair to other applications
PUSH 1 ; PM_REMOVE
PUSH 0 ; Process all messages
PUSH 0
PUSH 0 ; Any window
PUSH OFFSET MSG
CALL PeekMessageA
OR EAX,EAX
JZ WINLOOP
PUSH OFFSET MSG
CALL TranslateMessage
PUSH OFFSET MSG
CALL DispatchMessageA
MOV EAX,
CMP EAX,12h ; WM_QUIT
JNE WINLOOP
PUSH 0
CALL ExitProcess ; Hasta la vista!
ERROR: PUSH 00001001h ; Special return code, means error
CALL ExitProcess ; Error detected
ALIGN 4
Patcharea: DB 2047 DUP(90h) ; Big patch area (2 K of NOPs)
Endpatch:NOP
ENDS _TEXT1
END START
LOADDLL.RC:
MAINICON ICON // Green bug
{
'00 00 01 00 02 00 20 20 10 00 00 00 00 00 E8 02'
'00 00 26 00 00 00 10 10 10 00 00 00 00 00 28 01'
'00 00 0E 03 00 00 28 00 00 00 20 00 00 00 40 00'
'00 00 01 00 04 00 00 00 00 00 80 02 00 00 00 00'
'00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00'
'00 00 00 00 80 00 00 80 00 00 00 80 80 00 80 00'
'00 00 80 00 80 00 80 80 00 00 80 80 80 00 C0 C0'
'C0 00 00 00 FF 00 00 FF 00 00 00 FF FF 00 FF 00'
'00 00 FF 00 FF 00 FF FF 00 00 FF FF FF 00 00 00'
'00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00'
'00 00 00 00 02 A0 00 00 00 00 A2 00 00 00 00 00'
'00 00 00 00 0A 20 00 00 00 0A 2A 2A 00 00 00 00'
'00 00 00 00 A2 A2 00 00 00 A2 A2 A2 00 00 00 00'
'00 00 00 00 2A 2A 00 00 0A 2A 2A 2A 00 00 00 00'
'00 00 00 00 A2 A2 00 00 A2 A2 A2 A0 00 00 00 00'
'00 00 00 00 2A 2A 00 0A 2A 2A 2A 20 00 00 02 A2'
'00 00 00 00 02 A2 A0 A2 A2 A2 A2 00 00 00 0A 2A'
'2A 2A 00 00 0A 2A 2A 2A 2A 2A 20 00 00 00 02 A2'
'A2 A2 A0 00 02 A2 A2 A2 A2 A2 00 00 00 00 0A 2A'
'2A 2A 2A 2A 2A 2A 2A 2A 2A 00 00 00 00 00 00 A2'
'A2 A2 A2 A2 A2 A2 A2 A2 00 00 00 00 00 00 00 00'
'2A 2A 2A 2A 2A 2A 2A 2A 00 00 00 00 00 00 00 00'
'00 02 A2 A2 A2 A2 A2 A2 00 00 00 00 00 00 00 00'
'00 00 0A 2A 2A 2A 2A 2A 2A 00 00 00 00 00 00 00'
'00 00 02 A2 A2 A2 A2 A2 A2 A2 A2 00 00 00 00 00'
'00 00 0A 2A 2A 2A 2A 2A 2A 2A 2A 20 00 00 00 00'
'00 00 02 A2 A2 A2 A2 A2 A2 A2 A2 A2 A2 00 00 00'
'00 00 0A 2A 2A 2A 2A 2A 00 00 2A 2A 2A 20 00 00'
'00 00 A2 A2 A0 A2 A2 A0 00 00 02 A2 A2 A0 00 00'
'00 00 2A 2A 00 0A 2A 20 00 00 00 2A 2A 20 00 00'
'00 00 00 00 00 00 A2 A0 00 00 00 00 00 00 00 00'
'00 00 00 00 00 00 2A 20 00 00 00 00 00 00 00 00'
'00 00 00 00 00 00 A2 A0 00 00 00 00 00 00 00 00'
'00 2A 20 00 00 00 2A 2A 00 00 00 00 00 00 00 00'
'A2 A2 A0 00 00 00 A2 A2 00 00 00 00 00 00 00 00'
'2A 2A 20 00 00 00 2A 2A 00 00 00 00 00 00 00 00'
'A2 A2 A0 00 00 00 02 A2 00 00 00 00 00 00 00 0A'
'2A 2A 20 00 00 00 0A 2A 00 00 00 00 00 00 00 02'
'A2 A2 00 00 00 00 00 00 00 00 00 00 00 00 00 0A'
'2A 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00'
'00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF F9'
'FF 3F FF F0 FE 0F FF F0 FC 07 FF E0 78 07 FF E0'
'70 07 FF E0 60 0F 8F E0 40 0F 00 F0 00 1F 00 70'
'00 3F 00 10 00 7F 00 00 00 FF 80 00 03 FF C0 00'
'0F FF E0 00 03 FF FC 00 00 3F FF 00 00 1F FF 00'
'00 03 FF 00 00 01 FF 00 00 00 FE 00 0F 00 FE 04'
'0F 80 FF 0E 0F C1 FF FE 0F FF FC 7E 0F FF F0 3E'
'07 FF E0 3E 07 FF E0 3E 07 FF C0 3F 07 FF C0 3F'
'07 FF C0 7F 0F FF C0 FF FF FF E3 FF FF FF 28 00'
'00 00 10 00 00 00 20 00 00 00 01 00 04 00 00 00'
'00 00 C0 00 00 00 00 00 00 00 00 00 00 00 00 00'
'00 00 00 00 00 00 00 00 00 00 00 00 80 00 00 80'
'00 00 00 80 80 00 80 00 00 00 80 00 80 00 80 80'
'00 00 80 80 80 00 C0 C0 C0 00 00 00 FF 00 00 FF'
'00 00 00 FF FF 00 FF 00 00 00 FF 00 FF 00 FF FF'
'00 00 FF FF FF 00 00 00 00 00 00 00 00 00 00 00'
'00 AA 00 0A AA 00 00 00 00 AA 00 AA AA 00 00 00'
'00 AA 0A AA A0 00 0A AA 00 0A AA AA 00 00 0A AA'
'AA AA AA 00 00 00 00 0A AA AA AA 00 00 00 00 00'
'0A AA AA A0 00 00 00 00 0A AA AA AA AA 00 00 00'
'AA AA AA 00 AA A0 00 00 00 00 A0 00 00 00 00 00'
'00 00 A0 00 00 00 00 0A 00 00 AA 00 00 00 00 AA'
'00 00 AA 00 00 00 00 AA 00 00 00 00 00 00 00 00'
'00 00 00 00 00 00 FC E3 00 00 F8 41 00 00 F8 01'
'00 00 88 03 00 00 00 07 00 00 00 0F 00 00 80 1F'
'00 00 E0 03 00 00 F0 01 00 00 E0 00 00 00 F0 31'
'00 00 EE 3F 00 00 86 1F 00 00 86 1F 00 00 87 3F'
'00 00 8F FF 00 00'
}
从START开始执行,loaddll获取命令行,跳过可执行文件名(必须有双引号),解析dll路径将其传给loadlibrary,一旦出错,就会将错误信息指针放到固定位置,以0x1001退出码退出,成功后创建一个小窗口,然后暂停在Firstbp,这个断点是ollydbg启动时设置的。所有和ollydbg的通信都是通过128字节内存区,这个区域必须从0x420020开始,该处刚好位于关键区域之后。前几个数据包含loaddll.exe的地址,用于ollydbg设置断点和参数。接着是函数调用地址,寄存器内容,参数个数,参数。当loaddll执行到windows消息循环时,它会不断检查输出函数的地址是否非0,如果是,loaddll保存ESP和EBP,将16个0压栈。这样能避免用户指定无效参数个数。然后他会将参数和寄存器压栈,在Prepatch地址有16个NOP用于打补丁。如果你需要更多空间,可以调到Patcharea 2K字节长的地方。注意到Ollydbg在存在同名文件时不解析loaddll.exe 当CallDLL输出函数被调用时,该指令之后会有16个NOP,调用之后程序保存修改的寄存器和ESP偏移。如果提供的参数个数非法,ollydbg会报告错误。最终loaddll存储esp和ebp,清空PROCADR,断在Finished的INT3处,当执行到这里,ollydbg知道直接完毕。
Loaddll.asm是自由软件,不过不要使用loaddll.rc的绿虫子图标!
{:soso_e163:}
页:
[1]