一、前言
OllyDbg简称OD,是一款具有可视化界面的用户模式调试器,结合了动态调试和静态分析,具有强大的反汇编引擎,能够识别数千个被C和Windows所使用的函数,并能将其参数注释出,能自动分析函数过程,循环语句,代码中的字符串等,非常容易上手,并且对异常的跟踪处理相当灵活,这些特性使得OllyDbg成为调试ring3级程序的首选工具,爱好者不断地修改,扩充OllyDbg,脚本执行能力和开发插件接口使得其变得越来越强大。
二、界面构成
2.1 开始页面
开始页面如图:
2.2 实验准备
现在我编译一个很简单的C++程序(normal.exe):
1 |
|
其正常输出如下:
2.3 载入程序,解释界面
单击“File”->“open”选项,打开一个EXE文件,这次打开的是之前编译过的C++程序。
载入程序后的界面如下:
下面解释各个部分的功能含义:
标题栏
显示当前线程(main)和当前运行的程序名(normal)菜单栏
快捷入口
里面集成了许多系统工具,如文本编辑器(notepad),计算器(calc)等调试快捷键
(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]窗口快捷键
使用OD打开目标程序后,OD会打开多个子窗口,单击各个标签按钮可以在各个子窗口之间切换,这些按钮依次对应Log窗口,Executable modules窗口,Memory窗口,Threads窗口,Windows窗口,Handles窗口,CPU窗口,Patches窗口,Call stack窗口,Breakpoints窗口,References窗口,Run trace窗口,Source窗口。反汇编面板窗口
- Address列:显示被双击行地址的相对地址,再次双击返回标准地址模式
- Hex dump列:设置或取消无条件断点,对应的快捷键是“F2”键。
- Disassembly列:调用汇编器,可直接修改汇编代码,对应的快捷键是空格键。
- Comment列:允许增加或编辑注释,对应的快捷键是“;”键。
寄存器面板窗口
寄存器面板窗口( Registers window)显示CP各寄存器的值,支持浮点、MM和3DNow寄存器。可以单击右键或窗口标题切换显示寄存器的方式。信息面板窗口
在进行动态跟踪时,信息面板窗口(Information window)将显示与指令相关的各寄存器的值、API函数调用提示和跳转提示等信息。数据面板窗口
数据面板窗口( Dump window)以十六进制和字符方式显示文件在内存中的数据。要显示指定内存地址的数据,可单击右键快捷菜单中的Go to expression命令或按“Ctrl+G”快捷键,打开地址窗口,输入地址。栈面板窗口
栈面板窗口(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,如下图所示:
可以看到函数对堆栈进行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):
这样就可以看到那些指令被执行过
双击后便可以直达指令处: