本帖最后由 ftyh 于 2024-01-19 21:52 编辑
修改x64dbg插件 Multiline Ultimate Assembler 完美支持中文
一、分析篇 Multiline Ultimate Assembler 是一个调试器多行汇编插件,但它对中文的支持不好,体现在: (1)不能显示中文注释,键盘输入中文会显示乱码; (2)从调试器向插件同步中文注释会显示乱码; (3)从插件向调试器同步中文注释会显示乱码。 近期对通过 x64dbg 插件存在的以上问题进行分析,最终实现了中文的支持。 通过网络搜索类似问题,发现这个插件的 OD 版本有人实现了中文显示,是通过修改插件的二进制文件,默认使用中文字体就能正常显示中文,但也只能显示,未能解决输入和同步中文的问题。既然有了前人的经验就试着按 OD 版本的修改方法修改二进制文件,修改后发现完全没有作用,不管改成什么字体界面显示字体都没有变化,就像没有改过一样,怀疑二进制里设置的字体并不是关键。最后把目光定位到调试器的配置文件,打开 x64dbg.ini,果然发现有[Multiline Ultimate Assembler]小节,其中就有“font_name=Lucida Console”的项目,改成中文字体“font_name=Microsoft YaHei UI”,再打开插件,果然可以显示中文了,从外部粘贴中文过去也能正常显示。猜想二进制里的字体只是初始化设置,ini 里的才是实际使用的字体(后来看到源码也印证了猜想)。 接着是输入的问题,因为系统输入是正常的,显然插件自己处理了字符信息,只要不让插件处理 WM_CHAR 消息,交给系统去处理就好了(感谢网友 csjwaman 提供的思路,还有不明白插件为什么要自己处理输入字符)。 插件同步乱码的问题,(2)(3)其实是类似的问题,解决了一个另一个就迎刃而解。 查询 x64dbg 用户手册,在开发接口函数里发现有 DbgGetCommentAt 这个函数,虽然没有更进一步的介绍,但从字面上可以猜得出这是从调试器获取注释信息的。既然要从调试器同步注释过来第一步肯定是先获取注释,我们先看看取过来的注释是否正常,就用 x64dbg 自己来分析一下吧。 先打开一个 x64dbg,随便载入一个程序,在某条反汇编注释处输入中文字符串,再打开第二个 x64dbg,附加到第一个 x64dbg 上,找到 multiasm_x64dbg.dp64 里的跨模块调用,定位到 DbgGetCommentAt 函数并下断点。 在第一个 x64dbg 里中文注释的反汇编指令右键选择“Multiline Ultimate Assembler”,第二个 x64dbg 成功断下,F8 单步执行 DbgGetCommentAt 函数,看寄存器已经出现了我们输入的中文字符串,看起来一切正常。 一般乱码我们第一时间想到的就是编码问题,这时内存中的中文编码是 UTF-8,这和插件界面的编码是否一致呢,我们设定字体后显示的中文是正常的,我们把它们复制出来粘贴到 UltraEdit 去看,编码是 GBK,答案已经呼之欲出了。 我们手工将内存里取到的注释改成 GBK 编码,继续执行,发现同步到插件里的中文显示正常了。 同样,插件同步到调试器,我们定位到 DbgSetCommentAt 函数,在函数执行前将参数的 GBK 转换为 UTF-8 就可以正常显示中文。 这样,几个问题如何修改,我们就有了一个大致的思路: (1)修改默认字体,使支持中文显示; (2)拦截插件 WM_CHAR 消息,交给系统处理; (3)DbgGetCommentAt 函数执行后将注释信息转码(UTF-8 -> GBK); (4)DbgSetCommentAt 函数执行前将注释信息转码(GBK -> UTF-8)。
二、修改篇 (一)环境准备 1、源码下载 https://github.com/m417z/Multiline-Ultimate-Assembler
2、搭建环境 源码原来是 VS2015 的工程,搭配 Win SDK 7,支持 WinXP。 搭建环境这个环节踩了不少坑,原先图省事先后安装了 VS2015 便携版和 VS2017 便携版,结果编译一堆问题,还把注册表搞得乱七八槽,影响到后面的 VS2019 安装,最终清了半天注册表才搞定。想编译的朋友直接用 VS2019 在线安装就好,模块化的安装方式,增加删除模块都很方便。 VS2019 安装界面勾选“使用C++的桌面开发“,然后在“单个组件”下勾选下图的项目: 安装完成后将: C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Tools\MSVC\14.16.27023\atlmfc\include\afxres.h 复制一份到: C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Tools\MSVC\14.29.30133\atlmfc\include 否则编译可能会出现“error RC1015: cannot open include file 'afxres.h'“错误。 以上完成后打开项目解决方案,会出现以下提示,确定即可。 如果没出现上面提示,可以手动在工程属性中设置 SDK 版本和平台工具集设置如下: 这时可以编译一下,编译成功就可以着手进行代码修改了。
安装选项参考: https://learn.microsoft.coAm/en-us/cpp/build/configuring-programs-for-windows-xp?view=msvc-170&viewFallbackFrom=vs-2019
(二)源码修改 1、修改默认字体(微软雅黑) 文件:assembler_dlg.c 找到 SetRAEditDesign 函数,修改如下: if(!MyGetstringfromini(hInstance, _T("font_name"), lfLogFont.lfFaceName, LF_FACESIZE)) { lstrcpy(lfLogFont.lfFaceName, _T("Microsoft YaHei UI")); // Default font MyWritestringtoini(hInstance, _T("font_name"), lfLogFont.lfFaceName); }
2、插件输入中文乱码 文件:assembler_dlg.c 找到 AssemblerPreTranslateMessage 函数,修改如下: BOOL AssemblerPreTranslateMessage(LPMSG lpMsg) { if(hAsmDlg) { HWND hWnd = hAsmDlg; HWND hFindReplaceWnd = AsmDlgParam.hFindReplaceWnd; if(hFindReplaceWnd && IsDialogMessage(hFindReplaceWnd, lpMsg)) return TRUE; if(GetActiveWindow() == hWnd) { if (lpMsg->message == WM_CHAR) return FALSE; if(hAccelerators && TranslateAccelerator(hWnd, hAccelerators, lpMsg)) return TRUE; } if(IsDialogMessage(hWnd, lpMsg)) return TRUE; } return FALSE; }
3、从x64dbg同步中文注释 文件:plugin_x64dbg.c 找到 GetComment 函数,修改如下: void Utf8ToGbk(char* utf8String, char* gbkString) { gbkString = utf8String; wchar_t* unicodeStr = NULL; int Len = 0; Len = MultiByteToWideChar(CP_UTF8, 0, utf8String, -1, NULL, 0); unicodeStr = (wchar_t*)malloc(Len * sizeof(wchar_t)); MultiByteToWideChar(CP_UTF8, 0, utf8String, -1, unicodeStr, Len); Len = WideCharToMultiByte(CP_ACP, 0, unicodeStr, -1, NULL, 0, NULL, 0); WideCharToMultiByte(CP_ACP, 0, unicodeStr, -1, gbkString, Len, NULL, 0); free(unicodeStr); } int GetComment(DWORD_PTR addr, TCHAR *name) { if(!DbgGetCommentAt(addr, name)) return 0; if(name[0] == '\1') // Automatic comment return 0; char* gbkString; Utf8ToGbk(name, gbkString); return lstrlen(name); }
4、向x64dbg同步中文注释 文件:plugin_x64dbg.c 找到 QuickInsertComment 函数,修改如下: void GbkToUtf8(char* gbkString, char* utf8String) { utf8String = gbkString; wchar_t* unicodeStr = NULL; int Len = 0; Len = MultiByteToWideChar(CP_ACP, 0, gbkString, -1, NULL, 0); unicodeStr = (wchar_t*)malloc(Len * sizeof(wchar_t)); MultiByteToWideChar(CP_ACP, 0, gbkString, -1, unicodeStr, Len); Len = WideCharToMultiByte(CP_UTF8, 0, unicodeStr, -1, NULL, 0, NULL, 0); WideCharToMultiByte(CP_UTF8, 0, unicodeStr, -1, utf8String, Len, NULL, 0); free(unicodeStr); } BOOL QuickInsertComment(DWORD_PTR addr, TCHAR *s) { char* utf8String; GbkToUtf8(s, utf8String); return DbgSetCommentAt(addr, s); }
如果中文显示乱码请将x32dbg.ini和x64dbg.ini文件中 [Multiline Ultimate Assembler]小节下“font_name”一项删除
注:若转载请注明大神论坛来源(本贴地址)与作者信息。
|