Vanlin的BLOG

好好学习,天天向上

OllyDbg完全教程 示例 不完整

在我们选择这个函数后,右边的消息框中会出现 Number of arguments: 4(有四个参数)的字样。OllyDbg 会根据函数尾部的RET 10语句来正确识别参数的数量。RET nnn
是使用PASCAL调用约定的函数的典型特征。(参数被放入栈中,第一个参数会被最后一个压入栈中,函数调用完毕后,参数会被遗弃)。大多数的 Windows API 函数都是
PASCAL形式的。

下一步,我们要设定栈中参数的个数。在这个例子中,不必做进行这个操作,因为OllyDbg已经知道了MessageBoxW函数的参数数量。但是,如果您愿意的话,也可以单击左边的复选框,改变成您认为合适的参数数量

现在填写参数列表。这个对话框中支持至多10个参数. 参数可以是任何有效的表达式,而不必使用寄存器。如果操作数指向了内存,则参数右边的缓冲区窗口会显示内存中的数据。Loaddll.exe 有10个大小为1K的缓冲区,这些缓冲区被标记为Arg1 .. Arg10,,您可以方便自由的使用它们。 另外,对话框还支持两个伪变量:由loaddll.exe创建的父窗口句柄<Hwnd>, 以及loaddll的实例句柄<Hinst>。为了方便您的使用,在您第一次使用调用输出函数时,OllyDbg就已经将这两个伪变量加到了历史列表中去了。

MessageBoxW e函数需要4个参数:


?父窗口句柄。 这里我们选择<Hwnd> ;handle of owner window. Here, we simply select <Hwnd>;
?在消息框中UNICODE文本的地址。选择Arg2并按回车。缓冲区窗口会以16进制的格式显现内存中的缓冲区。这个缓冲区初始化全是0。点击第一个字节,并按快捷键
Ctrl+E(另外, 也可以从菜单中选择“二进制[Binary]|编辑[Edit]”)。这时会出现一个对话框,在对话框中键入“Text in box”或者其他希望显示的字符串;

?消息框标题的UNICODE文本的地址。选择Arg3并在Unicode格式的内存中写上“Box title”;
?消息框的风格。使用常量MB_xxx进行组合.OllyDbg 可以识别这些常量。在这里我们键入:MB_OK|MB_ICONEXCLAMATION。

这里不需要寄存器参数。

现在我们准备调用输出函数。选项“在调用时隐藏[Hide on call]”意思是说,当函数运行时对话框将会从屏幕消失。当我们执行一个会运行很长时间的函数,或者设置了断点的时候,这个选项非常的有用。您也可以手动关闭对话框。当函数执行完毕后,OllyDbg会重新自动打开。“调用输出函数”对话框。选项“在调用后暂停[Pause after call]”意思是说,在执行完函数后,loaddll将会被暂停。

按“调用[Call]按钮”后,OllyDbg 会自动备份所有的内存、校验、参数、寄存器等信息。并隐藏对话框,然后调用 MessageBoxW 函数。和期望的一样,消息框在屏幕中出现了:

函数 MessageBoxW 不会修改参数。如果您调用的函数更新了内存,比如函数 GetWindowName,修改的字节将会在数据区里高亮。注意:EAX 返回值为1,表示成功。

其他的例子请访问我的网站:
http://home.t-online.de/home/Ollydbg/Loaddll.htm.

不幸的是,您不能通过这种方式调试OllyDbg的插件,插件关联到ollydbg.exe文件,Windows系统不能在同一个应用程序里加载并运行两个可执行文件。

解码提示[Decoding hints]
在某些情况下,分析器不能区分代码和数据。让我们看看下面的例子:


const char s[11] = "0123456789";
...
for (i=0x30; i<0x3a; i++) t[i-0x30]=s[i-0x30];

好的编译器将会将上面的代码优化成如下样子: e


for (i=0x30; i<0x3a; i++) (t-0x30)=(s-0x30);

这里t-0x30 和 s-0x30 都是常量,并编译成如下形式:


MOV AL,[BYTE s_minus_30+EBX]
MOV [BYTE t_minus_30+EBX],AL

编译器也可能将常量字符串"0123456789"插入到执行代码中。在1.10版本中,我打算用寄存器的值来决定是否的数据或代码。当遇到上面的命令,分析器将假定地址
s_minus_30处包含字符数据。但事实上,可能那里是代码。

万一出现上述问题,我们应该怎么办呢?有两种办法:最快最笨的办法是:将分析错误的部分删除(快捷键:退格键),这样OllyDbg将使用默认的反汇编器进行解码。

更好的办法是使用解码提示[decoding hints]。您可以告诉OllyDbg如何解释选中的内存内容。这种方法在重新分析(Ctrl+A)时,解释依然有效。

设置提示的方法:在反汇编窗口中,选中需要修正提示的代码或数据,然后在快捷菜单中选择 分析[Analysis]|在下次分析时,将选择部分视为[During next analysis, treat selection as]。选择以下选项之一:


命令[Command] - 第一个被选中的字节开始的有效命令。这条命令,还有所有后面的部分,直到有Jump或Return命令出现,以及含有Jump或Call命令所到达位置的部分,都会被视为命令;

字节[Byte],
字[Word],
双字[Doubleword] - 选中的前1、2、4字节视为对应大小的数据;

所有选中命令[Commands] - 全部选中部分(直到第一个无效命令)和可以到达由有效命令集组成的目的地址;

字节[Bytes],
字[Words],
双字[Doublewords], - 全部选中部分以1、2、或 4字节分组;

ASCII字符串[ASCII text],
UNICODE字符串[UNICODE text] - 全部选中部分为ASCII 或 UNICODE 字符串;

默认(移除提示)[Default (remove hints)] - 从选中部分中移除全面提示;

移除全部提示[Remove all hints] - 从全部模块中移除解码提示。

OllyDbg 保存提示到.udd文件中。

表达式赋值[Evaluation of expressions]

[code]
OllyDbg能够支持非常复杂的表达式。表达式的语法格式将在这个主题的后面进行介绍,但我想您对此不一定真的感兴趣。那么我先举几个实例来说明:


10 - 常量 0x10 (无符号)。所有整数常量都认为是十六进制的,除非后面跟了点;

10. - 十进制常量10(带符号);

'A' - 字符常量 0x41;

EAX - 寄存器EAX的内容,解释为无符号数;

EAX. -寄存器EAX的内容,解释为带符号数;

[123456] - 在地址123456处的无符号双字内容。默认情况,OllyDbg假定是双字长操作数;

DWORD PTR [123456] - 同上。关键字 PTR 可选;

[SIGNED BYTE 123456] - 在地址123456处带符号单字节。OllyDbg支持类MASM和类IDEAL两种内存表达式;

STRING [123456] - 以地址123456作为开始,以零作为结尾的ASCII字符串。中括号是必须的,因为您要显示内存的内容;

[[123456]] - 在地址123456处存储的双字所指向的地址内的双字内容;

2+3*4 - 值为14。OllyDbg 按标准C语言的优先级进行算术运行;

(2+3)*4 - 值为20。使用括号改变运算顺序。

EAX.<0. - 如果EAX在0到0x7FFFFFFF之间,则值为0,否则值为1。注意0也是有符号的。当带符号数与无符号数比较时,OllyDbg会将带符号数转成无符号数。

EAX<0 - 总为0(假),因为无符号数永远是正的。

MSG==111 - 如果消息为WM_COMMAND,则为真。0x0111是命令 WM_COMMAND 的数值。MSG只能用于设置在进程消息函数的条件断点内。

[STRING 123456]=="Brown fox" - 如果从地址0x00123456开始的内存为ASCII字符串"Brown fox"、"BROWN FOX JUMPS"、 "brown fox???",或类似的串,那么其值为1。比较不区分大小写和文本长度。

EAX=="Brown fox" - 同上,EAX按指针对待。

UNICODE [EAX]=="Brown fox" - OllyDbg认为EAX是一个指向UNICODE串的指针,并将其转换为ASCII,然后与文本常量进行比较。

