- 1、本文档共140页,可阅读全部内容。
- 2、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
- 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
查看更多
ARM 逆向
ARM 中基于 PC 的寻址
最近看 ARM 的反汇编,计算地址时搞得有点头晕,总结了两天,把总结的结果记录下来。还是那句话,网上的资料很零碎,多不可
信。
在 ARM 的代码中,经常会用到相对偏移,换句话说就是基于PC 的寻址,以PC 为基准,加上偏移后找到相对地址。听起来似乎是个
很简单的事情,但由于 ARM 指令的多样性,从 ARM 的指令机器码推算出偏移地址并不是一件简单的事情。
今天用一个例子讨论三种基于 PC 的寻址方式,相关的规则等等。看一段Thumb 指令:
先看 0x 处的指令:BL sub_8B84,对应的机器码是:F90EF000.
第 一个问题来了,Thumb 指令不是 16bit 吗?为何这个指令是 32bit?原因是ARMv7 中引入了新的指令模式Thumb-2,Thumb-2 允
许 16bit 和 32bit 的指令混合使用,添加了一些新指令,即兼顾了 ARM 体积小速度快的优点,又兼顾了 Thumb 低功耗的有点。在
Thumb-2 的模式 下如果指令 bit[15:11]=11101/11110/11111, 那么这条指令就是 32bit,否则就是 16bit. 这个 case 中
bit[15:8] = 0xF0, bit[15:11] = 11110, 属于 32bit 指令。
那么如何通过 0xF90EF000 实现从 0x 到 0x8B84 的偏移的?先要查阅Thumb-2 中 32bit BL 指令的格式。经查询,这条指令符
合如下格式:
套这个格式的时候,左边的 16bit 对应指令的低 16 位,右边的对应高 16 位。这条指令的参数:S=0,
imm10=0,J1=1,J2=1,imm11=0x10E
根 据公式算出 imm32 = 0x10E1 = 0x21C,因为 S=0 所以这是一个正数,向后跳转。为何要左移一位?因为 Thumb- 2 指令
的长度是 2 字节或者 4 字节,那么指令的开始地址最后一位一定是 0,所以在指令中把要存储的地址右移一位,节省空间。如果是
表示 ARM 指令的地址,那 么就要左移两位,原理是一样的。
回过头来再看PC 的值和要跳转的地址:0x8B84-0x =0x220,什么?居然不是 0x21C?原因是在执行这条指令的时候PC 的值并
不是 0x . 由于ARM 处理器采用的是流水线技术,使用指令预取,在执行一条指令的时候 PC 的 值是下下条指令的地址。那么
下下条指令地址要加多少呢?在 ARM 模式下是 4*2=8,在 Thumb 模式下是 2*2=4. 那么在 Thumb-2 模式下是多 少?也是 2*2=4,
虽然 Thumb-2 有些指令是 4 字节,但依然按照 2*2=4 来算。
所以 0x21C+4=0x220,一切都能说的通了。
再 看另外一条指令, 0x895E: BEQ loc_8A40, 机器码:0xD06F, 这是一个 16bit 的Thumb-2 指令。CPU 怎么知道这是 个
16bit 的指令的?前面已经说过了,如果这是个 32bit 的指令,那么bit[15:11]=11010,显然不符合标准。因而这是个 16bit 指
令。有了前面的基础,这个就好推算多了。先查 ARM 指令表,符合这个格式:
cond=0, imm8=0x6F
imm32 = 0x6F1 = 0xDE == 0x8A40- (0x895E+4)
解释圆满
最 后看 0x895A 处的指令:LDR R3,=0x2711,机器码:0x4B3D, 这也是一个 16bit 的Thumb-2 指令。显而易见的是 0x2711 超过
了 16bit 指令所能忍受的立即数大小,因而 0x2711 直接放在指令里,而是要放在其他地方,用指令里存储的偏移地址来索
引。还是 一样先查 ARM 指令表,找到符合的格式:
Rt=3, imm8=0x3D
imm32=0x3D2=0xF4
按此推论存放 0x2711 的地址:0x895A+4+0xF4=0x8A52
查看一下具体地址:
居然是 0x8A50,差了两个字节,怎么回事?
再仔细查看 ARM 指令说明,找到这么一行:
原来这个指令在寻址的时候要求字对齐(4 字节),因而会强制把 bit[1]设为 0,不巧的是我们这个PC 原来的值 bit[1]刚好是
1,所以PC 的值被减去了 2,又一次 大白了。
总的来说 ARM 指令的寻址多种多样,对于每一种寻址方式都需要仔细
文档评论(0)