如何在 IDA Pro 7.5 中将十六进制值转换为 16 位 Unicode?

逆向工程 艾达 编码 字符串 pe32
2021-06-12 14:18:37

上下文:

对于一个旨在让我们学习逆向工程以及如何使用 IDA Pro 的学生项目,我们必须对 APT28 款待恶意软件进行逆向工程(如本博文所述:https ://blog.xpnsec.com/apt28-hospitality -malware-part-2/ )

为此,我们提供了 IDA 教育许可证(7.5 版)和恶意 Word 文件。从 Word 文件中提取恶意软件后,我们可以开始对恶意软件进行逆向工程。

问题:

正如您在博客文章中所见,可以(以某种方式)使 IDA 解码load函数中设置的字符串(以下屏幕截图来自博客文章):

加载函数中的解码字符串,截图来自博文

然而,当我们试图重现这一点时,我们找不到办法做到这一点。如果我没记错的话,每条mov指令实际上将 2 个以 16 位(宽字符)unicode(UTF-8)编码的字符放入指定的地址(通过对 应用偏移量找到ebp)。我们可以通过查看 Ghidra 中的恶意软件来确认这一点:

Ghidra 中的同一部分,显示这些值是 16 位编码的 Unicode 字符

我试过的:

我尝试更改ENCODING变量的值,ida.cfg以便自动分析识别 UTF-8。(基于此:https : //www.hex-rays.com/products/ida/news/7_0/docs/strlits/

基于此页面IDA Convert to Unicode我尝试了两件事:

  • 选择我想转换的值,使用Alt- A,然后选择Unicode C-style (16 bits)
  • 选择存储值的所有地址(在Stack of load部分中),将它们转换为带有 的字符串A,然后Unicode C-style再次尝试转换为

当我尝试这 2 件事时,我最终在输出窗口中看到以下内容:

Command "SetStrlitStyle" failed.

最终目标:

最终,我可以继续与 Ghidra 合作,但目标是真正了解 IDA 的新知识并能够正确使用它。一定有我不明白的地方,我很想增加我对这个工具的了解。我们试着问老师,但他也不知道该怎么做。

任何帮助将非常感激。

2个回答

您链接的页面指出ENCODINGcfg 文件中的指令仅适用于 1-byte-per-unit (1bpu) 编码,而事实并非如此。UTF-16 是一种 2bpu 格式。

ENCODING指令很重要,因为 1bpu 字符的编码方式因您的文化而异。字符表中 32 和 126 之间的值通常相同,匹配 ASCII,但低值和扩展一半 (127-255) 取决于正在使用的字母编码,这是由当前文化定义的。这些编码在 ISO 8859 中定义,它为不同的文化定义了 14 种不同的编码。ISO 8859-1 (Latin-1) 是使用最广泛的,但其他值得注意的部分包括 8859-5(西里尔文)、8859-6(阿拉伯文)和 8859-8(希伯来文)。

这会变得有点复杂,因为这些字符集(通常称为代码页)的每个实现都有一点不同。虽然 ISO 8859-1“Latin-1”通常被认为是拉丁语言的定义标准,但您在实践中更有可能看到 Windows-1252,它向后兼容 ISO 8859-1 但包括许多扩展字符并定义控制代码的编码,例如\r\n

可以想象,这在分析时实际上是无法猜测的。这也很棘手,因为 UTF-8 是一种可变长度的多字节编码,它在很多时候使用 1bpu 来处理基本的 ASCII 范围字符。该字cafe在 ASCII、ISO 8859-1、Windows-1252 和 UTF-8 中编码为相同的字节。但是在 e 上添加一个重音,以获得café,并且编码各不相同,纯 ASCII 没有代码点é,ISO 8859-1 和 Windows-1252 都将其编码为E9,UTF-8 将其编码为C3A9. 如果您尝试反向执行此操作,ISO 8859-1 和 Windows-1252 将C3A9变成é,这是完全有效的,但显然不是预期的。

当您加载二进制文件时,IDA 会尝试根据操作系统的当前语言设置猜测使用了哪种 1bpu 编码。它使用检测到的编码(例如 Windows-1252)将它找到的任何 1bpu 字符串文字字节解码为可读字符。如果猜不出来,则默认为UTF-8。

如果检测到的编码不是 UTF-8,IDA 然后会根据它选择的字符编码选择一种文化每个文化都在一个.clt文件中定义,并定义了一些常见字符,这些字符存在于该特定文化的公共(类似 ASCII)范围之外。然后在检测字节序列是否可能是字符串文字时使用它。如果文化被错误地检测到,IDA 仍然能够识别 ASCII 字符串,但带有扩展字符(例如café)的字符串可能只显示为十六进制。

简而言之:对于 1bpu 字符串,IDA 检测编码以便能够将字节转换为可读字符串,并且(除非它是 UTF-8)它使用区域性定义来检测包含扩展代码点的字符串文字。

UTF-8 不受这些问题影响的原因是 UTF-8 只是 UTF-8 - 无论当前的文化或语言如何,代码点在任何地方都是相同的。

IDA 提供了两个可以影响这个过程的配置指令。第一个是ENCODING,它覆盖了第一步并提供用于解码 1bpu 字符的特定字符编码。第二个是CULTURE,它告诉 IDA.clt使用哪个文件来检测程序中哪些文字可能是字符串。

您的情况完全不受此影响,因此设置ENCODINGCULTURE不会帮助您。UTF-16 是一种 2bpu 编码,与 UTF-8 一样,根据文化没有不同的编码。

不幸的是,我不清楚你为什么会遇到那个特定的问题。首先要检查的是您没有在字符串文字样式对话框中选择“字符终止”选项,因为这些单个指令操作数不是终止字符串。我建议的另一件事是尝试将字符串解释为 big-endian (UTF16-BE),以防 IDA 尝试错误地转换字节顺序。

主要问题是所有字符串文字选项或命令都适用于字符串文字,即字符或代码点序列。在您的示例中没有完整的文字;它是从片段构建到堆栈变量中的。对于 8 位 (ASCII) 字符串,您可以使用 R 热键将数字转换为字符常量(例如 65h -> 'A'),但是由于嵌入了零,这不适用于 UTF-16 片段。

我认为您能做的最好的事情是收集连续复制到堆栈上的值(例如 ebp-14h,然后是 ebp-10h 等),在另一个内存区域或脚本中重建相应的数组,然后将其解码为 UTF-16。