【问题标题】:Disassembly of a mixed ARM/Thumb2 ELF file混合 ARM/Thumb2 ELF 文件的反汇编
【发布时间】:2015-10-08 16:36:38
【问题描述】:

我正在尝试反汇编我使用arm-linux-gnueabihf 编译的ELF 可执行文件以定位thumb-2。但是,ARM 指令编码让我在调试反汇编程序时感到困惑。让我们考虑以下指令:

mov.w fp, #0

我使用 objdumphopper 作为 thumb-2 指令进行反汇编。该指令在内存中显示为4ff0000b,这意味着它实际上是0b00f04f(小端序)。因此,指令的二进制编码为:

0000 1011 0000 0000 1111 0000 0100 1111

根据 ARM 架构手册,似乎所有 thumb-2 指令都应以 111[10|01|11] 开头。因此,上述编码不对应于任何 thumb-2 指令。此外,它与 A8.8.102 节(第 484 页)中的任何编码都不匹配。

我错过了什么吗?

【问题讨论】:

    标签: arm disassembly thumb


    【解决方案1】:

    我认为您错过了宽 Thumb-2 编码不像 ARM 编码那样是 32 位字的细微区别,它们是一对 16 位半字(请注意 ARM ARM 编码图上方的位编号)。因此,虽然半字本身是小端的,但它们仍然以相对于彼此的“正常”顺序存储。如果内存中的字节为4ff0000b,那么实际编码的指令为f04f 0b00

    【讨论】:

      【解决方案2】:

      thumb2 是 thumb 指令集的扩展,以前未定义的指令,现在其中一些已定义。 arm 是一个完全不同的指令集。如果工具链没有给你留下关于什么代码是 thumb vs arm 的线索,那么弄清楚它的唯一方法是从入口点的假设开始,然后从那里按执行顺序反汇编,即使在那里你也可能不知道一些的代码。

      您无法仅通过位模式将 arm 指令与 thumb 或 thumb+thumb2 扩展区分开来。还要记住 arm 指令在 4 字节边界上对齐,其中 thumb 是 2 字节,而 thumb 2 扩展不必与其父拇指处于相同的 4 字节边界,这使得这一切变得更加有趣。 (thumb+thumb2 是由 16 位值的倍数组成的变长指令集)

      如果您的所有代码都是 thumb 并且其中没有 arm 指令,那么您仍然会遇到使用可变长度指令集时会遇到的问题,并且要正确处理,您必须按执行顺序遍历代码。例如,在 .text 中嵌入一个看起来像 thumb2 扩展的前半部分的数据值并不难,然后是一个真正的 thumb 2 扩展,导致你的反汇编程序脱轨。基本的可变字长反汇编问题(以及击败简单反汇编程序的基本方法)。

      16 位字 A、B、C、D

      如果 C + D 是通过解码 C 已知的 thumb 2 指令,A 是一个拇指指令,B 是一个类似于 thumb2 扩展的前半部分的数据值,那么通过 ram A 线性解码就是拇指指令B 和 C 被解码为 thumb2 扩展,而实际上是 thumb2 扩展的后半部分的 D 现在被解码为指令的前 16 位,所有关于它如何解码或者它是否会导致所有或许多以下指令被解码错误。

      所以开始看看精灵是否告诉你一些事情,如果没有,那么你必须按照所有可能的分支和线性的执行顺序通过代码(你必须对入口点做出假设)执行将 16 位段标记为指令的第一个或附加块,未标记的块不一定确定为指令与数据,必须小心。

      是的,可以玩其他游戏来击败反汇编程序,故意分支到 thumb2 指令的后半部分,该指令被手工制作为有效的 thumb 指令或 thumb2 的开始。

      固定长度的指令集,如 arm 和 mips,您可以线性解码,一些数据解码为奇怪或未定义的指令,但您的反汇编程序不会偏离轨道而无法完成工作。可变长度指令集,反汇编充其量只是一个猜测......真正解码的唯一方法是像处理器一样执行指令。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-05-04
        • 1970-01-01
        • 2011-12-24
        • 1970-01-01
        • 2012-05-13
        • 2013-08-04
        • 1970-01-01
        • 2011-03-12
        相关资源
        最近更新 更多