大神论坛

找回密码
快速注册
查看: 425 | 回复: 0

[原创] 修改 Multiline Ultimate Assembler x64dbg插件完美支持中文

digest

主题

帖子

0

积分

初入江湖

UID
691
积分
0
精华
威望
0 点
违规
大神币
68 枚
注册时间
2023-10-14 10:58
发表于 2024-01-19 21:52
本帖最后由 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”一项删除


注:若转载请注明大神论坛来源(本贴地址)与作者信息。

返回顶部