一、前言

OllyDbg简称OD,是一款具有可视化界面的用户模式调试器,结合了动态调试和静态分析,具有强大的反汇编引擎,能够识别数千个被C和Windows所使用的函数,并能将其参数注释出,能自动分析函数过程,循环语句,代码中的字符串等,非常容易上手,并且对异常的跟踪处理相当灵活,这些特性使得OllyDbg成为调试ring3级程序的首选工具,爱好者不断地修改,扩充OllyDbg,脚本执行能力和开发插件接口使得其变得越来越强大。

二、界面构成

2.1 开始页面

开始页面如图:

2.2 实验准备

现在我编译一个很简单的C++程序(normal.exe):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>
using namespace std;

int main()
{
int flag = 1;
if(flag)
{
cout << "hello world!" << endl;
}
else
{
cout << "you have cracked it!" << endl;
}
system("pause");
return 0;
}

其正常输出如下:

2.3 载入程序,解释界面

单击“File”->“open”选项,打开一个EXE文件,这次打开的是之前编译过的C++程序。

载入程序后的界面如下:

下面解释各个部分的功能含义:

  1. 标题栏
    显示当前线程(main)和当前运行的程序名(normal)

  2. 菜单栏

  3. 快捷入口
    里面集成了许多系统工具,如文本编辑器(notepad),计算器(calc)等

  4. 调试快捷键

    (1) 打开新的可执行文件[快捷键F3]
    (2) 重新载入程序[快捷键Ctrl+F2]
    (3) 关闭程序 [快捷键Alt+F2]
    (4) 运行程序[快捷键F9]
    (5) 暂停执行程序 [快捷键F12]
    (6) 单步步入[快捷键F7]
    (7) 单步步过[快捷键F8]
    (8) 跟踪步入[快捷键Ctrl+F11]
    (9) 跟踪步过[快捷键Ctrl+F12]
    (10) 执行到返回[快捷键Ctrl+F9]
    (11) 转到反汇编窗中口的地址(转到表达式)[快捷键Ctrl+G]

  5. 窗口快捷键
    使用OD打开目标程序后,OD会打开多个子窗口,单击各个标签按钮可以在各个子窗口之间切换,这些按钮依次对应Log窗口,Executable modules窗口,Memory窗口,Threads窗口,Windows窗口,Handles窗口,CPU窗口,Patches窗口,Call stack窗口,Breakpoints窗口,References窗口,Run trace窗口,Source窗口。

  6. 反汇编面板窗口

    • Address列:显示被双击行地址的相对地址,再次双击返回标准地址模式
    • Hex dump列:设置或取消无条件断点,对应的快捷键是“F2”键。
    • Disassembly列:调用汇编器,可直接修改汇编代码,对应的快捷键是空格键。
    • Comment列:允许增加或编辑注释,对应的快捷键是“;”键。
  7. 寄存器面板窗口
    寄存器面板窗口( Registers window)显示CP各寄存器的值,支持浮点、MM和3DNow寄存器。可以单击右键或窗口标题切换显示寄存器的方式。

  8. 信息面板窗口
    在进行动态跟踪时,信息面板窗口(Information window)将显示与指令相关的各寄存器的值、API函数调用提示和跳转提示等信息。

  9. 数据面板窗口
    数据面板窗口( Dump window)以十六进制和字符方式显示文件在内存中的数据。要显示指定内存地址的数据,可单击右键快捷菜单中的Go to expression命令或按“Ctrl+G”快捷键,打开地址窗口,输入地址。

  10. 栈面板窗口
    栈面板窗口(Stack window)显示栈的内容,即ESP指向地址的内容。将数据放入栈的操作称为入栈(push),从栈中取出数据的操作称为出栈(pop)栈窗口非常重要,各API函数和子程序都利用它传递参数和变量等。

三、实战:运用OD

现在运用OD将一个软件(名为URLegal.exe)进行注册码破解。

3.1 简单测试

软件界面如下:
软件界面
点开注册页面如下:
注册页面
尝试注册(注册信息:Name:hjf 、Code:123456):
输入注册信息 注册失败

