X64dbg中文乱码解决

X64dbg可以对64位的软件进行反编译,是针对Olldbg只能调试32位软件的改进,使用也比较方便。但由于该软件前端使用QT开发,对中文的解析经常会出现乱码,不能很好解析出中文(经测试发现对GB2312、GBK的字符解析都没问题),使用Strings和x64dbg_tol两款插件也不能解决问题,为此对x64dbg-2021-1-12版进行了修改完善,增加了解析UTF-8及完善了UTF-16(Unicode)的功能,并对CPU dump界面显示方式和寄存器、堆栈标签显示方式进行了修改,同时增加了自动对进程PEB和线程TLB进行注释的功能。

一、源码下载及编译

1、下载development版源码

$ git clone -b development https://hub.fastgit.org/x64dbg/x64dbg.git

进入x64dbg目录下,将.gitmodules内的github.com替换为hub.fastgit.org
然后在x64dbg目录内执行:

git submodule update --init --recursive

下载子目录文件。(使用hub.fastgit.org代替github.com是为了加快下载速度)

2、安装编译环境

下载安装:
qt-opensource-windows-x86-msvc2013_64-5.6.3.exe
qt-opensource-windows-x86-msvc2013-5.6.3.exe
qt-creator-opensource-windows-x86-4.3.1.exe
vs2013sp5
windows_sdk_8.1
qt-vsaddin-msvc2013-2.3.2.vsix
并完成QT_VS_TOOLS的设置(通用设置,略)。
为了调试方便,QT的pro工程使用QT_VS_TOOLS导入解决方案中,不单独使用qt-creater编译。
导入工程选择x64-release版本编译即可成功。(略)

二、UTF-8解析功能实现

在x64dbg\src\dbg\disasm_helper.cpp文件内修改如下函数:
在isunicodestring内对汉字进行严格过滤

extern "C" __declspec(dllexport) bool isunicodestring(const unsigned char* data, int maxlen)
{int len = 0;wchar_t* safebuffer = new wchar_t[maxlen];if(!safebuffer)return false;//修改开始//严格匹配汉字if (((unsigned char)data[0] < 0x34) || ((unsigned char)data[0] > 0x80)){return false;}else if (((unsigned char)data[0] == 0x4D) && ((unsigned char)data[1] > 0xB5)){return false;}//修改结束for(const wchar_t* p = (const wchar_t*)data; *p; len += sizeof(wchar_t), p++){if(len >= maxlen)break;safebuffer[p - (const wchar_t*)data] = *p;}if(len < 2 * sizeof(wchar_t)){delete[] safebuffer;return false;}safebuffer[len / sizeof(wchar_t) - 1] = 0; // Mark the end of stringString data2;WString wdata2;// Convert to and from ANSIdata2 = StringUtils::Utf16ToLocalCp(safebuffer);delete[] safebuffer;if(data2.size() < 2)return false;wdata2 = StringUtils::LocalCpToUtf16(data2);if(wdata2.size() < 2)return false;// Is the data exactly representable in both ANSI and Unicode?if(memcmp(wdata2.c_str(), data, wdata2.size() * sizeof(wchar_t)) != 0)return false;// Filter out bad charsif(!isunicodestring(wdata2))return false;return true;
}

增加utf-8字符串判断函数(此处只检测第一个字符是否为utf-8):通过对软件数据跟踪发现,x64dbg内同时存在三字节的UTF-8和两字节的UTF-8,而两字节的UTF-8软件处理位Unicode编码(软件命名为UTF-16),而对三字节的UTF-8编码没有进行处理,
如图:0000h地址处的 E590就是"启"的两字节UTF-8编码0x90E5,即通常意义的Unicode码。
0xCCh处的E590AF就是启的三字节UTF-8编码0xE590AF。

