资讯动态

x64dbg StepInto(sti)单步步入命令完全指南:Trap-Flag 单步原理、参数与源码实现

发布时间:2026/9/19 20:24:53 来源:尧图企业网站定制
x64dbg StepIntosti单步步入命令完全指南Trap-Flag 单步原理、参数与源码实现【免费下载链接】x64dbgAn open-source user mode debugger for Windows. Optimized for reverse engineering and malware analysis.项目地址: https://gitcode.com/gh_mirrors/x6/x64dbg本文以 x64dbg 官方命令文档 docs/commands/debug-control/StepInto.md 为骨架深入剖析StepInto别名sti命令的语法、参数、执行语义及其底层源码实现同时覆盖eStepInto、seStepInto等变体命令的差异帮助逆向工程师在动态调试中精确控制单步行为并理解 x64dbg 是如何借助 Trap-Flag 完成指令级步进的。命令概览StepInto / sti 是什么StepInto是 x64dbg 中最基础的调试控制命令之一作用是单步步入Single Step即执行当前指令后暂停在被执行指令的下一条指令处。若当前指令是一条call则会进入被调用函数内部继续逐指令执行这是与单步跳过StepOver的核心区别。根据文档该命令有以下要点别名sti此外SingleStep、sstep、sst也是它的同义命令由命令注册表确认。实现方式文档明确标注为Single Step (using Trap-Flag)即通过 CPU 的陷阱标志TF, Trap Flag实现单步而非软件断点INT3或硬件断点DR 寄存器。参数可选参数[arg1]指定步进次数缺省为1。结果变量该命令不设置任何结果变量如$result等因此无法直接在脚本中通过结果变量判断执行是否成功。命令语法与参数详解基本用法StepInto sti在无参数情况下x64dbg 执行一条指令后暂停等价于 GUI 中的 F7 快捷键默认设置下。指定步进次数sti 5执行 5 次单步后暂停。参数arg1通过valfromstring解析因此除十进制整数外也支持表达式/十六进制值等 x64dbg 表达式语法。参数细节与边界行为参数含义默认值边界行为无参数步进 1 次1—0不执行任何步进—源码中if(!steprepeat) return true;直接返回不做任何操作正数n连续步进 n 次—每次步进后递减计数直到为 0 才暂停非法表达式解析失败—valfromstring返回 false命令直接失败返回三个 StepInto 变体普通 / e / se 的差异x64dbg 在StepInto基础上提供了两个异常处理语义不同的变体均由命令注册表 src/dbg/x64dbg.cpp 注册命令别名注册的回调异常语义StepIntosti,SingleStep,sstep,sstcbDebugStepInto正常单步遇 first-chance 异常按异常过滤器处理eStepIntoesticbDebugeStepInto单步并跳过所有 first-chance 异常不中断seStepIntosesti,eSingleStep,esstep,esstcbDebugseStepInto单步并吞掉当前异常若正停在异常上则继续执行并吞掉该异常三者均以cbDebugStepInto为核心实现区别仅在前置处理src/dbg/commands/cmd-debug-control.cppbool cbDebugeStepInto(int argc, char* argv[]) { dbgsetskipexceptions(true); // 跳过 first-chance 异常 return cbDebugStepInto(argc, argv); } bool cbDebugseStepInto(int argc, char* argv[]) { cbDebugContinue(argc, argv); // 吞掉当前异常DBG_CONTINUE return cbDebugStepInto(argc, argv); }实际场景中调试系统代码或库函数时频繁的 first-chance 异常如访问违例试探会打断单步流程此时用esti可以无痛连续步进若程序已停在某个异常处直接用sti步进可能再次触发该异常而sesti先吞掉异常再步进行为更干净。源码级原理从命令到 Trap-Flag 的完整调用链命令注册StepInto系列命令在调试器初始化时通过dbgcmdnew注册注意最后一个参数为true表示这是debug-only 命令——只有在调试会话激活时才能使用dbgcmdnew(StepInto,sti,SingleStep,sstep,sst, cbDebugStepInto, true); dbgcmdnew(eStepInto,esti, cbDebugeStepInto, true); dbgcmdnew(seStepInto,sesti,eSingleStep,esstep,esst, cbDebugseStepInto, true);src/dbg/x64dbg.cpp核心实现 cbDebugStepIntocbDebugStepInto的完整逻辑src/dbg/commands/cmd-debug-control.cppbool cbDebugStepInto(int argc, char* argv[]) { duint steprepeat 1; if(argc 1 !valfromstring(argv[1], steprepeat, false)) return false; if(!steprepeat) //nothing to be done return true; if(skipInt3Stepping(1, argv) !--steprepeat) return true; StepIntoWow64(cbStep); dbgsetsteprepeat(true, steprepeat); return cbDebugRunInternal(1, argv, steprepeat 1 ? history_record : history_clear); }关键步骤逐条解读解析步进次数默认steprepeat 1若提供了argv[1]则用valfromstring解析为数值失败则命令返回false。零次步进短路steprepeat 0时直接返回不触发任何底层步进。INT3 跳过优化skipInt3Stepping检查是否停在 INT3 异常且用户开启了SkipInt3Stepping选项。若满足则吞掉该异常并减少一次步进计数src/dbg/commands/cmd-debug-control.cpp。这一机制用于避免在断点指令本身是 INT3上原地踏步。发起底层单步StepIntoWow64(cbStep)触发真正的一次指令级单步cbStep是每完成一步后的回调。记录重复步数dbgsetsteprepeat(true, steprepeat)将是否步进true 表示 StepInto 而非 StepOver与剩余次数写入全局状态src/dbg/debugger.cpp。恢复运行并管理历史cbDebugRunInternal将调试状态切换为 running、解除等待锁并广播CB_RESUMEDEBUG插件回调。值得注意的是只有单步 1 次时才记录历史history_record为InstrUndo撤销指令提供依据多次连续步进则不记录避免历史膨胀src/dbg/commands/cmd-debug-control.cpp。Trap-Flag 单步与 Wow64 兼容处理文档所述 using Trap-Flag 正是通过 TitanEngine 的StepInto原语设置 CPU 的 TF 标志实现CPU 执行完当前指令后触发单步异常EXCEPTION_SINGLE_STEP调试器捕获后暂停。StepIntoWow64是对底层StepInto的封装src/dbg/debugger.cpp包含两项特殊处理Wow64 长跳转 workaround仅 32 位构建在 x86 调试器x32dbg调试 64 位程序时系统切换代码段会执行ljmp 33,XXXXXXXX机器码EA XX XX XX XX 33 00。x64dbg 检测到该指令后改为在栈顶返回地址处设置单次断点SetBPX(ret, UE_SINGLESHOOT, callback)从而跨过模式切换点避免 Trap-Flag 在 64 位代码中失效。未处理异常分发兜底若当前正停在未处理异常上且存在异常分发地址则在分发地址设置单次断点而不是盲目依赖 TF。步进完成回调 cbStep每次单步完成或连续步进的每一步完成后底层引擎回调cbStepsrc/dbg/debugger.cppvoid cbStep() { hActiveThread ThreadGetHandle(GetDebugData()-dwThreadId); duint CIP GetContextDataEx(hActiveThread, UE_CIP); if(bAbortStepping || !stepRepeat || !--stepRepeat) { DebugUpdateGuiSetStateAsync(CIP, paused); dbgtraceexecute(CIP); ... // 插件回调 CB_PAUSEDEBUG / CB_STEPPED lock(WAITID_RUN); ... } else { dbgtraceexecute(CIP); (bRepeatIn ? StepIntoWow64 : StepOverWrapper)(cbStep); } }逻辑要点每次步进都调用dbgtraceexecute(CIP)将当前地址写入 Trace Record配合StartRunTrace可回溯执行轨迹若还有剩余步数stepRepeat未归零自动发起下一次StepIntoWow64实现连续步进而无需用户干预步数耗尽或收到bAbortStepping如用户按 Pause时才更新 GUI 状态为 paused、触发CB_PAUSEDEBUG与CB_STEPPED插件回调并进入等待状态bRepeatIn决定续步时用StepIntoWow64还是StepOverWrapper这正是StepInto与StepOver在连续步进时行为差异的根源。相关命令与补充说明StepInto属于 Debug Control 命令族与之配套的还有StepOver单步跳过call不进入直接执行完整个调用StepOut执行到当前函数返回eStepOver、seStepOver跳过异常语义的 StepOver 变体skip不解码执行、直接跳过指令InstrUndo配合单步历史记录实现指令级撤销HistoryRestoreStepUser / StepSystem仅步进用户模块 / 仅步进系统模块代码。这些命令共享同一套参数约定可选步数与不设置结果变量的语义便于脚本中统一记忆。常见问题速查sti与 F7 的关系GUI 默认将 F7 绑定到StepInto但快捷键可通过选项自定义命令行执行与快捷键最终走同一条命令路径。连续步进会暂停在哪里若步进途中遇到断点、异常或用户暂停x64dbg 会提前停下bAbortStepping而不是机械地走满指定步数。Trace Record 的配合单步时配合StartRunTrace可记录每一步的指令地址用于事后分析执行流。小结StepInto看似简单其背后却串联了命令解析、Trap-Flag 单步、Wow64 兼容处理、连续步进调度、Trace Record 记录与插件回调通知等一整套调试器基础设施。掌握它的参数语义步进次数、零值短路与三个变体普通/e/se的异常处理差异是高效使用 x64dbg 进行指令级逆向分析的基础而理解cbStep的重复步进循环则能帮助你在编写自动化脚本或插件时准确预判单步命令的暂停时机与行为边界。【免费下载链接】x64dbgAn open-source user mode debugger for Windows. Optimized for reverse engineering and malware analysis.项目地址: https://gitcode.com/gh_mirrors/x6/x64dbg创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价