aarch64架构汇编速成,用于逆向aarch64代码
学习资料:https://github.com/nzcv/note
重要寄存器
- x0~x7:传递子程序的参数和返回值,一般x0保存返回值
- x29:帧指针寄存器(FP),用于连接栈帧,使用时必须保存。(类似8064架构下的ebp)
- x30:链接寄存器(LR),用于保存子程序的返回地址
- x31:堆栈指针寄存器(SP),用于指向每个函数的栈顶。
重要指令
ADD指令
add x0, x1, #1 ; x0 = x1 + 1
第一个操作数是destination,后面两个操作数是source
#
表示立即数
STR指令
==》
STR X1, [SP,#0x20+var_10] ; var_10 = x1
LDR指令
《==
LDR X0, [SP,#0x20+var_18] ; x0 = var_18
BL/B/BR指令
- BL: Branch with Link (−16MB to +16MB)
- B : Branch (−2KB to +2KB)
- BR: Branch to register (Any value in register)
BL unk_639712B640 ; jump to printf with save lr
BL unk_639712B650 ; jump to getchar with save lr
B loc_639712B738 ; while(1)
BR X17 ; printf
ADPR指令
用 adrp 来辅助定位 经过随机化ASLR的地址
ADRP X8, #aGoing@PAGE ; "going ...... \n"
ADD X8, X8, #aGoing@PAGEOFF ; "going ...... \n"
- 得到一个大小为4KB的页的基址,而且在该页中有全局变量aGoing的地址
- 基址+偏移==真正地址, 存放在X8;
PLT调用特征
loc_639712B640 ; CODE XREF: main+28↓p
ADRP X16, #off_639713BFB0@PAGE ; X16 = PAGE(0x110000)
LDR X17, [X16,#off_639713BFB0@PAGEOFF] ; X17 = mem(X16 + offset) ; offset=00112000
ADD X16, X16, #off_639713BFB0@PAGEOFF ; X16 = X16 + offset
BR X17 ; printf
ARM调用约定
参数1~参数8 分别保存到 X0~X7 寄存器中 ,剩下的参数从右往左依次入栈,被调用者实现栈平衡,返回值存放在 X0 中
canary机制
关键指令
MRS X8, #3, c13, c0, #2
LDR X9, [X8,#0x28]
STUR X9, [X29,#var_8]
MRS(Move to Register from State register)指令读取状态寄存器,这里的意思是读取TPIDR_EL0寄存器,这个寄存器可以存储线程身份信息以便于管理,其作用相当于TLS(Thread Local Storage)。cookie信息存在线程身份信息中
之后把cookie读到栈中
switch case/if else
.text:0000000000000968 SUB SP, SP, #0x10
.text:000000000000096C MOV W8, #1 ;w8 临时变量
.text:0000000000000970 STR W0, [SP,#0x10+var_8] ;var8 = w0
.text:0000000000000974 LDR W0, [SP,#0x10+var_8] ;
.text:0000000000000978 CMP W0, W8 ;NZCV0010
.text:000000000000097C CSET W8, EQ ;W8 = Z = 0
.text:0000000000000980 TBNZ W8, #0, loc_988 ;NZ
.text:0000000000000984 B loc_994
.text:0000000000000988 ; ---------------------------------------------------------------------------
.text:0000000000000988
.text:0000000000000988 loc_988 ; CODE XREF: test12+18↑j
.text:0000000000000988 MOV W8, #0xA1
.text:000000000000098C STR W8, [SP,#0x10+var_4]
.text:0000000000000990 B loc_A2C
CSET和TBNZ理解为BNZ,识别出switch/case if/else结构即可
循环结构
和8086类似
数组汇编结构
- memset进行初始化, 然后进行单个初始化
- memcpy直接进行拷贝初始化