[ESP+8]==WM_PAINT - i在表达式中您可以使用上百种Windows API符号常量。

([BYTE ESI+DWORD DS:[450000+15*(EAX-1)]] & 0F0)!=0 - 这绝对是个有效的表达式。

现在我们介绍语法格式。在大括号({})内的每个元素都只能出现一次,括号内的元素顺序可以交换:


表达式 = 内存中间码|内存中间码<二元操作符>内存中间码

内存中间码 = 中间码| { 符号标志 大小标志 前缀} [表达式 ]

中间码 = (表达式)| 一元操作符 内存中间码 | 带符号寄存器 | 寄存器 | FPU寄存器 | 段寄存器 | 整型常量 | 浮点常量 | 串常量 | 参数 | 伪变量

一元操作符 = ! | ~ | + |

带符号寄存器 = 寄存器.

寄存器 = AL | BL | CL ... | AX | BX | CX ... | EAX | EBX | ECX ...

FPU寄存器 = ST | ST0 | ST1 ...

段寄存器 = CS | DS | ES | SS | FS | GS

整型常量 = <十进制常量>. | <十六进制常量> | <字符常量> | <API符号常量>

浮点常量 = <符点常量>

串常量 = "<串常量>"

符号标志 = SIGNED | UNSIGNED

大小标志 = BYTE | CHAR | WORD | SHORT | DWORD | LONG | QWORD | FLOAT | DOUBLE | FLOAT10 | STRING | UNICODE

前缀 = 中间码:

参数 = %A | %B // 仅允许在监察器[inspector] 中使用

伪变量 = MSG // 窗口消息中的代码

这个语法并不严格。在解释[WORD [EAX]]或类似的表达式时会产生歧义。可以理解为以寄存器EAX所指向地址的两字节内容为地址,所指向的双字内容;也可以理解为以寄存器EAX所指向地址的四字节内容为地址,所指向的两字节内容。而OllyDbg会将修饰符尽可能的放在地址最外面,所以在这种情况下,[WORD [EAX]] 等价于 WORD [[EAX]]。

默认情况下,BYTE、WORD 和 DWORD 都是无符号的,而CHAR、SHORT 和 LONG都是带符号的。也可以使用明确的修饰符SIGNED 或 UNSIGNED。例如在二元操作时,如果一个操作数是浮点的,那么另外一个就要转成浮点数;或者如果一个是无符号胆,那么另外一个要转成无符号的。浮点类型不支持UNSIGNED。大小修饰符后面跟 MASM兼容关键字PTR(如:BYTE PTR)也允许的,也可以不要PTR。寄存器名和大小修饰符不区分大小写。

您可以使用下面类C的运算符(0级最高):


优先级 类型 运算符
0 一元运算符 ! ~ + -
1 乘除运算 * / %
2 加减运算 + -
3 位移动 << >>
4 比较 < <= > >=
5 比较 == !=
6 按位与 &
7 按位异或 ^
8 按位或 |
9 逻辑与 &&
10 逻辑或 ||
在计算时,中间结果以 DWORD 或 FLOAT10 形式保存。某些类型组合和操作是不允许的。例如:QWODRD 类型只能显示;STRING 和 UNICODE 只能进行加减操作(像C语言里的指针)以及与 STRING、UNICODE 类型或串常量进行比较操作;您不能按位移动 浮点[FLOAT] 类型,等等。

阅读更多
个人分类: 学习人生---破解说
上一篇OllyDbg完全教程 自定义函数描述[Custom function descriptions]
下一篇破解高手 教程工具篇
想对作者说点什么? 我来说一句

OllyDbg完全教程OllyDbg完全教程

2010年01月31日 7KB 下载

OllyDbg完全教程

2011年08月01日 242KB 下载

OLLYDBG完全教程

2008年09月23日 266KB 下载

OllyDbg入门完全教程(完美排版)

2018年04月01日 645KB 下载

OllyDbg完全教程.rar

2012年06月14日 165KB 下载

ollydbg完美教程(超强入门级别)

2017年08月03日 1.15MB 下载

没有更多推荐了,返回首页

关闭
关闭