extern "C" __declspec(dllexport) bool isutf8string(const unsigned char* data, int maxlen)
{int len = 0;char* safebuffer = new char[maxlen];if (!safebuffer)return false;for (const char* p = (const char*)data; *p; len++, p++){if (len >= maxlen)break;safebuffer[p - (const char*)data] = *p;}if (len < 2){delete[] safebuffer;return false;}safebuffer[len] = 0; // Mark the end of stringbool isutf8 = false;//只匹配三字节表示的汉字if (((unsigned char)safebuffer[0] >= 0xE3) && ((unsigned char)safebuffer[0] <= 0xE9)){if (((unsigned char)safebuffer[1] >= 0x80) && ((unsigned char)safebuffer[1] <= 0xBF)){if (((unsigned char)safebuffer[2] >= 0x80) && ((unsigned char)safebuffer[2] <= 0xBF)){isutf8 = true;}else{isutf8 = false;}}else{isutf8 = false;}}else{isutf8 = false;}return isutf8;
}

disasmispossiblestring内增加对utf8字符串的处理

bool disasmispossiblestring(duint addr, STRING_TYPE* type)
{unsigned char data[60];memset(data, 0, sizeof(data));duint bytesRead = 0;if(!MemReadUnsafe(addr, data, sizeof(data), &bytesRead) && bytesRead < 2)return false;if(isasciistring(data, sizeof(data))){if(type)*type = str_ascii;return true;}if(isunicodestring(data, sizeof(data) / 2)){if(type)*type = str_unicode;return true;}//修改开始if (isutf8string(data, sizeof(data) + 1)){if (type)*type = str_utf8;return true;}//修改结束if(type)*type = str_none;return false;
}

disasmgetstringat对三字节UTF-8字符串进行编码转换,并返回

bool disasmgetstringat(duint addr, STRING_TYPE* type, char* ascii, char* unicode, int maxlen)
{if(type)*type = str_none;if(!MemIsValidReadPtrUnsafe(addr, true) || !disasmispossiblestring(addr))return false;Memory<unsigned char*> data((maxlen + 1) * 2, "disasmgetstringat:data");MemReadUnsafe(addr, data(), (maxlen + 1) * 2); //TODO: use safe version?// Save a few pointer castsauto asciiData = (char*)data();// First check if this was an ASCII only stringif(isasciistring(data(), maxlen)){if(type)*type = str_ascii;// Convert ANSI string to UTF-8std::string asciiData2 = StringUtils::LocalCpToUtf8((const char*)data());memcpy(asciiData, asciiData2.c_str(), min((size_t(maxlen) + 1) * 2, asciiData2.size() + 1));// Escape the stringString escaped = StringUtils::Escape(asciiData);// Copy data back to outgoing parameterstrncpy_s(ascii, min(int(escaped.length()) + 1, maxlen), escaped.c_str(), _TRUNCATE);return true;}if(isunicodestring(data(), maxlen)){if(type)*type = str_unicode;// Convert UTF-16 string to UTF-8std::string asciiData2 = StringUtils::Utf16ToUtf8((const wchar_t*)data());memcpy(asciiData, asciiData2.c_str(), min((size_t(maxlen) + 1) * 2, asciiData2.size() + 1));// Escape the stringString escaped = StringUtils::Escape(asciiData);// Copy data back to outgoing parameterstrncpy_s(unicode, min(int(escaped.length()) + 1, maxlen), escaped.c_str(), _TRUNCATE);return true;}//修改开始if (isutf8string(data(), maxlen)){if (type)*type = str_utf8;// Convert UTF-16 string to UTF-8std::string asciiData2 = (const char*)data();memcpy(asciiData, asciiData2.c_str(), min((size_t(maxlen) + 1) * 2, asciiData2.size() + 1));// Escape the stringString escaped = StringUtils::Escape(asciiData);// Copy data back to outgoing parameterstrncpy_s(unicode, min(int(escaped.length()) + 1, maxlen), escaped.c_str(), _TRUNCATE);return true;}//修改结束return false;
}

disasmgetstringatwrapper处理字符串输出,此处“&L”开头为两字节Unicode(UTF-16)字符,“#F”开头为三字节UTF-8字符

