7、动态分析工具(上):OllyDbg/x64dbg基础使用
动态分析,说白了就是让程序跑起来,然后我们在旁边盯着它的一举一动。静态分析像是在看剧本,动态分析则是直接看演员在台上表演。我个人觉得,真正有意思的逆向工作,往往是从动态分析开始的。
今天我们要聊的两把利器——OllyDbg和它的接班人x64dbg。嗯,这里要注意,OllyDbg已经有些年头了,但它处理32位程序的能力依然很能打。而x64dbg,顾名思义,是专门为64位世界准备的。我在项目中遇到过不少次,拿着OllyDbg去调64位的程序,结果打不开,那种尴尬你懂的。
7.1 界面布局:别被密密麻麻的窗口吓到
第一次打开调试器,你可能会觉得眼花缭乱。别慌,核心就四个窗口:
| 窗口名称 | 作用 | 我的习惯 |
|---|---|---|
| 反汇编窗口 | 显示CPU指令,这是主战场 | 我一般会把它拉大,占屏幕一半 |
| 寄存器窗口 | 显示CPU寄存器的当前值 | 重点关注EAX/RAX,返回值常在这里 |
| 堆栈窗口 | 显示函数调用栈和局部变量 | 看函数参数时必看这里 |
| 内存转储窗口 | 查看任意内存地址的内容 | 字符串、数据结构都在这 |
你想想看,这四个窗口其实对应了程序的四个维度:代码在做什么(反汇编)、CPU的状态(寄存器)、调用关系(堆栈)、数据长什么样(内存)。搞懂这四块,你就掌握了调试器的命脉。
7.2 断点:让程序在你想停的地方停下来
断点就是给程序设个路障。程序跑到这里,就会乖乖停下来等你检查。OllyDbg和x64dbg都支持好几种断点,但最常用的就三种:
7.2.1 普通断点(INT3断点)
这是最基础的断点。调试器会在你指定的地址写入一个0xCC指令(也就是INT3中断)。程序执行到这里,就会触发异常,调试器就接管了控制权。
怎么设?简单:在反汇编窗口找到你想停的那行指令,按F2。再按一次F2取消。就这么简单。
7.2.2 内存断点
内存断点不是停在某条指令上,而是停在某个内存被访问的时候。比如你想知道某个全局变量什么时候被修改了,就可以在它身上设内存断点。
操作步骤:
- 在内存转储窗口找到目标地址
- 选中一段内存区域
- 右键 → 断点 → 内存访问/内存写入
内存断点分两种:内存访问断点(读或写都触发)和内存写入断点(只有写才触发)。我个人习惯先用写入断点,因为大部分时候我们关心的是谁改了数据。
7.2.3 硬件断点
硬件断点是个好东西。它利用CPU的调试寄存器(DR0-DR3)来实现,不会修改程序代码,所以能绕过很多反调试检测。
在x64dbg里,选中一条指令,右键 → 断点 → 硬件断点,然后选择执行、写入或访问。硬件断点最多只能设4个,因为CPU只有4个调试寄存器。
为什么会这样?因为硬件断点是在CPU层面实现的,不是软件模拟的。所以它更快、更隐蔽,但也更稀缺。
| 断点类型 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| 普通断点 | 无限数量,操作简单 | 容易被检测,修改代码 | 调试自己的程序 |
| 内存断点 | 监控数据访问 | 性能差,只能设一个 | 追踪数据流向 |
| 硬件断点 | 隐蔽,不修改代码 | 最多4个 | 对抗反调试 |
7.3 单步执行:一步一步看程序怎么走
设好断点后,程序停下来了。接下来怎么走?单步执行就是让你一步一步地看程序执行。
常用的几个快捷键:
- F7(步进):执行一条指令,如果遇到CALL就进入函数内部
- F8(步过):执行一条指令,如果遇到CALL就整个执行完,不进去
- F9(运行):直接运行到下一个断点
- Ctrl + F9(执行到返回):一直运行到当前函数返回
我刚开始学逆向的时候,有个坏习惯:不管遇到什么CALL都按F7进去看。结果经常钻进一个几百行的系统函数里,半天出不来。后来学乖了,先按F8步过,如果觉得这个函数有问题,再重新调试进去看。
7.4 修改内存与寄存器:调试器不只是看的,还能改
调试器最强大的地方在于——你可以改变程序的运行状态。这就像你在看一部电影,突然可以改写剧本了。
7.4.1 修改寄存器
在寄存器窗口,双击某个寄存器的值,就可以直接修改。比如你想跳过某个条件判断,可以把ZF标志位从0改成1。
我记得有一次,我在分析一个软件的注册验证。它把用户输入的注册码经过一系列计算后,跟正确的注册码比较。比较结果存在EAX里,如果是0就表示失败。我直接在比较指令后面把EAX改成1,程序就认为注册成功了。虽然这只是临时绕过,但帮我确认了验证逻辑的位置。
7.4.2 修改内存
在内存转储窗口,你可以直接修改任意地址的数据。右键 → 编辑,或者直接按Ctrl + E。
举个例子:
// 假设程序里有个判断
if (is_admin == 0) {
printf("你没有管理员权限\n");
exit(0);
}
// 在内存中找到is_admin变量
// 地址: 0x004A3B10
// 当前值: 00
// 改成: 01
// 程序就认为你是管理员了
修改内存时要注意字节序。x86是小端序,比如你要写一个DWORD值0x12345678,在内存里看到的是78 56 34 12。我第一次改内存时没注意这个,折腾了半天才发现是顺序搞反了。
7.5 知识体系总览
说了这么多,我们来梳理一下本章的核心逻辑。下面这张图可以帮你快速建立知识框架:
这张图把今天讲的内容串起来了。你想想看,界面布局是操作基础,断点是暂停程序的手段,单步执行是精细控制,修改能力则是逆向的终极武器。四者缺一不可。
好了,今天的内容就到这里。OllyDbg和x64dbg的功能远不止这些,但掌握了界面、断点、单步执行和修改能力,你已经可以应付大部分逆向场景了。剩下的,就是在实战中慢慢积累经验了。