如何将已知的寄存器值告知 Hex-Rays 反编译器 (7.0)?

逆向工程 艾达 反编译
2021-06-27 11:13:32

我目前正在使用 IDA 7.0 处理具有加密字符串的二进制文件。加密的数据被复制到内存中的另一个位置,然后解密。我已经就地解密了字符串,但是由于访问字符串的方式,反编译器无法解析它们。

这是访问解密字符串的 ASM 示例:

mov     rcx, cs:StringTableOffset
lea     rax, cs:180000000h
lea     rcx, [rcx+rax+130A4h]
call    cs:GetModuleHandleA

出于反转的目的,StringTableOffset可以认为是 0,因此最终lea指令实际上只是将值移动0x1800130A4到 中rcx但是,反编译器不知道这一点,而是显示指针算术。

|| ((v11 = GetModuleHandleA((LPCSTR)(StringTableOffset + 0x1800130A4i64))

有什么方法可以向反编译器发出信号rcx(GetModuleHandleA 的参数)的值是已知的,以便它可以显示定义的字符串?

1个回答

您提出的具体问题的答案是:不是直接通过 UI,但可以使用插件。Hex-Rays SDK 中的示例插件 #18插件顶部的评论说:

* It shows how to specify a register value at a desired location.
* Such a functionality may be useful when the code to decompile is
* obfuscated and uses opaque predicates.

但是,您的问题有更好的答案。您显示的汇编代码通常由 MSVC 在访问 x64 上的全局数组或数据结构时生成。基本上,一个寄存器将被设置为包含模块的基地址(rax在上面的代码片段中),然后数组访问将被编码为[rax+r64+RVA_of_array],其中r64一些寄存器用于索引目的。

Hex-Rays 会跳过像这样的片段,但有一种方法可以修复它:即将内存表达式中的数字偏移量转换为 RVA。据我所知,目前没有办法通过 GUI 做到这一点(编辑:在下面的评论中,Igor Skochinsky 告诉我们如何通过 GUI 做到这一点),但您可以通过一个小的 IDAPython 脚本来做到这一点。

def make_rva(ea, n):
    idaapi.op_offset(ea, n, ida_nalt.REFINFO_RVAOFF | ida_nalt.REF_OFF64, idaapi.BADADDR, idaapi.get_imagebase(), 0)

现在,您可以make_rva通过提供指令地址和内存表达式作为第一个参数来运行该函数。第二个参数是操作数编号:左侧为 0,右侧为 1。这是我打开的数据库中的一个示例。前:

0000000180019AEC cmp     byte ptr [rcx+rdx+138C84h], 0

执行后make_rva(0x0000000180019AEC,0)

0000000180019AEC cmp     rva stru_180138C80.sectors_per_cluster[rcx+rdx], 0

我最近发布了一个恶意软件样本数据库,我对其进行了详尽分析,并在其中使用了这些技巧作为分析的一部分。你可以在这里获取数据库,然后跳转到地址0000000180014607查看效果。

编辑,2021 年 8 月 24 日:我向 Hex-Rays 报告了上面讨论的问题,Hex-Rays 在 7.6 中修复了它。