首页 > 代码库 > Android 图解逆向工程中ARM常用汇编指令(一)

Android 图解逆向工程中ARM常用汇编指令(一)

我们走得太快,灵魂都跟不上了。
微小的幸福就在身边,容易满足就是天堂。



在逆向和爆破中我们经常会在IDA中接触到汇编,一般做安卓的不会太了解VB回编等,不太了解的同学可以先查看上篇文章《Android ARM常用的汇编指令合集》 再来继续我们的学习,我们先来看张图。

技术分享

这个view里面有 PUSH/LDR/SUB/MOVS/BLX/SUBS/BEQ/CMP ,这些差不多都是常见的,不过也不需要看得懂,理解这个指令即可,接下来我们就来分析下这些指令分别有什么作用吧。

先引入 概念性 东西,免得大家后面被搞混,那就是为什么会有S和!

  • S:指令执行后程序状态寄存器的条件标志位将被刷新 , 如ADDS R1,R0,#2
  • ! :指令中的地址表达式中含有!后缀时,指令执行后,基址寄存器中的地址值将发生变化,变化的结果是:基址寄存器中的值(指令执行后)=指令执行前的值 + 地址偏移量,如 LDR R3,[R0,#2]! 指令执行后,R0 = R0 + 2

接下来分别讲解这个View里面的指令分别有什么作用。

PUSH,顾名思义,直接PUSH进栈了。相反的,POP则为出栈了。

?指令示例:

  • PUSH{cond} reglist PUSH将寄存器推入满递减堆栈
  • PUSH {r0,r4-r7} 将R0,R4-R7寄存器内容压入堆栈
  • POP{cond} reglist POP从满递减堆栈中弹出数据到寄存器
  • POP {r0,r4-r7} 将R0,R4-R7寄存器从堆栈中弹出

LDR,指令语法:LDR{条件} 目的寄存器,<存储器地址>,LDR指令用于从存储器中将一个32位的字数据传送到目的寄存器中。该指令通常用于从存储器中读取32位的字数据到通用寄存器,然后对数据进行处理,当程序计数器PC作为 目的寄存器时,指令从存储器中读取的字数据被当作目的地址,从而可以实现程序流程的跳转。该指令在程序设计 中比较常用,且寻址方式灵活多样。
??详情可见上篇文章中 Ctrl + F 搜索《Android ARM常用的汇编指令合集》:加载/存储指令

?指令示例:

  • LDR R0,[R1] ;将存储器地址为R1的字数据读入寄存器R0。
  • LDR R0,[R1,R2] ;将存储器地址为R1+R2的字数据读入寄存器R0。

MOVS 、LDR 这些是跳转指令,直接向程序计数器PC写入跳转地址值,通过向程序计数器PC写入跳转地址值,可以实现在4GB的地址空间中的任意跳转,那有人会问,如果说从当前指令向前或向后的32MB的地址空间的跳转是怎么个实现原理?其实在 上篇文章中提及到了,它们是B\BL\BLX\BX 四大指令,这个我们最后才来讲解,其实它们有点像我们常说的分支结构,我们从图片里面选第四条指令作为查看数据。

技术分享

则可以看到,R5是原地址,其实为0xFF8->0x104A,复制返回地址到PC,实现子的返回,做安卓的同学可能会有个疑问,为什么有个S,因为语法就是 MOV{条件}{S} 目的寄存器+源操作数

看到这里大家可能会头晕,怎么感觉都是看不懂的数字,那其它那些,如ADD、等就给大家整理了一份表格。

助记符 指令功能描述 助记符 指令功能描述
ADD 加法指令 MRS 传送CPSR或SPSR的内容到通用寄存器指令
ADC 带进位加法指令 MRC 从协处理器寄存器到ARM寄存器的数据传输指令
AND 逻辑与指令 MSR 传送通用寄存器到CPSR或SPSR的指令
B 分支指令 MUL 32位乘法指令
BL 带返回的分支指令 BIC 位清零指令
BLX 带返回和状态切换的分支指令 MLA 32位乘加指令
BX 带状态切换的分支指令 MVN 数据取反传送指令
TST 位测试指令 ORR 逻辑或指令
CDP 协处理器数据操作指令 RSC 带错位的逆向减法指令
RSB 逆向减法指令 SBC 带错位减法指令
CMN 比较反值指令 CMP 比较指令
STC 协处理器寄存器写入存储器指令 EOR 异或指令
STM 批量内存字写入指令 LDC 存储器到协处理器的数据传输指令
STR 寄存器到存储器的数据存储指令 LDM 加载多个寄存器指令
SUB 减法指令 LDR 存储器到寄存器的数据加载指令
SWI 软件中断指令 MCR 从ARM寄存器到协处理器寄存器的数据传输指令
TEQ 相等测试指令 MOV 数据传送指令



SUBS 从表中可以看到,SUB是减法指令,如SUB R0,R1,R2则对应了R0 = R1 - R2,SUB R0,R1,#1 则是R0 = R1 -1,要注意的是 SUBS 是低32位相减。

BEQ 呢?!不要着急,来看下图
技术分享

BEQ 指令是跳转指令,但是跳转要满足一定的条件,满足则跳转执行,看下图红框部分。

技术分享

那就只剩下 CMP 了,CMP是比较指令,指令格式:CMP{条件} 操作数1,操作数2

?指令示例:

  • 如 CMP R1,#10,则等于比较R1和10,并设置CPSR的标志位。
  • CMP R1,R0 ;将寄存器R1的值与寄存器R0的值相减,并根据 结果设置CPSR的标志位
  • CMP R1,#100 ;将寄存器R1的值与立即数100相减,并根 据结果设置CPSR的标志位
  • 如果和BEQ一起使用话则是:CMP R1,#0 换行 BEQ Label ;当CPSR寄存器中的Z条件码置位时,程序跳转到标号Label处执行

OK , 从第一张图中我们看到后面跟的是两位,那如果是复杂一点的两位以上怎么看

?指令示例:

  • 先来看MOV的,如MOV R0,R1 , LSL R3 ,这个又是何解?其实它是将R1的值左移R3位,然后将结果存放到R0中 。
  • 再来看LDR的,LDR R0,[R1],R2 ,这个何解? 它是将存储器地址为R1的字数据读入寄存器R0,并将新地址R1+R2写入R1 , 要记住,R1是最终落地的地址 。

上篇文章中提及了其它更复杂的指令示例,不太明白这些可以看上篇文章的《Android ARM常用的汇编指令合集》,然后Ctrl + F 搜:数据加载/存储指令 或者搜索 数据处理指令,又或者搜索 自己需要的指令

|| 版权声明:本文为博主杜锦阳原创文章,转载请注明出处。http://blog.csdn.net/DJY1992/article/details/71404947

<script type="text/javascript"> $(function () { $(‘pre.prettyprint code‘).each(function () { var lines = $(this).text().split(‘\n‘).length; var $numbering = $(‘
    ‘).addClass(‘pre-numbering‘).hide(); $(this).addClass(‘has-numbering‘).parent().append($numbering); for (i = 1; i <= lines; i++) { $numbering.append($(‘
  • ‘).text(i)); }; $numbering.fadeIn(1700); }); }); </script>

    Android 图解逆向工程中ARM常用汇编指令(一)