3.2 开始逆向

3.2.1 加载程序后,点击运行,运行后OD界面如下:

运行界面

3.2.2 查找字符串

由于注册失败界面有提示框,里面包含字符串,则搜索字符串,双击便可以进入实现注册判断的代码部分。
查找字符串

3.2.3 判断关键跳

进入后视图如下:

可以看到标记1处为跳到标记2处的关键跳之一,还有另外一个关键跳为JNZ下面的JE跳,而一般而言,关键跳的前一个CALL指令为关键CALL指令,现对JNZ上的CALL指令进行断点。
我们还可以看到堆栈中(标记3)的内容,有我们刚输入的CODE,大概猜测是用于比较用的。

3.2.4 找真正的关键跳

由于可能的关键跳有两个,一个是JNZ一个是JE,接下来判断哪个是关键跳,下断点后运行如图:

可以看到:EAX寄存器中的值为0,则test指令执行后零标志寄存器ZF=1,JNZ不会进行跳转

text eax,eax是与运算,只有当eax为00000000才能保证0标志位ZF=1 即满足下面的跳转。换言之,这个是测试eax是否为0,为0则跳 。

继续进行步过(F8),到达JE跳中(标记3),可以从下图中看到,JE下的跳转是红色的(会执行跳转),则判断JE上的CALL指令(标记2)为关键指令。
而且,在CALL和JE中间还有指令AND和TEST,这些都是对EAX寄存器进行操作。

3.2.5 进入关键CALL

判断完关键跳为JE,则尝试进入关键CALL,如下图所示:
进关键CALL
可以看到函数对堆栈进行push操作,可以大致肯定其用于比较操作。也就是说以下信息就是我们的正确CODE!可以直接拿来注册(经过验证是正确的)。

0019F950 00A3A030 ASCII “0781B2666326E5574C053884D070882E”

3.2.6 爆破

既然已经发现跳转时由于EAX寄存器的值,那么可以推断是由于在关键CALL中修改了EAX导致后面的关键跳执行,则找到最后修改EAX的指令,进行NOP填充,如图:
爆破
跳出CALL后可以看到JE不执行了

3.2.7 运行成功!

关键跳不执行,则可以直接运行了,可以看到注册成功页面:
破解成功

3.3 其他功能

3.3.1 断点查看

可以在快捷菜单选择B,或者快捷键alt+b,可以看到我下的全部断点:

可以对断点进行Disable、Remove等操作

3.3.2 函数参考

加载程序执行后,按下快捷键ctrl+N就可以看到调用的全部函数了,如图:

这样我们就可以很方便地对函数出现处进行断点:

3.3.3 内存

通过分析上面的关键CALL指令,知道EAX是装有我们的伪CODE的地址005E9F40,则可以找到在内存中的数据如下:

可以看到,我们输入的123456就在内存中。

3.3.4 消息

先打开注册页面,输入注册信息,不要点击确认,在OD里按下快捷菜单中的W,便可以看到注册框中的消息:

在Vaildate My Codes字段上右击,选择消息断点,进入以下页面

选择202左键触发

然后开启RUN跟踪

RUN跟踪是干什么的?简单的说,RUN跟踪就是把被调试程序执行过的指令保存
下来,让你可以查看被调试程序运行期间干了哪些事。RUN跟踪会把地址、寄存器的内容、消息以及已知的操作数记录
到RUN跟踪缓冲区中,你可以通过查看RUN跟踪的记录来了解程序执行了那些指令。在这还要注意一个缓冲区大小的
问题,如果执行的指令太多,缓冲区满了的话,就会自动丢弃前面老的记录。

我们可以在调试选项->跟踪中设置:

然后设置:

效果如下:(灰条)

现在回到软件点击Vaildate My Codes,便可以直达断点:

然后一步步走,会有刚输入的字符串放在堆栈和内存里的。

现在可以呼出内存映射页面M,并在CODE代码处下断点:

然后回到反汇编页面,运行,直达页面:

还可以查看RUN跟踪,选择统计(profile):

这样就可以看到那些指令被执行过

双击后便可以直达指令处: