2016年9月17日星期六

ASM 逆向学习笔记 (一)- 汇编基础


因为安卓逆向时而需要分析在 .so 文件中定义的 natvie 函数,所以对汇编的指令伪代码也需要进行学习,在《Android软件安全与逆向分析》中的第六章针对部分指令有所讲述,不过例子感觉举的不太充分,下面对部分内容做一个备忘。

Register

R0 ~ R3 :用作传入函数参数,传出函数返回值,比方说 test 函数需要两个参数一个返回值,那么即使用 R0、R1 作为函数的参数,返回值保存在 R0 里。在子程序调用之间,可以将 R0 ~ R3 用于任何用途。 被调用函数在返回之前不必恢复。如果调用函数需要再次使用 R0 ~ R3 的内容,则它必须保留这些内容。

R4 ~ R11 :用作存放函数的局部变量,作用域是单个子程序。如果被调用函数使用了这些寄存器,它在返回之前必须恢复这些寄存器的值。在程序运行过程中,编译器会自动保护R4~R11。

R12:内部调用暂时寄存器 IP。它在过程链接胶合代码(例如,交互操作胶合代码)中用于此角色。 在过程调用之间,可以将它用于任何用途。被调用函数在返回之前不必恢复 R12。

R13:栈指针 SP,不能用于任何其它用途,SP 中存放的值在退出被调用函数时必须与进入时的值相同。 每一种异常模式都有其自己独立的r13,它通常指向异常模式所专用的堆栈,也就是说五种异常模式、非异常模式(用户模式和系统模式),都有各自独立的堆栈,用不同的堆栈指针来索引。这样当ARM进入异常模式的时候,程序就可以把一般通用寄存器压入堆栈,返回时再出栈,保证了各种模式下程序的状态的完整性。

R14:链接寄存器 LR,用于保存函数的返回地址。如果其他寄存器保存了函数返回地址,则可以在调用之间将 R14 用于其它用途,程序返回时要恢复。(1)保存子程序返回地址。使用BL或BLX时,跳转指令自动把返回地址放入 R14 中;子程序通过把 R14 复制到PC来实现返回。(2)当异常发生时,异常模式的 R14 用来保存异常返回地址,将 R14 如栈可以处理嵌套中断。

R15:程序计数器 PC,用于指向当前指令地址的指针。它不能用于任何其它用途。

Command

STR:STR{条件} 源寄存器,<存储器地址>

STR R0,[R1],#8     ;将 R0 中的字数据写入以 R1 为地址的存储器中,并将新地址 R1+8 写入 R1 。
STR R0, [R1, #8]   ;将 R0 中的字数据写入以 R1+8 为地址的存储器中。

LDR:LDR{条件} 目的寄存器,<存储器地址>

LDR R0,[R1,R2,LSL#2]!     ;将存储器地址为 R1+R2×4 的字数据读入寄存器 R0,并将新地址 R1+R2×4 写入 R1。
LDR R0,[R1],R2,LSL#2      ;将存储器地址为 R1 的字数据读入寄存器 R0,幵将新地址 R1+R2×4 写入 R1。
LDR R0,0x12345678           ;将 0x12345678 地址保存的数据放入 R0
LDR{cond}  register,=[expr | label-expr] ;伪代码

B 指令向前向后跳转的情况

cond_1: ;A
cmp r0, #0
beq cond_1f ; r0==0那么向前跳转到B处执行, f 表示 forward
bne cond_1b ; 否则向后跳转到A处执行, b 表示 backward
cond_1: ;B

感叹号[!]:可以用来使指令执行后,更新基底位地址。

LDR R0, [R1, #8]! ;[R1+8]->R0 
                 ;R1+8->R1
LDR R0!, {R1-R4}  ; R1=[R0], R2=[R0+#4]

Reference

Category: