一、ARM64 函數調用分析(匯編級)
寄存器規則(AArch64 ABI)
用途 | 寄存器 |
---|---|
參數傳遞 | x0 ~ x7 |
返回值 | x0(最多兩個:x0、x1) |
棧指針 | sp |
鏈接寄存器 | x30(lr) |
幀指針 | x29(fp) |
臨時/通用寄存器 | x9~x15等 |
函數調用指令流程
bl target_func ; 跳轉并將返回地址保存到 x30(link register)
ret ; 返回上一級,等價于 br x30
舉例
mov x0, #2
mov x1, #3
bl add_func ; 調用 add_func(2, 3)
二、棧幀結構詳解
每個函數調用會建立自己的“棧幀”,用于:
-
保存 caller 的寄存器(尤其是 x29, x30)
-
為局部變量騰出空間
-
管理多層調用時的上下文切換
標準函數前后結構
函數入口
stp x29, x30, [sp, #-16]! ; 保存 fp 和 lr,棧頂向下擴展 16 字節
mov x29, sp ; 新幀指針 = 當前棧頂
函數返回
ldp x29, x30, [sp], #16 ; 恢復幀指針和返回地址
ret ; 返回上一層
示例完整函數
func:stp x29, x30, [sp, #-16]! ; 建棧幀mov x29, sp// 函數體ldp x29, x30, [sp], #16 ; 恢復ret
三、棧幀結構圖解(棧向下增長)
高地址 ↑
───────────────上一幀 fp ← x29返回地址(lr) ← x30
───────────────局部變量區參數傳遞區(x8+)
───────────────當前 sp(棧底)
低地址 ↓
分析技巧:
-
IDA 里找
stp x29, x30, [sp,#-xxx]!
是函數入口特征 -
棧幀大小往往是 16 的倍數(對齊)
四、系統調用實現(Linux syscall in ARM64)
在裸匯編中實現 syscall 需要:
-
把 syscall 參數放入 x0~x5
-
把 syscall 編號放入 x8
-
執行
svc #0
發起系統調用
系統調用號對照
功能 | syscall 號 |
---|---|
write | 64 |
read | 63 |
openat | 56 |
mmap | 222 |
exit | 93 |
示例:調用 write 輸出字符串
匯編代碼(寫到 stdout)
.global _start.section .data
msg: .ascii "Hello ARM64!\n"
len = . - msg.section .text
_start:mov x0, #1 // stdoutldr x1, =msg // buf addressmov x2, #12 // lengthmov x8, #64 // syscall number: writesvc #0 // trigger syscall// exit(0)mov x0, #0mov x8, #93 // syscall number: exitsvc #0
編譯運行方式(Linux ARM64 模擬器或真機)
aarch64-linux-gnu-as hello.s -o hello.o
aarch64-linux-gnu-ld hello.o -o hello
qemu-aarch64 ./hello
五、逆向視角:系統調用識別
在 IDA 中看到以下指令,基本可以確認是系統調用:
mov x8, #64 ; syscall 編號
svc #0 ; 系統調用
結合調用前的 mov x0, #1
, ldr x1, =addr
, mov x2, #len
可以還原 syscall 是寫 stdout。
匯總圖(函數調用 → 棧幀 → syscall)
main:stp x29, x30, [sp, #-16]! // 保存mov x29, spmov x0, #1 // arg0: stdoutldr x1, =msg // arg1: buffer addrmov x2, #13 // arg2: lengthmov x8, #64 // syscall writesvc #0 // 發起調用ldp x29, x30, [sp], #16 // 恢復ret
六、總結
內容 | 關鍵點 |
---|---|
調用規則 | x0~x7 傳參,x30 返回地址 |
棧幀結構 | 使用 x29 做幀指針,函數內局部變量/保存寄存器都存在棧 |
系統調用 | x0~x5 參數, x8 syscall 號, svc #0 觸發 |
IDA/Ghidra逆向 | 找 stp/ldp , bl , svc 判斷函數入口、調用、syscall |
實戰環境 | 用 qemu + aarch64 工具鏈模擬也能練習 |