ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

x64dbg 插件开发:使用 `_plugin_menuentryseticon` 为菜单条目动态设置图标

2026/9/19 18:15:18 拓冰建站 浏览量
x64dbg 插件开发:使用 `_plugin_menuentryseticon` 为菜单条目动态设置图标 逆向工程调试器开发工具应用安全【免费下载链接】x64dbgAn open-source user mode debugger for Windows. Optimized for reverse engineering and malware analysis.项目地址https://gitcode.com/gh_mirrors/x6/x64dbg点击查看免费下载_plugin_menuentryseticon是 x64dbg 为插件开发者导出的_plugin_前缀 API 家族成员之一用于为已添加的插件菜单条目menu entry设置或更换图标。在本文中你将掌握该函数的完整签名、ICONDATA数据结构定义、从插件层到 GUI 层的完整调用链并通过可运行的示例代码学会将其与_plugin_menuaddentry等菜单 API 配合使用实现带图标的自定义插件菜单。函数签名与核心行为该函数用于为一条插件菜单条目设置图标。其原型定义在 menuentryseticon.rst 中void _plugin_menuentryseticon( int pluginHandle, //plugin handle int hEntry, //handle of the menu entry const ICONDATA* icon //icon data );函数声明位于 src/dbg/_plugins.h导出实现位于 src/dbg/_plugins.cpp其内部直接转发给调试器核心层的pluginmenuentryseticonPLUG_IMPEXP void _plugin_menuentryseticon(int pluginHandle, int hEntry, const ICONDATA* icon) { pluginmenuentryseticon(pluginHandle, hEntry, icon); }该函数没有返回值。与返回bool的_plugin_menuaddentry不同你无法通过返回值判断操作是否成功因此更需要在调用前确保hEntry的来源合法例如来自之前成功的_plugin_menuaddentry调用。参数详解参数类型含义pluginHandleint调用方插件的句柄handle即pluginit阶段由 x64dbg 分配并写入PLUG_INITSTRUCT::pluginHandle的值hEntryint菜单条目句柄。必须是先前通过_plugin_menuaddentry添加子菜单或主插件菜单条目时使用的插件级唯一标识符iconconst ICONDATA*图标数据指针结构定义见src/bridge/bridgemain.h详见下文需要特别说明hEntry的语义根据 menuaddentry.rst 的说明hEntry是插件全局唯一plugin-wide的条目标识符而不是 GUI 内部生成的句柄——当你点击该菜单条目时x64dbg 会通过PLUG_CB_MENUENTRY回调把这个同样的hEntry值传回给插件。这意味着hEntry在整个菜单生命周期中充当插件与 GUI 之间的对账键_plugin_menuentryseticon正是借助这个键定位到目标条目。ICONDATA 数据结构ICONDATA定义于 src/bridge/bridgemain.h是整个桥接层通用的图标描述结构typedef struct { const void* data; duint size; } ICONDATA;两个字段的含义data指向图标原始数据的指针。从核心层 plugin_loader.cpp 的注释The icon (can be all kinds of formats).来看该指针可以指向多种格式的图标数据size图标数据的字节大小duint即 x64dbg 的地址宽度整数类型x86 下为 32 位x64 下为 64 位用于告知 GUI 端数据缓冲区的长度。该结构同样被_plugin_menuseticon为整个菜单设置图标所使用是 x64dbg 桥接层插件 → 调试器 → GUI传递二进制图标数据的统一载体。底层调用链从插件到 Qt 菜单理解调用链有助于你在排查图标没生效类问题时快速定位环节。_plugin_menuentryseticon的完整链路如下1. 插件导出层src/dbg/_plugins.cpp转发到核心层pluginmenuentryseticon。2. 核心层查找与防护src/dbg/plugin_loader.cppvoid pluginmenuentryseticon(int pluginHandle, int hEntry, const ICONDATA* icon) { if(hEntry -1) return; SHARED_ACQUIRE(LockPluginMenuList); for(const auto currentMenu : gPluginMenuEntryList) { if(currentMenu.pluginHandle pluginHandle currentMenu.hEntryPlugin hEntry) { GuiMenuSetEntryIcon(currentMenu.hEntryMenu, icon); break; } } }这里有两个值得注意的实现细节hEntry -1的快速失败当条目句柄为-1时直接返回这是菜单 API 家族共用的无效句柄约定pluginmenuentrysetchecked等函数同样如此双重匹配条件核心层维护着全局插件菜单条目表gPluginMenuEntryList必须同时满足pluginHandle与hEntryPlugin两个条件才命中。由于hEntry只是插件级唯一不同插件可能使用相同的数值因此调用时必须传入正确的pluginHandle否则可能匹配到其他插件的条目或匹配不到任何条目。3. 桥接层消息发送src/bridge/bridgemain.cppBRIDGE_IMPEXP void GuiMenuSetEntryIcon(int hEntry, const ICONDATA* icon) { _gui_sendmessage(GUI_MENU_SET_ENTRY_ICON, (void*)(duint)hEntry, (void*)icon); }通过_gui_sendmessage把GUI_MENU_SET_ENTRY_ICON消息投递给 GUI 进程。4. GUI 端落地src/gui/Src/Gui/MainWindow.cppvoid MainWindow::setIconMenuEntry(int hEntry, QIcon icon) { MethodInvoker::invokeMethod([this, hEntry, icon] { QMutexLocker locker(mMenuMutex); auto entry findMenuEntry(hEntry); if(entry nullptr) return; entry-mAction-setIcon(icon); }); Bridge::getBridge()-setResult(BridgeResult::MenuSetEntryIcon); }可以看到最终动作是在 GUI 线程中查找对应的菜单项并调用 Qt 的QAction::setIcon。由于 x64dbg 的 GUI 基于 QtICONDATA中的原始图标数据会被转换成QIcon后应用到QAction上。同时mMenuMutex的存在说明对菜单结构的并发访问是受保护的。从这条链路可以得出一个实用结论图标设置本质上是一个异步的跨进程/跨线程消息过程即使_plugin_menuentryseticon立即返回图标在 GUI 上的呈现也存在延迟插件无需也无法等待其完成。实战示例创建带图标的插件菜单将_plugin_menuentryseticon与菜单 API 家族配合使用的典型流程是在plugsetup阶段添加菜单条目随后为条目设置图标。以下示例基于 basics.md 描述的插件导出约定pluginit/plugsetup/plugstop并结合 menuaddentry.rst 的返回约定// 插件级唯一的条目 ID后续会通过 PLUG_CB_MENUENTRY 回调传回 #define MENU_ENTRY_ICONED 1 // 插件自带的小图标以原始字节数组形式编译进插件 static const unsigned char myIconData[] { /* ...PNG/ICO 等格式的字节... */ }; static int hMenu; // 插件根菜单句柄 PLUG_EXPORT void plugsetup(PLUG_SETUPSTRUCT* setupStruct) { hMenu setupStruct-hMenu; // x64dbg 为插件分配的主菜单句柄 // 1. 先添加菜单条目hEntry 是插件级唯一 ID if(_plugin_menuaddentry(hMenu, MENU_ENTRY_ICONED, My Iconed Command)) { // 2. 条目添加成功后为其设置图标 ICONDATA icon; icon.data myIconData; icon.size sizeof(myIconData); _plugin_menuentryseticon(setupStruct-pluginHandle, MENU_ENTRY_ICONED, icon); } }结合源码示例中有几点值得强调setupStruct-hMenu即文档参数说明中提到的主插件菜单main plugin menu_plugin_menuentryseticon的hEntry参数文档同样指出其来源是先前添加的子菜单或主插件菜单setupStruct-pluginHandle必须原样传给_plugin_menuentryseticon因为核心层的查找逻辑以(pluginHandle, hEntryPlugin)二元组为匹配键见 plugin_loader.cpp若菜单条目是在子菜单下添加的只需把_plugin_menuaddentry的第一个参数换成_plugin_menuadd返回的子菜单句柄即可hEntry的用法不变。注意事项与最佳实践调用时机菜单条目必须先通过_plugin_menuaddentry成功添加才能对其设置图标对不存在的hEntry调用不会产生任何效果核心层遍历找不到匹配项即静默返回。因此最佳实践是把_plugin_menuentryseticon放在plugsetup阶段、条目添加成功之后或放在PLUG_CB_MENUENTRY回调等条目已确定的时机。hEntry的取值约束不要使用-1核心层会将其视为无效句柄直接忽略。同时该值必须在插件内全局唯一否则会与回调匹配产生歧义。pluginHandle必须匹配由于查找条件是pluginHandle与hEntry的组合传入其他插件的句柄将无法命中本条目的记录导致图标静默失效。图标数据格式从核心层注释看ICONDATA.data支持多种图片格式GUI 端会将其转换为QIcon。建议使用 x64dbg GUI 原生支持的常见格式如 PNG并保证size与实际数据长度严格一致避免越界解析。区分两个 API_plugin_menuentryseticon针对单个菜单条目而_plugin_menuseticon见 menuseticon.rst针对整个菜单如插件根菜单。两者共享同一个ICONDATA结构容易混淆使用时注意区分目标句柄的类型。相关 API 与继续阅读_plugin_menuentryseticon属于 x64dbg 插件菜单 API 家族完整清单见 API 索引。与之经常配合使用的函数包括_plugin_menuaddentry添加菜单条目并返回布尔结果是本函数的前置步骤_plugin_menuadd添加子菜单用于构建多级菜单结构_plugin_menuseticon为整个菜单设置图标_plugin_menuentrysetchecked为条目设置勾选状态常与图标配合实现状态可视化。如果想深入插件开发的整体流程pluginit/plugsetup/plugstop等导出函数可以阅读 插件开发基础想进一步追踪菜单机制的完整实现可以沿 src/dbg/_plugins.cpp → src/dbg/plugin_loader.cpp → src/bridge/bridgemain.cpp → src/gui/Src/Gui/MainWindow.cpp 这条调用链继续研读源码。赞分享逆向工程调试器开发工具应用安全【免费下载链接】x64dbgAn open-source user mode debugger for Windows. Optimized for reverse engineering and malware analysis.项目地址https://gitcode.com/gh_mirrors/x6/x64dbg点击查看免费下载相关推荐x64dbg GUI 接口详解GuiMenuSetIcon 为插件菜单设置图标x64dbg GUI 接口详解GuiMenuSetIcon 为插件菜单设置图标 本文围绕 x64dbg 开发者文档中的 GuiMenuSetIcon 接口展开逆向工程调试器开发工具应用安全x64dbg GuiMenuSetEntryIcon通过 Bridge 与插件 API 为菜单项设置图标x64dbg GuiMenuSetEntryIcon通过 Bridge 与插件 API 为菜单项设置图标 本文以 x64dbg 开发者文档中的 GuiMenu逆向工程调试器开发工具应用安全x64dbg GUI Bridge API 详解GuiMenuAddEntry 向菜单动态添加条目x64dbg GUI Bridge API 详解GuiMenuAddEntry 向菜单动态添加条目 本文以 x64dbg 官方 API 文档 docs/dev逆向工程调试器开发工具应用安全创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考