bool disasmgetstringatwrapper(duint addr, char* dest, bool cache)
{if(!MemIsValidReadPtrUnsafe(addr, cache))return false;auto readValidPtr = [cache](duint addr) -> duint{duint addrPtr;if(MemReadUnsafe(addr, &addrPtr, sizeof(addrPtr)) && MemIsValidReadPtrUnsafe(addrPtr, cache))return addrPtr;return 0;};*dest = '\0';char string[MAX_STRING_SIZE];duint addrPtr = readValidPtr(addr);STRING_TYPE strtype;auto possibleUnicode = disasmispossiblestring(addr, &strtype) && strtype == str_unicode;//修改开始-by WangRui 20210107auto possibleUtf8 = disasmispossiblestring(addr, &strtype) && strtype == str_utf8;auto possibleAscii = disasmispossiblestring(addr, &strtype) && strtype == str_ascii;if (possibleAscii)  //addrPtr &&possibleAscii{if (disasmgetstringat(addr, &strtype, string, string, MAX_STRING_SIZE - 5))  //addrPtr{if (strtype == str_ascii)sprintf_s(dest, MAX_STRING_SIZE, "\"%s\"", string);else if (strtype == str_unicode)//unicodesprintf_s(dest, MAX_STRING_SIZE, "L\"%s\"", string);else if (strtype == str_utf8)sprintf_s(dest, MAX_STRING_SIZE, "F\"%s\"", string);return true;}}if (possibleUnicode){if (disasmgetstringat(addr, &strtype, string, string, MAX_STRING_SIZE - 4)){if (strtype == str_ascii)sprintf_s(dest, MAX_STRING_SIZE, "&\"%s\"", string);else if (strtype == str_unicode)//unicodesprintf_s(dest, MAX_STRING_SIZE, "&L\"%s\"", string);else if (strtype == str_utf8)sprintf_s(dest, MAX_STRING_SIZE, "&F\"%s\"", string);return true;}}if (possibleUtf8){if (disasmgetstringat(addr, &strtype, string, string, MAX_STRING_SIZE - 4)){if (strtype == str_ascii)sprintf_s(dest, MAX_STRING_SIZE, "#\"%s\"", string);else if (strtype == str_unicode)//unicodesprintf_s(dest, MAX_STRING_SIZE, "#L\"%s\"", string);else if (strtype == str_utf8)sprintf_s(dest, MAX_STRING_SIZE, "#F\"%s\"", string);return true;}}if (addrPtr && !possibleAscii &&!possibleUnicode &&!possibleUtf8){if (disasmgetstringat(addrPtr, &strtype, string, string, MAX_STRING_SIZE - 5))  //addrPtr{if (int(strlen(string)) <= (strtype == str_ascii ? 3 : 2) && readValidPtr(addrPtr))  //addrPtrreturn false;if (strtype == str_ascii)sprintf_s(dest, MAX_STRING_SIZE, "\"%s\"", string);else if (strtype == str_unicode)//unicodesprintf_s(dest, MAX_STRING_SIZE, "L\"%s\"", string);else if (strtype == str_utf8)sprintf_s(dest, MAX_STRING_SIZE, "F\"%s\"", string);return true;}}return false;
}

修改后即可在字符串参考中正确解析处UTF-8字符。

三、界面显示修改

在寄存器及堆栈的标签、备注显示方式中使用“string:module.label”形式,
并增加了PEB和TEB自动注释的功能


及CPU Dump窗口多种编码同时显示功能。

由于只是UI的操作,此处就不贴代码了

附件:

可编译源码 及 x64dbg修改版:
下载地址一:
链接:https://pan.baidu.com/s/1zEy0o_D3HJz1R5kUfKOj-Q
提取码:3jpm
复制这段内容后打开百度网盘手机App,操作更方便哦
下载地址二:
编译后软件:x64dbg_2021_01_12(Modified By 风吹小裤衩(20210329))
软件源码:x64dbg_2021_01_12源码(Modified By 风吹小裤衩(20210329))

不足之处,欢迎报告Bug

