反编译ARM64并了解分支目标边界

问题描述 投票:0回答:1

从arm64反编译代码时,如何知道无条件分支指令

b
是否分支到同一函数中的标签而不是其他函数?

最先进的反编译器如何识别分支目标是否仍在函数中还是一个新函数?他们是否依赖分支目标的值并查看它是否落在

TEXT
段中的不同部分?
位于相同部分但仍被视为新功能的分支目标又如何呢? ARM64 是否有一条经验法则说,如果分支目标距当前地址某个阈值太远,则将其视为新边界,从而视为新函数?就像在 x86 中,远跳转和短跳转有不同的编码,其中短跳转可能被视为函数中的标签,而远跳转可能不会。

我可能会补充一点,我现在正在检查的目标二进制文件是用 Objective-C 编写的 Machos,并且我尝试使用 Ghidra 验证我的发现,因此它可能会使用更多启发式方法,例如查看跳转目标是否在

 __stubs
部分或
__objc_stubs
部分,甚至分析块结构以识别更多程序(尽管从Ghidra反编译来看,最后一点似乎没有识别这些结构)?

objective-c arm64 decompiling mach-o
1个回答
0
投票

从arm64反编译代码时,如何知道无条件分支指令b是否分支到同一函数中的标签而不是其他函数?

你无法真正知道。您最多只能做出有根据的猜测。根据我的经验,即使是最先进的反编译器在这方面也很糟糕。好的允许用户手动覆盖此类检测。

核心问题是在汇编层面没有“函数”的概念。导出到 C 等高级语言的标签应该符合特定的 ABI,但对于其他任何东西,一切都是不可能的。即使是导出的东西,如果您遇到恶意作者(考虑:恶意软件),那么他们也可能会选择破坏此合同,以掩盖二进制文件的工作原理。但即使使用非恶意二进制文件,如果有人使用 Apple 支持的

-O3 -flto -moutline
来实现 arm64 目标,你也会陷入痛苦的境地。

您可以使用一些启发式方法:

  • x30 是否已保存在某处?
    通常这会通过

    stp x29, x30, [sp, ...]
    指令发生,并伴随着
    sp
    的减少。如果是这种情况,那么使用
    b
    您可能会看到同一函数内的分支。如果不是这种情况,那么您不知道这是尾调用还是同一函数内的跳转。

    假设:x30 用作链接寄存器。混淆器可以使用其他东西,例如通过

    adr x17, ...; b _func
    进行函数调用,然后
    x17
    就是链接寄存器。这也可以按功能随机化。

  • 当前地址和跳转目标之间是否有函数?
    也许你的二进制文件有符号,也许LC_FUNCTION_STARTS,也许你的反编译已经识别出功能单元等等

    假设:函数的所有基本块都彼此相邻,并且不会分散和分散。通常情况就是这样,但同样,这种假设可以作为混淆技术的一部分被打破。

  • 跳转目标是否从其他函数跳转到?
    如果您已经确定代码中存在其他调用点属于不同的函数,则跳转目标不能属于这些函数中的任何一个。

    注意:功能概述,请参阅下一点。

  • 被调用的代码是否维护您期望从函数中输入和输出的 ABI?
    ABI 违规应该很容易确定。 ABI 一致性需要诸如显式寄存器溢出之类的东西来给您信心。但如果它符合预期的 ABI,那么它很可能是它自己的函数。如果不是,那么可能是跳转到它的函数的一部分,或者是概述的代码。

但这些都不能保证一定会成功,而且总会有两种选择都可行的情况。

© www.soinside.com 2019 - 2024. All rights reserved.