x64dbg 运行追踪停止命令全解析:StopTraceRecording / StopRunTrace / tc 的原理、用法与实战
【免费下载链接】x64dbgAn open-source user mode debugger for Windows. Optimized for reverse engineering and malware analysis.项目地址: https://gitcode.com/gh_mirrors/x6/x64dbg
导读
StopTraceRecording(别名StopRunTrace、tc)是 x64dbg 中用于停止运行追踪(Run Trace)并关闭追踪记录文件的核心命令,是完整追踪工作流的收尾环节。本文以该命令为骨架,结合仓库源码讲清它在命令注册、底层实现、GUI 联动与调试生命周期中的完整调用链,并给出与StartTraceRecording、TraceIntoConditional等命令配合的可复现实战流程,帮助你掌握"开启追踪 → 录制指令 → 停止落盘 → 回放分析"的全套技能。
一、命令速览:无参、无结果变量
依据 StopRunTrace.md 官方文档,该命令的使用契约非常简单:
| 项目 | 说明 |
|---|---|
| 命令名 | StopTraceRecording(别名:StopRunTrace、tc) |
| 参数 | 无(This command has no arguments.) |
| 结果变量 | 不设置任何结果变量 |
它做的事情在文档中只有一句话:停止追踪记录并关闭记录文件(Stops trace recording and closes the file)。虽然文档极其精简,但它在命令系统中以三个名字注册,兼容了 OllyScript 风格的tc(trace close)脚本指令,因此在 x64dbg 的命令行、脚本(script)以及 GUI 菜单中都可以直接使用。
命令注册证据位于 x64dbg.cpp,与它的"开启"命令成对出现:
dbgcmdnew("StartTraceRecording,StartRunTrace,opentrace", cbDebugStartTraceRecording, true); //start run trace (Ollyscript command "opentrace" "opens run trace window") dbgcmdnew("StopTraceRecording,StopRunTrace,tc", cbDebugStopTraceRecording, true); //stop run trace (and Ollyscript command)tc别名同时被登记在脚本命令表中(见 script_commands.txt),意味着在 x64dbg 的脚本语言中同样可以调用tc停止追踪。
二、命令入口:从控制台命令到 TraceRecordManager
停止命令的处理器位于 cmd-tracing.cpp,实现极其精简——它不接受任何参数,直接委托给全局的TraceRecord管理器:
bool cbDebugStopTraceRecording(int argc, char* argv[]) { return TraceRecord.enableTraceRecording(false, nullptr); }TraceRecord是TraceRecordManager类的全局实例(声明见 TraceRecord.h),x64dbg 中所有运行追踪的开启、停止、指令记录、命中统计都收敛在这个类上。与之对称的开启命令cbDebugStartTraceRecording(cmd-tracing.cpp)则要求至少一个参数(追踪文件名),二者通过同一个enableTraceRecording(bool enabled, const char* fileName)入口,以enabled参数区分启停——这是理解本命令底层行为的关键。
三、底层实现:enableTraceRecording(false)究竟做了什么
停止逻辑位于 TraceRecord.cpp,当enabled == false时执行如下序列:
else { if(rtEnabled) { CloseHandle(rtFile); // 1. 关闭追踪文件句柄(落盘) rtPrevInstAvailable = false; // 2. 清除上一条指令缓存状态 rtEnabled = false; // 3. 置位停止标志 dputs(QT_TRANSLATE_NOOP("DBG", "Trace recording stopped.")); PLUG_CB_STOPTRACE stopTraceInfo{}; // 4. 通知插件追踪已停止 stopTraceInfo.reserved = nullptr; plugincbcall(CB_STOPTRACE, &stopTraceInfo); } return true; }可提炼出四个关键事实:
- 幂等性:只有
rtEnabled == true(即确实处于录制状态)时才执行清理,重复调用不会出错,也不会重复关闭句柄。 - 文件落盘:追踪期间通过
CreateFileW(..., FILE_APPEND_DATA, ..., OPEN_ALWAYS, ...)以追加模式持有的句柄(TraceRecord.cpp)在此处被CloseHandle关闭,保证缓冲数据完整写入磁盘。 - 状态复位:
rtPrevInstAvailable被清空,意味着下一次重新开启录制时不会沿用旧的"上一条指令"状态(TraceRecord.h 中该字段用于跨指令差分记录寄存器与内存变化)。 - 插件通知:通过
plugincbcall(CB_STOPTRACE, ...)广播停止事件,任何注册了该回调的插件都能感知追踪结束并做后续处理(如自动分析、导出等)。对应的开启阶段会广播CB_STARTTRACE(TraceRecord.cpp)。
同时,开启录制时还有一处值得注意的细节:如果当前已在录制,enableTraceRecording(true, ...)会先自动调用一次enableTraceRecording(false, NULL)实现"重开"(TraceRecord.cpp),且只有在DbgIsDebugging()为真(调试会话进行中)时才开始录制(TraceRecord.cpp);而停止命令没有此限制,即使调试已结束也可安全执行。
四、追踪文件的收尾格式:停止前写入了什么
理解停止命令"关闭文件"的意义,需要回看开启阶段写入的文件结构。enableTraceRecording(true, ...)在创建文件后,若文件为空会先写入一个文件头(TraceRecord.cpp):
- 8 字节头:
TRAC魔数(4 字节)+ 紧随其后的 JSON 头长度(4 字节); - JSON 头内容:
ver(版本,当前为 1)、arch(x86/x64,由ArchValue宏按架构生成)、hashAlgorithm(当前为murmurhash)、hash(可执行文件哈希,来自DbGetHash)、compression(当前为空串)、path(被调试模块路径,由ModPathFromAddr获得)。
若文件已存在且非空(例如追加录制),则定位到文件末尾继续追加(TraceRecord.cpp)。也就是说,停止命令执行的CloseHandle是保证上述文件头与后续指令记录完整落盘的最后一步;如果文件头写入失败(如只读介质)或写入不完整(如磁盘满),开启阶段会直接失败并打印"Trace recording failed to start because the file header cannot be written."(TraceRecord.cpp)。
录制过程中,每执行一条指令都会通过TraceExecuteRecord记录指令字节、寄存器上下文与内存访问差分数据(数据结构见 TraceRecord.h 中TraceRecordBitExec、TraceRecordByteWithExecTypeAndCounter、TraceRecordWordWithExecTypeAndCounter三种记录类型),并在开启时通过GuiOpenTraceFile(fileName)将文件同步打开到 Trace 视图(TraceRecord.cpp)。停止后该文件即可被 Trace 视图随时重新打开回放。
五、完整工作流:从开启、录制到停止落盘
5.1 第一步:开启追踪
使用 StartRunTrace.md 中描述的StartTraceRecording/StartRunTrace/opentrace命令:
StartTraceRecording C:\traces\sample.trace32注意:默认扩展名trace32或trace64不会自动追加,需在文件名中显式写出。文件也会立即在 Trace 视图中打开。开启录制本身不会驱动程序执行,需要配合追踪类命令才能真正录制指令:
- TraceIntoConditional.md:
TraceIntoConditional/ticnd,单步步入直到条件满足或达到最大步数; - TraceIntoIntoTraceRecord.md:
TraceIntoIntoTraceRecord/tiit,单步步入直到进入已记录的追踪覆盖范围,未指定最大步数时默认50000步; - 条件追踪的完整机制见 ConditionalTracing.md。
5.2 第二步:录制
在追踪执行期间,每条被单步或追踪到的指令都会立即出现在 Trace 视图中(见 Trace.md 说明);但若直接让程序自由运行(run),则不会记录这些指令——录制只覆盖"步进/追踪"路径。
5.3 第三步:停止录制
录制完成后执行:
StopTraceRecording(或StopRunTrace、tc)。日志区会输出Trace recording stopped.,文件句柄关闭、录制状态复位,之后可以随时用 Trace 视图的Open / Recent files重新打开该文件回放(回放时推荐同时调试对应的被调试程序,以便用其数据库中的标签渲染指令)。
5.4 实际调用路径与 GUI 联动
停止命令不仅在命令行可用,GUI 的Trace 视图 → Stop trace recording菜单、以及"关闭追踪文件"操作底层都通过DbgCmdExecDirect("StopTraceRecording")执行同一命令(见 TraceBrowser.cpp 与 TraceBrowser.cpp)。此外,当调试会话结束(StopDebug等)时,调试器清理流程也会主动调用TraceRecord.enableTraceRecording(false, nullptr)停止录制(debugger.cpp),避免遗留悬挂的文件句柄。
因此该命令的完整调用链可概括为:
命令行/GUI/脚本 → dbgcmdnew 注册的 cbDebugStopTraceRecording → TraceRecord.enableTraceRecording(false, nullptr) → CloseHandle(rtFile) + rtEnabled=false → CB_STOPTRACE 插件回调广播六、脚本与自动化场景
由于tc是 OllyScript 兼容别名,在 x64dbg 脚本中可以这样组织一个"录制-停止"片段(示意):
opentrace "C:\traces\run1.trace64" ticnd eax==0, 10000 tc即:开启追踪文件 → 条件步进录制至eax == 0或 10000 步 →tc停止并落盘。停止命令不设置任何结果变量,因此脚本中无需(也无法)通过$result判断其成败;如需判断录制是否真正生效,可结合日志输出或检查追踪文件是否生成。
七、小结与最佳实践
StopTraceRecording/StopRunTrace/tc虽是一个无参命令,但它串联了 x64dbg 运行追踪的完整生命周期:命令注册(x64dbg.cpp)、参数校验与委托(cmd-tracing.cpp)、底层文件关闭与状态复位(TraceRecord.cpp)、GUI 联动(TraceBrowser.cpp)与调试会话收尾(debugger.cpp)。实践要点:
- 停止前确保追踪文件路径显式带扩展名(
trace32/trace64不会自动补全); - 停止命令幂等且可在非调试状态调用,可放心放入脚本收尾;
- 追踪文件是
TRAC魔数 + JSON 头 + 指令记录的结构,停止后仍可反复打开回放(Trace.md); - 插件可通过
CB_STOPTRACE回调感知追踪结束,实现自动化后处理。
【免费下载链接】x64dbgAn open-source user mode debugger for Windows. Optimized for reverse engineering and malware analysis.项目地址: https://gitcode.com/gh_mirrors/x6/x64dbg
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考