news 2026/9/19 21:31:17

x64dbg 注释命令完整指南:commentset/cmt/cmtset 的语法、底层实现与实战用法

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
x64dbg 注释命令完整指南:commentset/cmt/cmtset 的语法、底层实现与实战用法

x64dbg 注释命令完整指南:commentset/cmt/cmtset 的语法、底层实现与实战用法

【免费下载链接】x64dbgAn open-source user mode debugger for Windows. Optimized for reverse engineering and malware analysis.项目地址: https://gitcode.com/gh_mirrors/x6/x64dbg

导读

commentset(别名cmtcmtset)是 x64dbg 用户数据库中用于"在指定地址上设置/编辑注释"的核心命令。注释是逆向工程中标记函数入口、解密循环、可疑调用点最常用的持久化标注手段,配合标签(label)、书签(bookmark)共同构成 x64dbg 的"用户数据库"体系。读完本文,你将掌握该命令的完整语法、地址表达式写法、底层存储机制(含 manual/auto 注释区分)、关联命令家族(删除/列出/清空)以及脚本 API 与测试用例的验证方式。

命令概览与语法

该命令在 x64dbg 的命令注册表中定义如下(见 src/dbg/x64dbg.cpp):

dbgcmdnew("commentset,cmt,cmtset", cbInstrCommentSet, true); //set/edit comment

命令名commentset,同时支持两个短别名cmtcmtset,三者完全等价。

参数(arguments)

参数含义是否必填
arg1要设置注释的地址(最好位于模块内部)必填
arg2注释文本内容必填

结果(result):该命令不设置任何结果变量,即执行后$result保持不变。

参数详解与实战示例

arg1:地址表达式

arg1并不是一个裸的十六进制字面量,它支持 x64dbg 完整的表达式求值系统。在命令处理器中,参数通过valfromstring(argv[1], &addr, false)解析(见 src/dbg/commands/cmd-user-database.cpp),这意味着你可以传入:

  • 直接地址:commentset 00401000, entry point
  • 表达式:commentset eip, current instruction
  • 符号/标签:commentset MessageBoxW, API hook target
  • 模块内地址表达式:commentset ntdll:7C921000, LdrLoadDll call

推荐将地址定位在模块内部,这样注释会随模块基址重定位逻辑正确保存与恢复;跨模块的裸地址注释在下次加载、基址变化时可能失效。

arg2:注释文本与两个隐藏规则

arg2是注释文本,底层实现(见 src/dbg/comment.cpp)对文本有两个关键约束:

  1. 空字符串即删除:如果传入的文本以\0开头(空文本),CommentSet不会写入注释,而是直接调用CommentDelete删除该地址的已有注释。这与执行commentdel的效果一致。
  2. 长度上限 512 字节:文本长度必须小于MAX_COMMENT_SIZE - 1,即最多 511 个有效字符。MAX_COMMENT_SIZE在 src/bridge/bridgemain.h 中定义为512。超长文本会被拒绝,命令返回 "Error setting comment"。
  3. 首字符保留:以 ASCII\1(0x01)开头的文本被禁止,因为该前缀在内部用于标记"自动注释"(见下文 manual/auto 区分),用户文本不得占用。

另外注意,命令行的参数分割以空格为界,含空格的注释文本建议用双引号包裹:commentset 00401000, "decrypt loop start"

底层实现解析:从命令到存储

命令分发链路

整条调用链为:

命令行输入 commentset → cbInstrCommentSet(命令处理器) → valfromstring 解析地址表达式 → CommentSet(addr, text, true)(注释核心逻辑) → GuiUpdateAllViews()(刷新所有视图)

cbInstrCommentSet的实现位于 src/dbg/commands/cmd-user-database.cpp:先检查参数数量(少于 3 个直接失败),再解析地址,成功后调用CommentSet并刷新 GUI 视图,失败则输出 "Error setting comment"。

注意第三个参数传的是true,即Manual标志——通过命令行设置的注释都是手动注释(manual)

CommentSet 的核心逻辑

src/dbg/comment.cpp 中的CommentSet负责将注释写入内存中的Comments哈希表(AddrInfoHashMap),并为每条记录填充地址、模块哈希、manual 标志与文本:

bool CommentSet(duint Address, const char* Text, bool Manual) { if(!Text || Text[0] == '\1' || strlen(Text) >= MAX_COMMENT_SIZE - 1) return false; if(Text[0] == '\0') { CommentDelete(Address); return true; } COMMENTSINFO comment; if(!comments.PrepareValue(comment, Address, Manual)) return false; comment.text = Text; return comments.Add(comment); }

每条注释通过Comments::VaKey(Address)以虚拟地址为键进行索引,COMMENTSINFO结构(见 src/dbg/comment.h)包含继承自AddrInfo的模块哈希、manual 标志,以及注释文本text

manual 与 auto 注释的区分

