0

我正在尝试反汇编我使用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 页)中的任何编码都不匹配。

我错过了什么吗?

4

2 回答 2

2

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

于 2015-10-08T16:45:44.103 回答
1

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

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

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

16 位字 A、B、C、D

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

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

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

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

于 2015-10-08T19:04:10.250 回答