
x64dbg 插件开发指南使用 DbgValSetScalar 按名称写入寄存器、变量与标志【免费下载链接】x64dbgAn open-source user mode debugger for Windows. Optimized for reverse engineering and malware analysis.项目地址: https://gitcode.com/gh_mirrors/x6/x64dbg导读DbgValSetScalar是 x64dbg 调试器桥接 APIbridge API中用于按名称写入标量值的核心函数它接收一个字符串形式的名称如eax、cip、_z或任意用户变量名和一个duint标量值将值写入对应的寄存器、变量、标志或内存位置并同步刷新 GUI 视图。本指南以官方文档 DbgValSetScalar.md 为主体结合 bridgemain.cpp 与 value.cpp 的源码实现完整讲解函数签名、参数语义、返回值、底层调用链、可写目标类型与实战示例帮助插件开发者安全、高效地修改调试会话中的任意可命名值。一、函数签名与基本语义1.1 官方声明bool DbgValSetScalar(const char* string, duint value);string要设置的目标名称使用 UTF-8 编码。名称可以是通用寄存器名、标志位名、FPU 标量字段名、内存位置表达式或用户变量名。value要写入的标量值类型为duint即duint为地址宽度整数32 位调试器下为 32 位、64 位调试器下为 64 位。返回值写入成功返回true失败返回false。官方示例DbgValSetScalar(eax, 1); // 将 eax 寄存器置为 11.2 历史命名DbgValToString文档明确说明该函数以前叫DbgValToString。源码中的兼容层印证了这一历史在 bridgemain.cpp 中保留了一个仅为二进制兼容而存在的导出函数// Deprecated api, only provided for binary compatibility extern C __declspec(dllexport) bool DbgValToString(const char* string, duint value) { return DbgValSetScalar(string, value); }因此旧插件若仍调用DbgValToString也不会链接失败但新代码应一律使用DbgValSetScalar。二、源码级调用链从桥接到核心实现DbgValSetScalar并不是在桥接层直接完成写入而是经过一条清晰的分层调用链。以 bridgemain.cpp 为起点BRIDGE_IMPEXP bool DbgValSetScalar(const char* string, duint value) { return _dbg_valsetscalar(string, value); }桥接层将请求转发给调试器核心dbg 模块的导出函数_dbg_valsetscalar见 _exports.cppextern C DLL_EXPORT bool _dbg_valsetscalar(const char* string, duint value) { return valsetscalar(string, value, true); }其中第三个参数silent true表示成功/失败时不在日志控制台输出消息。真正的业务逻辑位于 value.cppbool valsetscalar(const char* string, duint value, bool silent) { return valsetinternal(string, value, sizeof(value), ValSetMode::Scalar, silent); }也就是说标量设置最终统一收敛到内部函数valsetinternal它同时服务两种模式ValSetMode::Scalar写标量本函数ValSetMode::Buffer写原始字节缓冲区对应DbgValSetBuffer见 value.cpp。对应地读取方向由DbgValFromString完成声明位于 bridgemain.h实现在 bridgemain.cpp其核心为_dbg_valfromstring见 _exports.cpp。三者在头文件中的声明紧邻排列bridgemain.h共同构成按名称读写值的完整 API 家族BRIDGE_IMPEXP duint DbgValFromString(const char* string); BRIDGE_IMPEXP bool DbgValSetBuffer(const char* string, const void* data, size_t size); // Previously called DbgValToString. BRIDGE_IMPEXP bool DbgValSetScalar(const char* string, duint value);调用链可概括为DbgValSetScalar (bridge) → _dbg_valsetscalar (dbg 导出层silenttrue) → valsetscalar(string, value, silent) → valsetinternal(string, value, sizeof(value), ValSetMode::Scalar, silent)三、valsetinternal可写目标的分类处理valsetinternalvalue.cpp根据string名称的首字符与格式将目标分为四类分别处理这是理解DbgValSetScalar能力边界的关键。3.1 内存位置[...]与n:[...]语法当名称形如[addr]、byte:[addr]、word:[addr]、dword:[addr]64 位下还有qword:[addr]或以字节数:[前缀开头如4:[addr]或带段前缀fs:[...]/gs:[...]时函数进入内存写入分支要求当前处于调试状态DbgIsDebugging()否则返回false并提示 Not debugging标量模式下默认写sizeof(duint)字节但显式大小前缀会收紧写入宽度见 value.cpp段前缀在 x86/x64 下分别按GetTEBLocation(hActiveThread)计算 TEB 段基址见 value.cpp最终通过MemPatch写入目标地址并调用GuiUpdateAllViews()与GuiUpdatePatches()刷新界面见 value.cpp。3.2 通用寄存器isregister(string)对于寄存器名称如eax、cip、csp标量模式下要求数据能解释为标量getscalarfromdata检查size sizeof(duint)并同样要求处于调试状态随后调用setregister(string, value)写寄存器上下文。写入完成后还会针对特殊寄存器做定向刷新value.cpp名称含ip如cip取回新的cip并执行dbgtraceexecute(cip)DebugUpdateGuiAsync(cip, false)同步更新反汇编与寄存器视图名称含sp如csp调用DebugUpdateStack更新栈视图并刷新寄存器视图其他寄存器调用GuiUpdateAllViews()全量刷新。3.3 标志位与 FPU 标量字段_前缀_ 标志名如_z、_c、_zfisflag判定后通过setflag设置标志位非零值置位、零值清零value.cpp_ FPU 标量字段如_MxCsr的 RC 字段、_x87TW_*标签字、_x87SW_*状态字等进入setfpuscalar分支value.cpp按字段语义做位级修改。需要特别注意的是若字段属于需要完整缓冲区的寄存器如_XMM0、_YMM0、_ZMM0、_MM0、_K0、_x87r0/_st0valrequiresbuffer会要求调用方改用 Buffer 模式标量模式下直接返回falsevalue.cpp。3.4 用户变量与其他varset 兜底若名称不属于以上任何类别函数会先触发CB_VALTOSTRING插件回调允许第三方插件自定义写入逻辑若回调未处理则走varset(string, value, false)写入用户变量表value.cpp。x64dbg 的$前缀伪变量如$result、$pid与用户脚本变量均由这条路径管理。四、与 DbgValSetBuffer 的分工标量 vs 缓冲区DbgValSetScalar与DbgValSetBuffer服务于不同的数据宽度需求函数数据形态典型目标约束DbgValSetScalar单个duint标量通用寄存器、标志、标量 FPU 字段、内存、变量缓冲区目标XMM/YMM/ZMM/MM/K/x87r会被拒绝DbgValSetBuffer任意字节缓冲区XMM/YMM/ZMM/MM/K 掩码寄存器、x87r 80 位寄存器显式大小前缀必须与缓冲区大小一致value.cpp仓库测试 issue3803/plugin.cpp 精确验证了这条边界if(!_plugin_testassert(!DbgValSetScalar(_K0, 5), DbgValSetScalar should reject raw K registers)) return false; if(!_plugin_testassert(!DbgValSetScalar(_ZMM0, 5), DbgValSetScalar should reject raw ZMM registers)) return false; ULONGLONG opmask 0x0123456789ABCDEFULL; if(!_plugin_testassert(!DbgValSetBuffer(_K0, opmask, sizeof(DWORD)), DbgValSetBuffer should require the full K register size)) return false; if(!_plugin_testassert(DbgValSetBuffer(_K0, opmask, sizeof(opmask)), DbgValSetBuffer failed for _K0)) return false;即用标量模式写 K/ZMM 这类宽寄存器必然失败必须用DbgValSetBuffer并按完整寄存器大小传入缓冲区。该测试还进一步验证了标量表达式赋值_K05、mov _K0, 5等命令同样被正确拒绝。五、GUI 侧的真实调用场景DbgValSetScalar在 GUI 中有着广泛的直接调用可作为理解其典型用法的活样本寄存器编辑寄存器视图双击修改时将编辑框中的值写入对应寄存器见 CPURegistersView.cpp栈指针修正栈视图将当前栈指针csp写回见 CPUStack.cpp监视Watch表达式写入监视窗口编辑表达式值见 WatchView.cpp引用导航索引反汇编、Dump 与引用视图用$__disasm_refindex/$__dump_refindex这类$伪变量记录当前位置见 CPUDisassembly.cpp、CPUDump.cpp 与 ReferenceView.cppTrace 寄存器快照Trace 记录视图恢复寄存器值见 TraceRegisters.cpp。可见该函数既承担用户直接改寄存器的交互入口也承担 GUI 内部维护脚本变量的基础设施职责。六、命令与脚本侧的等价入口插件调用DbgValSetScalar等价于在命令行执行赋值表达式。x64dbg 的命令层大量复用valsetscalar赋值命令变量名值的解析最终调用valsetscalarcmd-general-purpose.cpp表达式解析器在写目标变量时调用valsetscalarexpressionparser.cpp表达式函数内部也会使用valsetscalarexprfunc.cpp。例如官方示例DbgValSetScalar(eax, 1)的效果与命令行eax1完全等价而_K0这类宽寄存器在两种入口下都会被拒绝行为一致。七、使用注意事项与最佳实践调试状态检查写寄存器、标志和内存位置前必须处于调试会话中已附加或已启动目标否则返回false。插件应在调用前通过DbgIsDebugging()自行判断避免误报。名称编码string必须为 UTF-8 编码GUI 侧调用时需将QString转换为 UTF-8如toUtf8().constData()这一点在寄存器视图等实现中随处可见。宽寄存器必须走 Buffer 模式XMM/YMM/ZMM/MM/K 掩码寄存器与 80 位 x87r 寄存器不接受标量写入请使用DbgValSetBuffer并传入与寄存器等长的缓冲区。返回值校验写入失败如目标不存在、处于错误状态、名称不合法返回false切勿忽略返回值参考 WatchView.cpp 的做法失败时给出用户提示。内存写入会留下补丁痕迹通过[...]语法写内存会走MemPatch同时刷新补丁对话框插件如需临时改动内存应注意这一点。优先使用常量名而非硬编码地址配合DbgValFromString(cip)、mod.main()等表达式读取目标地址后再写入代码更具可移植性。八、关联 API 与延伸阅读DbgValFromString表达式求值与DbgValSetScalar构成读写对DbgValSetBuffer缓冲区写入用于宽寄存器表达式语法string参数所支持的完整表达式与名称语法桥接层声明bridgemain.h核心实现value.cpp导出层_exports.cpp边界行为测试issue3803/plugin.cpp。总结而言DbgValSetScalar是 x64dbg 插件与脚本生态中按名称写标量值的统一入口理解其四类目标分发逻辑与标量/缓冲区的边界即可安全地修改寄存器、标志、内存与变量并与命令行和 GUI 交互行为保持一致。【免费下载链接】x64dbgAn open-source user mode debugger for Windows. Optimized for reverse engineering and malware analysis.项目地址: https://gitcode.com/gh_mirrors/x6/x64dbg创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考