x64dbg 的注释体系分为两类:

  • 手动注释(manual):由commentset命令或 GUI 右键菜单创建,持久保存并显示在反汇编视图中;
  • 自动注释(auto):由引擎/插件内部生成,例如cmd-undocumented.cpp中为RUNTIME_FUNCTION生成的自动标注(见 src/dbg/commands/cmd-undocumented.cpp),此时CommentSetManual参数传false

两者的读取差异体现在CommentGet中(src/dbg/comment.cpp):手动注释原样返回,自动注释则会被加上\1前缀,便于上层区分来源。在commentlist中也可以通过额外参数1选择是否同时列出自动注释。

持久化与数据库回调

注释属于"用户数据库"的一部分,随数据库保存/加载:

  • 序列化键名为"comments"(见 src/dbg/comment.cpp 的jsonKey()),通过CommentCacheSave/CommentCacheLoaddbsave/dbload时写入或读回;
  • 每条记录写入数据库操作时标记为DbItemTypeComment(src/dbg/comment.cpp),因此注释的增删会触发数据库回调(database callbacks),供插件与自动化测试监听。

关联命令家族

commentset不是孤立命令,它与另外三个注释命令共同构成完整的注释管理工具集(均在 src/dbg/x64dbg.cpp 注册):

命令别名功能
commentsetcmtcmtset设置/编辑注释
commentdelcmtccmtdel删除指定地址的注释
commentlist在 Reference View 中列出注释($result返回条数)
commentclear清空所有模块的全部注释

其中commentlist的结果可通过脚本配合ref.addr(i)ref.count()等表达式函数遍历(见 commentlist 文档 与 表达式函数)。

在 GUI 侧,反汇编视图(CPU 视图)会在指令行右侧直接显示注释文本,且手动注释会随数据库持久化;设置注释后GuiUpdateAllViews()会即时刷新所有相关视图。

脚本与插件 API

除命令行外,脚本与插件可以通过导出 API 完成相同操作:

  • 脚本 API:Script::Comment::Set(addr, text, manual)Script::Comment::Get(addr, text)Script::Comment::Delete(addr),实现在 src/dbg/_scriptapi_comment.cpp;
  • Set还提供基于CommentInfo的重载:传入模块名与 RVA,自动换算为模块基址 + RVA 的绝对地址后再写入,适合插件按"模块 + 偏移"的稳定坐标管理注释。

测试用例验证

仓库中的数据库回调测试对注释的写入/删除做了端到端验证,见 src/tests/database_callbacks/test.comment-single.txt:

init tests/database_callbacks.exe _c1 = database_callbacks:VariableTarget commentset _c1, test assertlastop mod.hash(mod.base(_c1)), (_c1-mod.base(_c1)), c, a, 0, test commentdel _c1 assertlastop mod.hash(mod.base(_c1)), (_c1-mod.base(_c1)), c, r, 0

该用例揭示了两个实用要点:

  1. 地址可以传标签/符号database_callbacks:VariableTarget),印证了 arg1 的表达式能力;
  2. 注释写入与删除都会触发数据库回调assertlastop校验操作码a/r),回调参数中携带模块哈希、RVA 与注释文本——这正是插件监听用户数据库变更的标准通道。

实践建议与注意事项

  • 用模块内地址:将注释设置在模块内部,配合dbsave保存数据库后,下次调试同一模块时注释可正确恢复;
  • 配合标签使用:先labelset命名关键位置,再用commentset补充说明,可读性最佳;
  • 注意文本长度:单条注释不要超过 511 字节,超长文本会被静默拒绝并报错;
  • 区分自动注释commentlist默认只列手动注释,排查异常时可追加参数查看自动注释,避免与引擎生成的RUNTIME_FUNCTION等自动标注混淆;
  • 空文本即删除commentset addr, ""commentdel addr等价,可用于脚本中条件化地清理注释。

相关命令的完整文档可在 user-database 命令索引 中查阅,用户数据库的批量管理(保存/加载/清空)参见 dbsave、dbload 与 dbclear。

【免费下载链接】x64dbgAn open-source user mode debugger for Windows. Optimized for reverse engineering and malware analysis.项目地址: https://gitcode.com/gh_mirrors/x6/x64dbg

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/19 21:31:04

Gatsby 升级指南:语义化版本、依赖更新命令与常见问题排查

Gatsby 升级指南:语义化版本、依赖更新命令与常见问题排查 【免费下载链接】gatsby React-based framework with performance, scalability, and security built in. 项目地址: https://gitcode.com/gh_mirrors/ga/gatsby 导读 本篇指南围绕 upgrade-gatsby…

作者头像 李华
网站建设 2026/9/19 21:25:07

Shopee接口逆向:x-sap-Ri与x-sap-Sec签名生成全解析

做电商平台数据采集的人,这两年应该都能明显感觉到,Shopee的详情页接口已经不是当年随手一抓就能返回数据的时代了。打开商品详情页,随便点一个请求,Headers里都会带上两个非常显眼的参数:x-sap-Ri和x-sap-Sec。第一次…

作者头像 李华
网站建设 2026/9/19 21:23:55

KimiCode 跑 Kimi K3 长程 Agent,Base URL 填 TaoToken 兼容地址

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华