x64dbg 异常断点命令绑定:SetExceptionBreakpointCommand 完整指南
x64dbg 异常断点命令绑定SetExceptionBreakpointCommand 完整指南【免费下载链接】x64dbgAn open-source user mode debugger for Windows. Optimized for reverse engineering and malware analysis.项目地址: https://gitcode.com/gh_mirrors/x6/x64dbg当异常断点被命中时调试器默认只是暂停下来等待人工处理。而SetExceptionBreakpointCommand命令允许你为异常断点绑定一段自动执行的命令把断点命中变成自动化处理流程的触发点。本文基于 x64dbg 开源仓库中的官方命令文档 SetExceptionBreakpointCommand.md结合src/dbg/commands/cmd-conditional-breakpoint-control.cpp与src/dbg/breakpoint.cpp等核心源码完整讲解该命令的参数语义、执行时机、源码实现原理及配套命令体系帮助你用一条命令实现异常处理自动化。一、命令概览一条命令解决异常断点自动化SetExceptionBreakpointCommand是 x64dbg 条件断点控制conditional breakpoint control命令家族中的一员用于设置异常断点命中时要执行的命令。它和普通的SetBreakpointCommand针对普通断点、SetHardwareBreakpointCommand针对硬件断点等命令共用同一套实现框架只是断点类型锁定为异常断点BPEXCEPTION。从官方文档的语义定义看其核心行为是Sets the command to execute when an exception breakpoint is hit. If the command condition is not specified, it will be executed when the debugger breaks, otherwise it will be executed when the condition is satisfied.即设置异常断点命中时执行的命令若未指定命令条件command condition则在调试器因该断点中断时执行若指定了命令条件则仅在条件满足时执行。这句话揭示了该命令与命令条件SetExceptionBreakpointCommandCondition之间的协作关系——命令条件负责要不要执行命令本身负责执行什么。二、参数详解arg1 与 arg2根据官方文档该命令接受两个参数参数名称含义是否必填arg1异常断点标识异常断点的名称、异常名或异常代码必填[arg2]命令文本命中时要执行的 x64dbg 命令不指定时为空字符串选填arg1如何定位一个异常断点x64dbg 的异常断点可以通过三种方式之一来引用断点名称name如果之前用SetExceptionBreakpointName为断点设置过自定义名称可以直接用该名称引用异常名exception name如ACCESS_VIOLATION、INT3、SINGLE_STEP等系统异常名称异常代码exception code如0xC0000005访问违例、0x80000003断点异常、0x80000004单步异常等。arg2命令文本[arg2]是要自动执行的命令字符串。它是可选参数——如果省略则该断点绑定的命令会被清空置为空字符串相当于取消此前的绑定。这一点从源码中可以明确验证详见第四节。三、执行时机无条件执行与条件执行这是理解该命令的关键。命令的实际执行与否取决于是否额外设置了命令条件未设置命令条件只要异常断点命中导致调试器中断break绑定的命令就会执行已设置命令条件只有在条件表达式求值为真时命令才会执行。命令条件的设置通过配套命令SetExceptionBreakpointCommandCondition完成其官方文档 SetExceptionBreakpointCommandCondition.md 的定义是Sets the command condition of an exception breakpoint. When command condition is not specified, the command will be executed when the debugger would break, otherwise it will be executed when the condition is satisfied.也就是说SetExceptionBreakpointCommand负责命中时做什么SetExceptionBreakpointCommandCondition负责命中时什么条件下才做。两者配合可以实现异常断点命中后仅当某寄存器满足特定值时执行命令这类精准的自动化逻辑。四、使用示例以下命令均在 x64dbg 的命令栏或脚本中直接输入。示例 1为访问违例异常断点绑定命令SetExceptionBreakpointCommand ACCESS_VIOLATION, log \hit access violation at {cip}\当ACCESS_VIOLATION异常断点命中时向日志输出当前指令指针{cip}为 x64dbg 的格式化占位符。注意命令行参数中含空格或引号时整个命令文本需要用双引号包裹。示例 2按异常代码绑定SetExceptionBreakpointCommand 0xC0000005, erun命中0xC0000005异常时自动执行erun在异常处继续运行可实现特定异常的自动跳过处理。示例 3清除已绑定的命令SetExceptionBreakpointCommand ACCESS_VIOLATION省略arg2即为清空该断点绑定的命令恢复为仅中断、不自动执行任何命令的默认行为。示例 4与命令条件组合使用SetExceptionBreakpointCommandCondition 0xC0000005, eax1 SetExceptionBreakpointCommand 0xC0000005, log \eax is 1, dumping...\此时0xC0000005断点命中后仅当eax 1时才执行日志命令条件不满足时调试器正常中断、不执行命令。示例 5脚本中动态绑定在 x64dbg 的脚本.txt中同样可以直接使用该命令SetExceptionBreakpointCommand INT3, log \int3 hit\五、源码级实现解析5.1 命令注册命令的注册位于 src/dbg/x64dbg.cpp在调试器初始化时通过dbgcmdnew挂载dbgcmdnew(SetExceptionBreakpointCommand, cbDebugSetBPXExceptionCommand, true); //set breakpoint command on hit dbgcmdnew(SetExceptionBreakpointCommandCondition, cbDebugSetBPXExceptionCommandCondition, true); //set breakpoint commandCondition第三个参数true表示这是一个调试状态命令仅在调试会话中有效。5.2 命令处理入口命令处理函数定义于 src/dbg/commands/cmd-conditional-breakpoint-control.cppbool cbDebugSetBPXExceptionCommand(int argc, char* argv[]) { return cbDebugSetBPXCommandCommon(BPEXCEPTION, argc, argv); } bool cbDebugSetBPXExceptionCommandCondition(int argc, char* argv[]) { return cbDebugSetBPXCommandConditionCommon(BPEXCEPTION, argc, argv); }这里将断点类型锁定为BPEXCEPTION。断点类型枚举定义在 src/dbg/breakpoint.henum BP_TYPE { BPNORMAL 0, BPHARDWARE 1, BPMEMORY 2, BPDLL 3, BPEXCEPTION 4 };5.3 公共实现参数解析与断点查找cbDebugSetBPXCommandCommon与cbDebugSetBPXCommandConditionCommon分别调用BpSetCommandText和BpSetCommandCondition两者最终都落到cbDebugSetBPXTextCommon这个公共函数cmd-conditional-breakpoint-control.cppstatic bool cbDebugSetBPXTextCommon(BP_TYPE Type, int argc, char* argv[], const String description, const std::functionbool(duint, BP_TYPE, const char*) setFunction) { BREAKPOINT bp; if(IsArgumentsLessThan(argc, 2)) return false; const char* value ; if(argc 2) value argv[2]; if(!BpGetAny(Type, argv[1], bp)) { dprintf(QT_TRANSLATE_NOOP(DBG, No such breakpoint \%s\\n), argv[1]); return false; } if(!setFunction(bp.addr, Type, value)) { dprintf(QT_TRANSLATE_NOOP(DBG, Cant set %s on breakpoint \%s\\n), description.c_str(), argv[1]); return false; } DebugUpdateBreakpointsViewAsync(); return true; }这段代码清晰地揭示了命令的完整执行流程参数校验argc 2直接返回false保证arg1必填默认值value初始化为空字符串仅当argc 2即提供了arg2时才取argv[2]——这正是省略 arg2 即清空命令的源码依据断点查找通过BpGetAny(Type, argv[1], bp)按名称/异常名/异常代码定位断点BpGetAny声明于 src/dbg/breakpoint.h。若找不到打印No such breakpoint并失败返回写入断点属性调用setFunction(bp.addr, Type, value)。对命令绑定而言即BpSetCommandTextbreakpoint.cpp它把命令文本写入BREAKPOINT结构体的command字段命令条件则通过BpSetCommandConditionbreakpoint.cpp写入commandCondition字段界面刷新成功后调用DebugUpdateBreakpointsViewAsync()异步刷新断点视图使 GUI 中显示的命令文本与命令条件同步更新。5.4 断点数据结构BREAKPOINT结构体breakpoint.h集中保存了断点的全部行为属性其中与本文相关的字段包括std::string name; // breakpoint name std::string breakCondition; // condition to stop. If true, debugger halts. std::string logText; // text to log. std::string logCondition; // condition to log // ...command / commandCondition 等字段异常断点的命令文本、命令条件、日志文本、日志条件、停止条件均存储于该结构体中BpSetCommandText/BpSetCommandCondition负责写入调试器命中断点时再读取并执行——这正是断点命中时执行命令的底层数据基础。六、GUI 联动断点视图中的命令编辑该命令不仅能在命令行使用x64dbg 的 GUI 断点管理界面在编辑断点命令时底层也是通过这条命令生效的。源码 src/gui/Src/Utils/Breakpoints.cpp 展示了 GUI 与命令的映射exec(QString(SetExceptionBreakpointCommand %1, \%2\).arg(addrText).arg(DbgCmdEscape(bp.commandText))); exec(QString(SetExceptionBreakpointCommandCondition %1, \%2\).arg(addrText).arg(DbgCmdEscape(bp.commandCondition)));同样的模式也出现在断点视图组件 src/gui/Src/Gui/BreakpointsView.cpp 中。可以看到GUI 通过DbgCmdEscape对命令文本做转义后再拼装成SetExceptionBreakpointCommand 标识, 命令的形式交给调试核心执行。因此在断点视图里编辑异常断点的命令与在命令行手工输入最终走的是同一条代码路径。七、命令条件体系定位你的命令在家族中的位置SetExceptionBreakpointCommand属于 x64dbg 为异常断点提供的条件控制命令家族。同一目录下还提供了与之配套的完整命令集见 docs/commands/conditional-breakpoint-control类别命令作用命令绑定SetExceptionBreakpointCommand设置命中时执行的命令命令条件SetExceptionBreakpointCommandCondition设置命令执行的条件停止条件SetExceptionBreakpointCondition设置是否中断停止的条件日志SetExceptionBreakpointLog/SetExceptionBreakpointLogCondition/SetExceptionBreakpointLogFile设置命中时的日志文本、日志条件与日志文件名称SetExceptionBreakpointName设置断点名称用于被 arg1 引用行为SetExceptionBreakpointFastResume/SetExceptionBreakpointSingleshoot/SetExceptionBreakpointSilent快速恢复、一次性断点、静默模式计数GetExceptionBreakpointHitCount/ResetExceptionBreakpointHitCount获取/重置命中次数它们的核心差异在于命中后做什么的不同维度是否中断SetExceptionBreakpointCondition、是否输出日志SetExceptionBreakpointLog系列、是否执行命令SetExceptionBreakpointCommand系列。其中命令与日志最典型的区别是日志文本只是写入日志窗口的静态文本而命令文本会被 x64dbg 的命令解析器当作新命令执行因此可以做erun、log、条件跳转甚至调用脚本等更复杂的操作。八、注意事项与最佳实践断点必须已存在arg1引用的异常断点必须已经通过SetExceptionBPX等命令创建否则命令会输出No such breakpoint并失败命令中的引号转义命令文本若包含逗号、引号或空格务必用双引号整体包裹GUI 路径会自动做DbgCmdEscape转义手工输入时需自行注意条件与命令的组合语义SetExceptionBreakpointCommandCondition控制的是命令是否执行而SetExceptionBreakpointCondition控制的是是否中断两者相互独立可分别设置以满足不中断但执行命令或中断但不执行命令等不同需求空命令即清除省略arg2会清除已绑定的命令恢复默认行为这一点在自动化脚本动态切换断点行为时非常实用命令不设置结果变量官方文档明确注明该命令不设置任何结果变量This command does not set any result variables因此在脚本中不要依赖其返回值做后续分支判断。参考资料官方命令文档SetExceptionBreakpointCommand.md、SetExceptionBreakpointCommandCondition.md命令实现src/dbg/commands/cmd-conditional-breakpoint-control.cpp、src/dbg/commands/cmd-conditional-breakpoint-control.cpp命令注册src/dbg/x64dbg.cpp断点类型与数据结构src/dbg/breakpoint.h断点属性写入src/dbg/breakpoint.cpp、src/dbg/breakpoint.cppGUI 联动src/gui/Src/Utils/Breakpoints.cpp、src/gui/Src/Gui/BreakpointsView.cpp【免费下载链接】x64dbgAn open-source user mode debugger for Windows. Optimized for reverse engineering and malware analysis.项目地址: https://gitcode.com/gh_mirrors/x6/x64dbg创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考