
x64dbg 命令详解mov/set 变量赋值与#...#字节写入【免费下载链接】x64dbgAn open-source user mode debugger for Windows. Optimized for reverse engineering and malware analysis.项目地址: https://gitcode.com/gh_mirrors/x6/x64dbg导读mov别名set是 x64dbg 命令体系中最基础的赋值命令用于把任意表达式求值结果写入用户变量或以#11 22 33#的紧凑语法直接把原始字节序列写入目标进程内存。本文以官方命令参考 mov.md 为主线结合命令注册与核心实现源码讲清该命令的语法、变量创建机制、表达式求值过程以及 SSE 寄存器限制的替代方案读完即可在命令行、脚本与条件断点场景中熟练使用。命令概览mov 与 set 是同一个命令在 x64dbg 中mov与set并非两个独立命令而是同一回调的两个注册别名。命令注册位于 src/dbg/x64dbg.cpp#L134dbgcmdnew(mov,set, cbInstrMov, false); //mov a variable, arg1:dest,arg2:srcdbgcmdnew的第一个参数为逗号分隔的别名列表因此下面的写法完全等价mov myvar, 1234 set myvar, 1234命令回调cbInstrMov实现在 src/dbg/commands/cmd-general-purpose.cpp#L415-L471与inc、dec、add、sub、mul、and、or、xor、test、cmp等命令同属 general-purpose通用算术/逻辑指令分组。参数说明arg1目标变量名变量名可以是任意自定义名称可选的$前缀如$myvar与myvar等价当目标变量尚不存在时会被自动创建无需事先用var命令声明目标必须是一个可写的变量名不能是寄存器或立即数——源码中会先做isvar判定若arg1本身就能被求值为一个值即已是值而非变量名则报错Invalid dest。arg2要存储的值arg2是一个完整的表达式x64dbg 会通过表达式解析器求值后写入变量因此支持十进制 / 十六进制字面量mov myvar, 1234、mov myvar, 0x1000算术与逻辑表达式mov myvar, 12*3、mov myvar, eax 0xFF寄存器与标志位mov myvar, eax内存取值mov myvar, [00401000]其它变量的引用mov myvar, othervar除此之外arg2还有一种特殊形态——以#包裹的十六进制字节序列此时行为完全不同不是赋值而是把字节写入进程内存见下文专节。结果变量该命令不设置任何结果变量如$result等。这一点与cmp、test这类会写$_EZ_FLAG/$_BS_FLAG的指令不同若脚本需要知道赋值是否成功只能通过后续读取该变量来验证。源码视角赋值与自动建变量的完整链路cbInstrMov的求值主路径cmd-general-purpose.cpp#L446-L470分四步解析源值调用valfromstring(srcText, set_value)把arg2交给表达式解析器求值。valfromstring内部通过ExpressionParser完成计算见 src/dbg/value.cpp#L1852-L1867失败时报Invalid src判定目标是否已是变量valfromstring(argv[1], temp, true, true, 0, isvar, 0)以baseonly模式解析arg1并取得isvar标记若还不是再调用vargettype复核一次因为目标可能尚不存在此处故意不做返回值检查写入或创建若目标已是变量调用valsetscalar(argv[1], set_value, true)更新其标量值若写入失败或不是变量则进入第 4 步自动创建先检查valrequiresbuffer目标是否是需要缓冲区而非标量排除把立即数当变量名的非法目标后调用varnew(argv[1], set_value, VAR_USER)以VAR_USER用户变量类型创建新变量并赋值。变量系统定义在 src/dbg/variable.h共有四种类型类型枚举值说明VAR_SYSTEM1系统变量如$pid等VAR_USER2用户变量mov自动创建的就是此类VAR_READONLY3只读变量mov无法覆盖VAR_HIDDEN4隐藏变量不出现在变量列表中也就是说mov本质上是valfromstring求值 变量表写入/新建的组合封装变量在内部以VAR_VALUEduint标量或字符串/数据缓冲存储参考 variable.h#L22-L39。如果确实需要显式声明变量例如想指定初始值或使用$前缀变量可参考 var/varnew但官方建议常规场景直接用myvar 42或mov即可。特殊模式mov addr, #11 22 33#写入内存当arg2以#开头且以#结尾时cmd-general-purpose.cpp#L420-L445mov切换为内存字节写入模式mov 00401000, #11 22 33#执行流程如下剥离首尾#得到内部文本调用StringUtils::FromCompressedHex解析为字节序列——支持空格分隔的写法#11 22 33#也支持无空格的紧凑写法#112233#解析失败报Invalid hex string用valfromstring(argv[1], dest)解析目标地址并调用MemIsValidReadPtr(dest)校验该地址可读否则报Invalid destination调用MemPatch(dest, data.data(), data.size())把字节写入目标进程内存失败报Failed to write to %p成功后调用GuiUpdateAllViews()刷新反汇编、内存转储等所有视图让改动立即在 GUI 上可见。因此mov的内存写入模式是对调试目标进程的直接补丁操作与补丁相关的持久化另见 patches 机制并非写调试器自身内存。这一特性非常适合在调试会话中临时修改目标进程数据如改写指令字节、填充缓冲区随后无需Fill/memcpy等命令即可完成小段写入。限制与替代方案SSE/AVX 寄存器怎么办官方文档明确mov不支持 SSE 寄存器xmm0~xmm15。其原因在注册代码中也能看到——SSE/AVX 相关的移动操作由独立命令承担src/dbg/x64dbg.cpp#L136-L143dbgcmdnew(movdqu,movups,movupd, cbInstrMovdqu, true); //move from and to XMM register dbgcmdnew(vmovups,vmovupd,vmovdqu, cbInstrVmovdqu, true); //move from and to YMM/ZMM register if(detectAVX512()) { dbgcmdnew(kmovq, cbInstrKmovq, true); //move qword from and to K0-K7 register dbgcmdnew(kmovd, cbInstrKmovd, true); //move dword from and to K0-K7 register }对应关系如下目标寄存器宽度应使用的命令说明XMM16 字节movdqu/movups/movupd支持xmmN, [addr]、[addr], xmmN、xmmN, xmmM双向移动YMM / ZMM32/64 字节vmovdqu支持ymm/zmm与内存/寄存器互拷K 掩码寄存器AVX-512kmovq/kmovd仅在检测到 AVX-512 时注册可用注意movdqu/vmovdqu的内存操作数只支持[addr]方括号语法且操作数宽度固定为 16/32/64 字节与普通mov的标量语义不同。若要在 XMM 寄存器与普通变量之间搬运标量更常见的做法是直接通过表达式读取寄存器值mov myvar, xmm0不支持此时可借助movdqu写入内存后再用mov myvar, [addr]读取。实战示例汇总以下示例均可在 x64dbg 命令框或脚本中直接执行mov myvar, 1234 ; 创建用户变量 myvar 并赋十进制 1234 set $myvar, 0x1000 ; set 是 mov 的别名$ 前缀可选 mov myvar, eax ; 把寄存器 eax 当前值存入变量 mov myvar, [00401000] ; 把地址 00401000 处的指针宽度数据读入变量 mov myvar, 12*3 ; 表达式求值结果为 7 mov myvar, myvar 1 ; 自增也等价于 inc myvar mov 00401000, #90 90# ; 向进程内存写入两个 NOP 字节0x90 mov 00401000, #9090# ; 紧凑写法效果同上 mov 00401000, #E9 00 00 00 00# ; 写入 5 字节 JMP 指令几点注意事项写入内存模式要求目标地址必须位于已提交且可读的内存页MemIsValidReadPtr校验对无效地址会直接报错字节序列按原样写入不做大小端转换mov只写标量值涉及浮点 XMM/YMM 数据的移动请使用 movdqu / vmovdqu表达式求值的完整语法操作符、函数、内存访问等可参考 Expressions 与 Expression-functionsvalfromstring的底层解析入口见 src/dbg/value.cpp#L1852。小结mov/set是 x64dbg 脚本与命令行交互中最高频的赋值原语普通模式下它是表达式求值 变量自动创建的快捷方式#...#模式下则是面向调试目标进程的字节级补丁工具。理解其背后的valfromstring → valsetscalar/varnew调用链与VAR_USER变量语义能帮助你在编写条件断点日志、自定义脚本时正确规划变量生命周期遇到 SSE/AVX 寄存器操作时则应及时切换到movdqu/vmovdqu系列命令。【免费下载链接】x64dbgAn open-source user mode debugger for Windows. Optimized for reverse engineering and malware analysis.项目地址: https://gitcode.com/gh_mirrors/x6/x64dbg创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考