X64dbg 2021最新版 中文乱码解决相关推荐

  1. java中文乱码解决之道(二)—–字符编码详解:基础知识 + ASCII + GB**

    原文出处:http://cmsblogs.com/?p=1412 在上篇博文(java中文乱码解决之道(一)-–认识字符集)中,LZ简单介绍了主流的字符编码,对各种编码都是点到为止,以下LZ将详细阐述 ...

  2. pycharm 运行控制台中文乱码解决办法

    pycharm 运行控制台中文乱码解决办法

  3. vs code中文乱码解决方法

    修改 1.(安装方法) 2.显示终端输入数据输出结果(完美解决) 3.修改部分:中文乱码解决方法 第一步: 第二步: 1.(安装方法) 转载于: https:blog.csdn.net/qq_4304 ...

  4. Zabbix 中文乱码解决

    Zabbix 中文乱码解决 1.在本地的C:\Windows\Fonts下选择自己喜欢的字体,此处选择黑体(我只测试过宋体,楷体,黑体,幼圆其他中文字体应该都支持) 在C:\Windows\Fonts ...

  5. Ubuntu10.04下gFtp2.0.19 远程客户端中文乱码解决方法

    Ubuntu10.04下gFtp2.0.19 远程客户端中文乱码解决方法如下: 1.打开"gFTP-FTP-属性-常规-远程字符集": 2.将远程字符集设置为:gb2312,gbk ...

  6. navicat for mysql 显示中文乱码解决办法

    navicat for mysql 显示中文乱码解决办法   最近遇到一个问题,用navicat for mysql 打开数据库时全都显示的是乱码(在用程序代码插入数据之前确保字符不是乱码),遇到问题 ...

  7. python cmd 窗口 中文乱码 解决方法 (附:打印不同颜色)

    python cmd 窗口 中文乱码 解决方法 (附:打印不同颜色) 参考文章: (1)python cmd 窗口 中文乱码 解决方法 (附:打印不同颜色) (2)https://www.cnblog ...

  8. Sublime Text 3中文乱码解决方法以及安装包管理器方法

    Sublime Text 3中文乱码解决方法以及安装包管理器方法 参考文章: (1)Sublime Text 3中文乱码解决方法以及安装包管理器方法 (2)https://www.cnblogs.co ...

  9. axios请求GBK页面中文乱码解决方法

    axios请求GBK页面中文乱码解决方法 参考文章: (1)axios请求GBK页面中文乱码解决方法 (2)https://www.cnblogs.com/bjhl/articles/10514038 ...

最新文章

  1. EigenUbuntu下的配置
  2. python 慕课课程笔记(一)
  3. 【Python基础】在pandas中使用pipe()提升代码可读性
  4. 将Sublime Text3添加到右键菜单中
  5. ai电磁组属于什么组_RPA+AI 创新案例挑战赛 2020 【专业组】amp;【校园组】优胜名单来也!...
  6. Java 面试题(3)—— JVM
  7. Linux中远程文件的传输
  8. 史上最全MySQL锁机制
  9. 通过AccessKey调用阿里云CDN接口刷新CDN资源案例
  10. python导入xlsx转为csv_Python 拆分工作表为单个工作簿
  11. 第六届华为创新杯编程大赛第二轮(2014.4.29)
  12. 磁盘加密工具-TrueCrypt
  13. labview霍夫曼编码_毕业设计 基于LabVIEW的编码的设计与仿真—信源编码
  14. pano2vr输出的HTML手机可以看吗,Pano2VR怎么导出手机可看, Pano2VR导出手机查看教程...
  15. win8系统电脑使用技巧的详细介绍--win7w.com
  16. 海外服务器对外提供业务是否需要ICP许可证?
  17. 吐血推荐:“四无男”泡良 妞 实战攻略
  18. qt修改程序图标名称_【Qt开发】更改应用程序图标和任务栏图标
  19. innerText和innerHTML区别
  20. 化妆品电商平台数据分析报告

热门文章

  1. 64位处理器_CAD安装包32位跟64位有什么区别吗?
  2. 凝思linux操作系统4.2内核版本_国产自主操作系统:凝思磐石安全操作系统
  3. inpaint 9.1新版3秒去除一切图片中的无关元素
  4. FPGA linux synplify综合工程的环境搭建
  5. WSL 错误 System has not been booted with systemd as init system (PID 1). Can‘t operate
  6. 微信分享默认logo修改
  7. 新手小白怎么学好PS平面设计?过来人经验总结
  8. 2018 数学建模 国赛(高教杯)-智能RGV的动态调度策略
  9. 【解决】小程序|微信公众号授权给第三方平台时报“没有绑定公众号”
  10. 车载硬盘录像机-从芯片层面来谈嵌入式DVR的发展