
逆向工程调试器开发工具应用安全【免费下载链接】x64dbgAn open-source user mode debugger for Windows. Optimized for reverse engineering and malware analysis.项目地址https://gitcode.com/gh_mirrors/x6/x64dbg点击查看免费下载导读GuiRegisterScriptLanguage是 x64dbg 桥接层bridge提供的一个 GUI 接口用于向调试器图形界面注册一种新的脚本语言使得该语言能够出现在主界面命令输入框的语言下拉列表中并被用户选择作为命令执行引擎。本文基于仓库源码完整梳理该 API 的函数签名、SCRIPTTYPEINFO参数结构、GUI 侧的处理逻辑、执行链路与注册示例帮助插件开发者在 x64dbg 中安全、正确地注册自定义脚本引擎并理解其与GuiUnregisterScriptLanguage、命令执行器之间的协作关系。一、函数定位与声明该函数是 x64dbg 桥接 API 的一员属于 GUI 侧gui分组接口声明位于 src/bridge/bridgemain.hBRIDGE_IMPEXP void GuiRegisterScriptLanguage(SCRIPTTYPEINFO* info);与之成对的反向接口是GuiUnregisterScriptLanguage用于注销已注册的脚本语言BRIDGE_IMPEXP void GuiUnregisterScriptLanguage(int id);两者在桥接层的实现位于 src/bridge/bridgemain.cppBRIDGE_IMPEXP void GuiRegisterScriptLanguage(SCRIPTTYPEINFO* info) { _gui_sendmessage(GUI_REGISTER_SCRIPT_LANG, (void*)info, nullptr); } BRIDGE_IMPEXP void GuiUnregisterScriptLanguage(int id) { _gui_sendmessage(GUI_UNREGISTER_SCRIPT_LANG, (void*)(duint)id, nullptr); }可以看出这两个函数本身只是把参数封装进_gui_sendmessage消息通道真正的工作发生在 GUI 线程的消息分发端。注册消息GUI_REGISTER_SCRIPT_LANG与注销消息GUI_UNREGISTER_SCRIPT_LANG被定义在 bridgemain.h 的GUIMSG_LIST消息枚举宏列表中msg(GUI_REGISTER_SCRIPT_LANG, SCRIPTTYPEINFO* info, unused) \ msg(GUI_UNREGISTER_SCRIPT_LANG, int id, unused) \二、核心参数结构SCRIPTTYPEINFOGuiRegisterScriptLanguage的唯一参数是SCRIPTTYPEINFO*指针该结构体定义在 src/bridge/bridgemain.htypedef struct { char name[64]; int id; GUISCRIPTEXECUTE execute; GUISCRIPTCOMPLETER completeCommand; } SCRIPTTYPEINFO;各字段含义与使用要点如下字段类型说明namechar[64]脚本语言名称UTF-8 编码将显示在命令输入框的语言下拉列表QComboBox中。注意缓冲区固定为 64 字节名称过长会被截断idint语言唯一标识。由 GUI 侧在注册时自动分配详见下文调用方传入前可初始化为 0注册成功后由 GUI 端回填executeGUISCRIPTEXECUTE执行回调函数指针当用户在该语言下按回车执行命令时被调用completeCommandGUISCRIPTCOMPLETER可选的命令补全回调用于为该语言提供自定义自动补全候选其中两个函数指针类型同样定义在 bridgemain.htypedef bool (*GUISCRIPTEXECUTE)(const char* text); typedef void (*GUISCRIPTCOMPLETER)(const char* text, char** entries, int* entryCount);execute接收用户输入的命令文本UTF-8返回bool表示是否执行成功completeCommand接收当前输入文本通过entries/entryCount向外输出补全候选列表。三、返回值GuiRegisterScriptLanguage返回类型为void本身不直接返回注册结果。注册是否成功通过桥接层的同步等待机制BridgeResult在 GUI 线程内确认在 GUI 侧消息分发处 src/gui/Src/Bridge/Bridge.cppcase GUI_REGISTER_SCRIPT_LANG: { BridgeResult result(BridgeResult::RegisterScriptLang); emit registerScriptLang((SCRIPTTYPEINFO*)param1); result.Wait(); } break;result.Wait()会阻塞等待 GUI 槽函数通过setResult写回结果。如果传入的info为空指针GUI 端会直接写回结果 0注册失败正常注册完成后写回 1。四、GUI 侧处理流程注册、选择与执行4.1 注册槽函数Qt 信号registerScriptLang(SCRIPTTYPEINFO*)在 src/gui/Src/Gui/CommandLineEdit.cpp 中被连接到命令输入框的槽函数registerScriptType完整实现见 CommandLineEdit.cppvoid CommandLineEdit::registerScriptType(SCRIPTTYPEINFO* info) { // Must be valid pointer if(!info) { Bridge::getBridge()-setResult(BridgeResult::RegisterScriptLang, 0); return; } // Insert info-id mScriptInfo.size(); mScriptInfo.push_back(*info); // Update mCmdScriptType-addItem(info-name); if(info-id 0) mCurrentScriptIndex 0; char savedType[MAX_SETTING_SIZE] ; if(BridgeSettingGet(Gui, ScriptType, savedType) strcmp(info-name, savedType) 0) mCmdScriptType-setCurrentIndex(info-id); Bridge::getBridge()-setResult(BridgeResult::RegisterScriptLang, 1); }关键逻辑可归纳为空指针校验info为空时直接返回失败结果自动分配 idinfo-id mScriptInfo.size()即按注册顺序从 0 开始递增第一个注册的语言 id 为 0这一规则与注销时的保护逻辑见下文直接相关保存副本mScriptInfo.push_back(*info)将结构体拷贝保存到QListSCRIPTTYPEINFO中调用方传入的栈上结构体生命周期可以安全结束加入语言下拉框mCmdScriptType-addItem(info-name)使该语言出现在命令输入框左侧的语言选择器中恢复上次选择读取Gui配置节下的ScriptType键通过BridgeSettingGet若与当前注册的语言名称一致则自动将其设为当前选中项回写成功结果setResult(..., 1)。4.2 语言切换与执行注册完成后用户可以通过命令输入框的语言下拉框mCmdScriptType或快捷键Ctrl Up / Ctrl Down在多种语言之间切换见 CommandLineEdit.cpp 的keyPressEvent实现。当前语言被记录在mCurrentScriptIndex用户按回车时由execute()完成实际执行CommandLineEdit.cppvoid CommandLineEdit::execute() { if(mCurrentScriptIndex -1) return; GUISCRIPTEXECUTE exec mScriptInfo[mCurrentScriptIndex].execute; QString cmd text(); if(exec) { if(cmd.trimmed().isEmpty()) if(Config()-getBool(Gui, AutoRepeatOnEnter)) cmd getLineFromHistory(); // Clear the status bar GuiAddStatusBarMessage(\n); // Send this string directly to the user exec(cmd.toUtf8().constData()); } ... }即根据当前选中的语言下标取出其execute回调把输入框中的 UTF-8 文本交给该回调执行。这就是脚本语言抽象的核心——不同语言只是不同execute回调的实现差异。若当前语言未设置execute空指针则直接跳过执行。另外语言切换会触发scriptTypeActivated将当前选择持久化到配置项Gui/ScriptTypeCommandLineEdit.cpp保证下次启动 x64dbg 时仍保持用户上次选择的脚本语言。4.3 注销逻辑与默认语言保护GuiUnregisterScriptLanguage(int id)在 GUI 端对应unregisterScriptTypeCommandLineEdit.cppvoid CommandLineEdit::unregisterScriptType(int id) { // The default script type cant be unregistered if(id 0) return; // Loop through the vector and invalidate entry (validate id) for(int i 0; i mScriptInfo.size(); i) { if(mScriptInfo[i].id id) { mScriptInfo.removeAt(i); mCmdScriptType-removeItem(i); break; } } // Update selected index if(mCurrentScriptIndex 0) mCurrentScriptIndex--; mCmdScriptType-setCurrentIndex(mCurrentScriptIndex); }注意两点限制id 为 0 的默认脚本语言不允许注销这是对内置语言的一种保护注销时会从内部列表与下拉框中同步移除对应条目并校正当前选中索引。五、注册示例内核启动时的两个内置语言x64dbg 自身在调试器初始化阶段就通过该 API 注册了两个内置语言位于 src/dbg/x64dbg.cpp这是最权威的教科书式用法SCRIPTTYPEINFO info {}; strcpy_s(info.name, GuiTranslateText(QT_TRANSLATE_NOOP(DBG, Default))); info.execute [](const char* cmd) { if(!DbgCmdExec(cmd)) return false; GuiFlushLog(); return true; }; GuiRegisterScriptLanguage(info); strcpy_s(info.name, GuiTranslateText(QT_TRANSLATE_NOOP(DBG, Script DLL))); info.execute DbgScriptDllExec; GuiRegisterScriptLanguage(info);该示例展示了标准的注册套路用{}将SCRIPTTYPEINFO结构体零初始化通过GuiTranslateTextQT_TRANSLATE_NOOP填充可翻译的语言名称分别指定execute回调Default执行DbgCmdExec(cmd)调用调试器命令系统成功后再GuiFlushLog()刷新日志实现命令即脚本Script DLL交给DbgScriptDllExec处理脚本 DLL 的命令输入依次调用GuiRegisterScriptLanguage完成注册。由于注册发生在调试器命令循环与插件加载pluginloadall之前插件后续可以通过同一机制继续追加自己的脚本语言。也正因如此下拉框中id 0 恒为 Default 语言scriptTypeChanged中对 index 0 的特殊占位提示文本Commands are comma separated (like assembly instructions): mov eax, ebx也是针对该内置语言的CommandLineEdit.cpp。六、无界面headless模式的对应实现x64dbg 的 headless 构建同样处理GUI_REGISTER_SCRIPT_LANG消息实现于 src/headless/headless.cppcase GUI_REGISTER_SCRIPT_LANG: { SCRIPTTYPEINFO* info (SCRIPTTYPEINFO*)param1; info-id (int)scriptInfo.size(); scriptInfo.push_back(*info); } break; case GUI_UNREGISTER_SCRIPT_LANG: { int id (int)(duint)param1; if(id ! 0) { puts([TODO] Not implemented GUI_UNREGISTER_SCRIPT_LANG); } } break;从源码结构看headless 模式仅维护一个std::vectorSCRIPTTYPEINFO scriptInfoheadless.cpp按注册顺序分配 id且注销逻辑标注为未实现TODO。这说明GuiRegisterScriptLanguage在两种构建下都有入口只是无界面模式下没有下拉框等 GUI 交互。七、相关函数与配套接口在桥接 API 的 GUI 分组中与脚本语言机制紧密相关的接口还包括同目录文档见 docs/developers/functions/guiGuiUnregisterScriptLanguage注销指定 id 的脚本语言与本文函数成对使用GuiScriptAdd/GuiScriptClear向脚本窗口添加/清空脚本内容GuiScriptSetTitle设置脚本窗口标题GuiScriptSetIp在脚本窗口中设置当前指令指针标记GuiScriptError在脚本窗口输出错误信息GuiScriptMessage/GuiScriptMsgyn脚本窗口的消息提示与询问对话框GuiScriptEnableHighlighting切换脚本语法高亮GuiScriptSetInfoLine在脚本窗口状态行显示提示信息。此外命令补全体系相关的GuiAutoCompleteAddCmd/GuiAutoCompleteDelCmd/GuiAutoCompleteClearAll可用来管理默认命令补全列表与SCRIPTTYPEINFO.completeCommand的自定义补全共同构成 x64dbg 输入框的补全能力。八、插件使用建议与注意事项综合源码实现为插件注册自定义脚本语言时建议遵循以下要点结构体必须零初始化SCRIPTTYPEINFO info {};可确保completeCommand等可选字段为nullptr避免 GUI 端访问未初始化指针名称使用 UTF-8 编码桥接层约定 code page 为 UTF-8见 bridgemain.h 附近注释语言名称建议通过GuiTranslateText支持多语言无需关心 id 分配id 由 GUI 端自动分配并从 0 递增插件在注册前后都无需也不应自行指定注销时注意默认保护id 0 的 Default 语言不可注销插件应在卸载时调用GuiUnregisterScriptLanguage(info.id)注销自己注册的语言避免残留注册时机可在插件初始化阶段pluginit调用此时 GUI 桥接已就绪内核内置注册发生在插件加载之前执行回调保持轻量execute在 GUI 消息分发链路中被同步调用result.Wait()等待处理完成回调内部不应执行长时间阻塞操作以免拖慢界面响应。通过合理运用GuiRegisterScriptLanguage与配套接口插件可以将自有的脚本引擎、宏命令集或外部脚本运行时无缝接入 x64dbg 的命令输入体系获得与内置语言一致的下拉选择、配置记忆Gui/ScriptType与执行体验。赞分享逆向工程调试器开发工具应用安全【免费下载链接】x64dbgAn open-source user mode debugger for Windows. Optimized for reverse engineering and malware analysis.项目地址https://gitcode.com/gh_mirrors/x6/x64dbg点击查看免费下载相关推荐x64dbg 脚本命令 pause 详解暂停脚本执行、恢复机制与脚本状态机原理x64dbg 脚本命令 pause 详解暂停脚本执行、恢复机制与脚本状态机原理 本篇文章讲解 x64dbg 内置脚本引擎simplescript中的 pa逆向工程调试器开发工具应用安全x64dbg dec 命令详解通用自减指令的语法、实现原理与脚本实战x64dbg dec 命令详解通用自减指令的语法、实现原理与脚本实战 dec 是 x64dbg 调试器命令行体系中面向通用运算分类的自减命令用于将某个目逆向工程调试器开发工具应用安全x64dbg 脚本视图 IP 指针同步GuiScriptSetIp 接口详解与源码调用链剖析x64dbg 脚本视图 IP 指针同步GuiScriptSetIp 接口详解与源码调用链剖析 x64dbg 的脚本视图Script View是展示 x64逆向工程调试器开发工具应用安全创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考