ARM64 là instruction set architecture (ISA) của mọi Apple Silicon chip (A-series, M-series). Mọi code chạy trên iPhone đều là ARM64 machine code.


Tại Sao Cần Học

  • Kernel exploits yêu cầu đọc hiểu disassembly để tìm gadgets, hiểu control flow
  • PAC bypass cần hiểu PAC instructions (PACIA, AUTIA, …)
  • ROP/JOP chains xây dựng từ assembly gadgets
  • Debugger (lldb) hiển thị assembly, không phải C

Kiến Thức Cần Nắm

1. Registers

Register Mục đích
X0 - X7 Function arguments & return values (X0 = arg1 & return)
X8 Indirect result location (struct return)
X9 - X15 Temporary registers (caller-saved)
X16 (IP0) Intra-procedure scratch, cũng dùng cho PLT/stub calls
X17 (IP1) Intra-procedure scratch
X18 Platform register (reserved trên Apple platforms)
X19 - X28 Callee-saved registers
X29 (FP) Frame pointer
X30 (LR) Link register (return address)
SP Stack pointer (phải luôn 16-byte aligned)
PC Program counter (không truy cập trực tiếp như trên ARM32)
NZCV Condition flags: Negative, Zero, Carry, oVerflow

Special registers cho iOS exploitation:

  • W0 - W28: 32-bit view của X0-X28 (lower 32 bits)
  • TPIDR_EL1: Thread-local storage pointer cho kernel
  • TTBR0_EL1 / TTBR1_EL1: Translation Table Base Registers (page table pointers)
  • VBAR_EL1: Vector Base Address Register (exception handlers)
  • SCTLR_EL1: System Control Register

2. Instructions Thường Gặp Trong Exploit Analysis

Data Movement:

MOV X0, X1          ; X0 = X1
MOV X0, #0x1234     ; X0 = immediate value
MOVK X0, #0xABCD, LSL #16  ; Move with keep (set bits 16-31)
LDR X0, [X1]        ; X0 = *(uint64_t*)X1
LDR X0, [X1, #0x10] ; X0 = *(uint64_t*)(X1 + 0x10)
LDP X0, X1, [SP]    ; Load pair from stack
STR X0, [X1]        ; *(uint64_t*)X1 = X0
STP X29, X30, [SP, #-0x10]!  ; Push FP and LR to stack (pre-index)

Arithmetic & Logic:

ADD X0, X1, X2      ; X0 = X1 + X2
SUB X0, X1, #0x10   ; X0 = X1 - 0x10
AND X0, X1, #0xFF   ; X0 = X1 & 0xFF (masking)
ORR X0, X1, X2      ; X0 = X1 | X2
EOR X0, X1, X2      ; X0 = X1 ^ X2 (XOR)
LSL X0, X1, #4      ; X0 = X1 << 4
LSR X0, X1, #4      ; X0 = X1 >> 4 (logical shift)

Branching:

B label              ; Unconditional branch
BL function          ; Branch with link (function call, LR = return addr)
BR X16               ; Branch to register (indirect jump)
BLR X8               ; Branch with link to register (indirect call)
RET                  ; Return (branch to LR/X30)
CBZ X0, label        ; Branch if X0 == 0
CBNZ X0, label       ; Branch if X0 != 0
B.EQ label           ; Branch if equal (Z flag set)
B.NE label           ; Branch if not equal
B.GT / B.LT / B.GE / B.LE  ; Signed comparisons
B.HI / B.LO / B.HS / B.LS  ; Unsigned comparisons

Compare:

CMP X0, X1           ; Set flags based on X0 - X1
CMN X0, X1           ; Set flags based on X0 + X1
TST X0, #0x1         ; Set flags based on X0 & 0x1

System:

SVC #0x80            ; Supervisor call (syscall trên iOS/macOS)
MRS X0, CurrentEL    ; Read system register
MSR TTBR0_EL1, X0   ; Write system register
ISB                  ; Instruction Synchronization Barrier
DSB SY               ; Data Synchronization Barrier
TLBI                 ; TLB Invalidate

3. PAC Instructions (A12+)

PACIA X0, X1         ; Sign X0 with key A, context X1
PACIB X0, X1         ; Sign X0 with key B, context X1
PACIZA X0            ; Sign X0 with key A, zero context
AUTIA X0, X1         ; Authenticate X0 with key A, context X1
AUTIB X0, X1         ; Authenticate X0 with key B, context X1
XPACI X0             ; Strip PAC bits from X0 (no auth check)
BRAA X0, X1          ; Authenticate & branch (key A)
BLRAA X0, X1         ; Authenticate & branch with link (key A)
RETAB                ; Authenticate LR with key B & return

Ý nghĩa cho exploitation:

  • PACIA/PACIB thêm cryptographic signature vào pointer
  • AUTIA/AUTIB verify signature — nếu sai → pointer bị corrupt → crash
  • XPACI strip PAC bits mà không verify — hữu ích khi cần raw address
  • Signing gadgets dùng PACIA trên controlled input → forge valid PAC

4. Calling Convention (AAPCS64 — Apple variant)

Caller:
  1. Đặt arguments vào X0-X7 (integer) hoặc D0-D7 (float)
  2. Arguments > 8 đẩy lên stack
  3. BL function_name (LR = return address)

Callee (function prologue):
  STP X29, X30, [SP, #-frame_size]!   ; Save FP and LR
  MOV X29, SP                          ; Set up frame pointer

  ... function body ...

Callee (function epilogue):
  LDP X29, X30, [SP], #frame_size     ; Restore FP and LR
  RET                                   ; Return to caller

Apple-specific:

  • X18 reserved (platform register — do not touch)
  • Stack phải 16-byte aligned tại mọi thời điểm khi gọi function
  • Red zone: 128 bytes dưới SP có thể dùng mà không cần adjust SP (leaf functions)

5. Memory Model

Address space trên ARM64 iOS:

0x0000000000000000 ┐
                   │ Userspace (TTBR0_EL1)
0x0000007FFFFFFFFF ┘ (~512GB, thực tế iOS giới hạn 0x8000000000 = 32GB)

0xFFFF000000000000 ┐
                   │ Kernel space (TTBR1_EL1)
0xFFFFFFFFFFFFFFFF ┘

Exception Levels:

EL0 — Userspace (apps, daemons)
EL1 — Kernel (XNU)
EL2 — Hypervisor (SPTM trên iOS 17+; trước đó không dùng)
EL3 — Secure Monitor (iBoot, Secure Enclave communication)

Tài Nguyên Học

Beginner

Intermediate

  • Đọc disassembly output từ IDA/Ghidra cho iOS binaries thật
  • Viết inline assembly trong C và compile cho arm64
  • Debug iOS apps bằng lldb, đọc register state

Advanced

  • Phân tích kernel cache disassembly
  • Tìm PAC signing/auth gadgets trong system frameworks
  • Hiểu exception vector table (VBAR_EL1) và cách kernel handle traps

Bài Tập Thực Hành

  1. Viết “Hello World” bằng ARM64 assembly cho macOS (nếu có Apple Silicon Mac)
  2. Disassemble một binary iOS đơn giản bằng IDA/Ghidra, trace execution flow bằng tay
  3. Identify calling convention trong decompiled code: tìm arguments, return values, stack frame
  4. Tìm gadgets trong một Mach-O binary: sequences kết thúc bằng RET, BLR, hoặc BR
  5. Đọc PAC instructions trong kernelcache disassembly và hiểu chúng bảo vệ cái gì