我试图反汇编我使用arm-linux-gnueabihf
编译到目标thumb-2
的ELF可执行文件。但是,ARM指令编码让我在调试反汇编程序时感到困惑。让我们考虑以下说明:
mov.w fp,#0
我使用objdump
和hopper
作为thumb-2指令进行了反汇编。该指令在内存中显示为4ff0000b
,这意味着它实际上是0b00f04f
(小端)。因此,指令的二进制编码是:
<00> 0000 1011 0000 0000 1111 0000 0100 1111
根据ARM体系结构手册,似乎所有thumb-2指令都应以111[10|01|11]
开头。因此,上述编码与任何thumb-2指令都不对应。此外,它不匹配A8.8.102(第484页)部分中的任何编码。
我错过了什么吗?
答案 0 :(得分:2)
我认为你忽略了宽Thumb-2编码不是像ARM编码这样的32位字的微妙区别,它们是一对16位半字(注意ARM ARM编码图上方的位编号)。因此,尽管半字本身是小端的,但它们仍然以相对于彼此的“正常”顺序存储。如果内存中的字节为4ff0000b
,则编码的实际指令为f04f 0b00
。
答案 1 :(得分:1)
thumb2是拇指指令集的扩展,以前是未定义的指令,现在已经定义了一些指令。 arm是一个完全不同的指令集。如果工具链没有给你提供关于拇指与手臂代码的线索,那么找出它的唯一方法就是从入口处的假设开始,然后从执行顺序进行反汇编,即使在那里你也可能找不到一些的代码。
你无法通过位模式区分拇指或拇指+拇指2伸展的手臂指令。还记得手臂指令在4字节边界上对齐,其中拇指是2字节,拇指2扩展不必与其父拇指在相同的4字节边界内,这使得这更加有趣。 (thumb + thumb2是由16位值的倍数组成的可变长度指令集)
如果你的所有代码都是拇指,并且那里没有arm指令,那么你仍然遇到可变长度指令集的问题,并且你必须按照执行顺序执行代码。例如,在.text中嵌入一个看起来像thumb2扩展的前半部分的数据值并不难,并通过一个真正的拇指2扩展跟随它,导致你的反汇编程序脱轨。基本变量字长度反汇编问题(以及打败简单反汇编程序的基本方法)。
16位字A,B,C,D
如果C + D是通过解码C已知的拇指2指令,则A表示拇指指令而B是类似于thumb2扩展的前半部分的数据值,则通过ram A线性解码是拇指指令B和C被解码为thumb2扩展,D实际上是thumb2扩展的后半部分,现在被解码为指令的前16位,并且关于如何解码或者如果它导致全部或多个以下说明要解码错误。
所以开始看看精灵是否告诉你一些东西,如果没有,那么你必须按照执行顺序通过代码(你必须对入口点做出假设)遵循所有可能的分支和线性执行将16位部分标记为第一个或附加的指令块,未标记的块不能被确定为指令与数据,必须小心。
是的,有可能玩其他游戏来击败反汇编程序,故意分支到thumb2指令的后半部分,这是手工制作的有效拇指指令或拇指指示2。
固定长度的指令集,如arm和mips,你可以线性解码,一些数据解码为奇怪或未定义的指令,但你的反汇编程序不会脱轨并且无法完成其工作。可变长度指令集,反汇编最多只是猜测......真正解码的唯一方法是以与处理器相同的方式执行指令。