关闭

OllyDbg完全教程 示例 不完整

2377人阅读 评论(0) 收藏 举报
在我们选择这个函数后,右边的消息框中会出现 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] 类型,等等。

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:107185次
    • 积分:1267
    • 等级:
    • 排名:千里之外
    • 原创:12篇
    • 转载:33篇
    • 译文:0篇
    • 评论:6条
    最新评论