目录
第一步:生成exe循环文件
第二步:打开 x32dbg
第三步:找到你的 main 函数
第四步:找到你的 for 循环
第五步:设置条件断点
第六步:运行程序,观察条件断点
第一步:生成exe循环文件
首先是理由vs去运行出一个exe格式的32位文件:
#include <stdio.h> int main() { int sum = 0; for (int i = 0; i < 10; i++) { sum += i; printf("i = %d, sum = %d\n", i, sum); } printf("Final sum = %d\n", sum); return 0; }配置管理器设置如下:
然后Ctrl+Shift+B生成exe文件:
第二步:打开 x32dbg
在你的电脑上,找到x32dbg.exe(32 位版本的 x64dbg),双击打开它。
打开后,你会看到一个灰色的窗口,里面有反汇编窗口、寄存器窗口、堆栈窗口等。
找到你刚才生成的
exe文件(在 VS 项目的Debug文件夹里)。用鼠标左键点住
exe,直接把它拖进 x32dbg 的窗口里,然后松开鼠标。拖进去之后,x32dbg 会加载这个程序,并自动停在一个地方。你看到的应该是类似这样的画面:
ntdll.dll 里的某个位置,比如: jmp xxxxxxxx
这不是你的代码,是 Windows 的系统代码。这完全正常,在之前的文章已经提到过。
第三步:找到你的 main 函数
按键盘上的
Ctrl键和G键(同时按下)。会弹出一个输入框,在框里输入:
_main
(注意:前面有个下划线,因为 VS 编译 32 位程序会自动加这个下划线。)
按回车。
反汇编窗口会跳到
_main函数的位置。你应该能看到类似这样的几行指令:push ebp mov ebp, esp sub esp, 0xC0
这就是你写的 main 函数。
然后点击f2进行断点设置,f9让程序之间运行到main函数入口处:
第四步:找到你的 for 循环
用鼠标滚轮慢慢往下翻(大概翻十几行)。
注意看反汇编窗口,找一条往回跳的指令,看起来像这样:
jmp 0x00401050
后面那个地址
0x00401050比当前行地址小,说明它往上跳了。这个
jmp以及它上面的那一段代码,就是你的for循环。
什么叫“往回跳”?
如果地址从
0x00401080跳到0x00401050,这就是往回跳。循环的本质是“执行一段代码,然后跳回开头”。所以一定会有一个往回跳的指令。
找到这个
jmp后,往上几行,找到循环体开始的位置。通常它会从内存里取变量i的值:mov eax, dword ptr [ebp-14]
记下这一行的地址(比如
0x00401050),等会要用。(在x32中,旁边有箭头可以辅助定位)
好的。找到了循环开始的位置,接下来我们要做最关键的一步:让程序在循环到第 5 次时自动停下来。
第五步:设置条件断点
用鼠标点击循环开始的那一行(比如
mov eax, dword ptr [ebp-0Ch]),把光标放在这一行上。按一下
F2,这一行会变成红色。这是一个普通断点。按键盘上的
Shift+F2在输入框里输入条件:
[ebp-14] == 5
解释:
[ebp-14]:这是变量i在内存中的位置(之前我们用 IDA 看到的偏移是ebp-0C,两个写法是一个意思)。== 5:当i等于 5 时条件成立。
注意:如果你在 IDA 里看到
i的偏移是ebp-8或其他值,就换成你看到的那个偏移。点击OK确定。
设置好后,这一行仍然是红色,但它现在带着一个条件——只有当i == 5时才会中断。
第六步:运行程序,观察条件断点
按一下键盘上的
F9(运行程序)。观察控制台窗口(那个黑色的命令行窗口,不是 x32dbg 的窗口)。你会看到:
i = 0, sum = 0 i = 1, sum = 1 i = 2, sum = 3 i = 3, sum = 6 i = 4, sum = 10 i = 5,sum=15
然后控制台停止打印了,程序卡住了。
回到 x32dbg 窗口,你会发现程序停在红色断点那一行。此时:
看右侧寄存器窗口,找到
EAX,它的值应该是5(因为刚把i的值加载到eax)。看右下角堆栈窗口,找到地址
EBP-0C那一行,它的值也变成了5。
发生了什么?
程序在
i = 0到i = 4时,条件[ebp-0Ch] == 5不成立,所以没有中断。当
i变成5时,条件成立了,CPU 自动把程序停住了。
你不需要手动按 5 次F8,条件断点帮你自动停在了第 6 次循环。
现在按F9,程序会继续打印剩下的输出并结束。
注意此时的栈:
在结束一次循环之前,会把i的值push到栈里面:
实验结束