Translated ['binary-exploitation/heap/README.md'] to rs

This commit is contained in:
Translator 2024-05-09 18:09:00 +00:00
parent 510d9729b7
commit 6edc771dee
7 changed files with 203 additions and 8 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 224 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 224 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 296 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

View file

@ -1,17 +1,212 @@
# Heap
## Uvod
## Osnove Heap-a
U ovom odeljku ćemo istražiti napade na heap memoriju i kako ih iskoristiti u cilju izvršavanja zlonamernog koda. Heap je deo memorije koji se koristi za dinamičku alokaciju memorije tokom izvršavanja programa. Napadi na heap mogu rezultirati u preplavljivanju bafera, oslobađanju dvostruke memorije ili iskorišćavanju drugih slabosti u upravljanju memorijom.
Heap je osnovno mesto gde program može skladištiti podatke kada zahteva podatke pozivajući funkcije poput **`malloc`**, `calloc`... Osim toga, kada ti podaci više nisu potrebni, oni se oslobađaju pozivom funkcije **`free`**.
## Heap napadi
Kao što je prikazano, heap se nalazi odmah nakon što se binarni fajl učita u memoriju (proverite odeljak `[heap]`):
Heap napadi uključuju različite tehnike kao što su preplavljivanje bafera, napadi na pokazivače funkcija, napadi na upravljanje memorijom i još mnogo toga. Kroz ove tehnike, napadač može da kontroliše tok izvršavanja programa i izvrši proizvoljan kod.
<figure><img src="../../.gitbook/assets/image (1241).png" alt=""><figcaption></figcaption></figure>
## Eksploatacija heap-a
### Osnovna Aloakcija Blokova
Eksploatacija heap-a zahteva razumevanje unutrašnjeg rada heap-a i specifičnosti implementacije korišćene u ciljanom programu. Kroz pažljivo planiranje i korišćenje odgovarajućih tehnika, napadač može da iskoristi slabosti u upravljanju memorijom i ostvari svoje ciljeve.
Kada se zatraže podaci da budu smešteni u heap, određeni prostor heap-a se alocira za njih. Taj prostor će pripadati binu i samo traženi podaci + prostor zaglavlja bina + minimalno pomeranje veličine bina će biti rezervisani za blok. Cilj je rezervisati što manje memorije koliko je moguće, a da ne bude komplikovano pronaći gde se svaki blok nalazi. Za to se koriste informacije o metapodacima bloka kako bi se znalo gde se nalazi svaki zauzet/slobodan blok.
## Prevencija
Postoje različiti načini za rezervisanje prostora, uglavnom zavisno o korišćenom binu, ali opšta metodologija je sledeća:
Prevencija heap napada uključuje korišćenje sigurnosnih mehanizama kao što su korišćenje sigurnih funkcija za upravljanje memorijom, provere granica bafera i implementacija sigurnosnih politika za upravljanje memorijom. Redovno ažuriranje softvera i korišćenje alata za statičku analizu koda takođe mogu pomoći u sprečavanju heap napada.
* Program počinje sa zahtevanjem određene količine memorije.
* Ako u listi blokova postoji dovoljno veliki blok koji može ispuniti zahtev, on će biti korišćen.
* To može značiti čak i da će deo dostupnog bloka biti korišćen za ovaj zahtev, a ostatak će biti dodat na listu blokova.
* Ako nema dostupnog bloka u listi, ali još uvek postoji prostor u alociranoj memoriji heap-a, menadžer heap-a kreira novi blok.
* Ako nema dovoljno prostora u heap-u da alocira novi blok, menadžer heap-a traži od kernela da proširi memoriju alociranu za heap, a zatim koristi tu memoriju da generiše novi blok.
* Ako sve propadne, `malloc` vraća null.
Imajte na umu da ako tražena **memorija pređe prag**, koristiće se **`mmap`** za mapiranje tražene memorije.
### Arene
U **višenitnim** aplikacijama, menadžer heap-a mora sprečiti **trke za stanjem** koje bi mogle dovesti do rušenja. Početno je to bilo postignuto korišćenjem **globalne mutex**-a kako bi se osiguralo da samo jedna nit može pristupiti heap-u u isto vreme, ali to je uzrokovalo **probleme sa performansama** zbog uskog grla koje je prouzrokovala mutex.
Da bi se to rešilo, ptmalloc2 allocator heap-a je uveo "arene", gde **svaka arena** deluje kao **zaseban heap** sa svojim **sopstvenim** podacima **strukture** i **mutex**-om, omogućavajući više niti da obavljaju operacije heap-a bez mešanja, sve dok koriste različite arene.
Podrazumevana "glavna" arena upravlja operacijama heap-a za aplikacije sa jednom niti. Kada se dodaju **nove niti**, menadžer heap-a im dodeljuje **sekundarne arene** kako bi smanjio sukob. Prvo pokušava da pridruži svaku novu nit neiskorišćenoj areni, kreirajući nove ako je potrebno, do granice od 2 puta broja CPU jezgara za 32-bitne sisteme i 8 puta za 64-bitne sisteme. Kada se dostigne granica, **niti moraju deliti arene**, što može dovesti do potencijalnih sukoba.
Za razliku od glavne arene, koja se proširuje korišćenjem poziva sistema `brk`, sekundarne arene kreiraju "pod-heapove" korišćenjem `mmap` i `mprotect` kako bi simulirale ponašanje heap-a, omogućavajući fleksibilnost u upravljanju memorijom za višenitne operacije.
### Pod-heapovi
Pod-heapovi služe kao rezerve memorije za sekundarne arene u višenitnim aplikacijama, omogućavajući im da rastu i upravljaju svojim sopstvenim heap regionima odvojeno od glavnog heap-a. Evo kako se pod-heapovi razlikuju od početnog heap-a i kako funkcionišu:
1. **Početni Heap vs. Pod-heapovi**:
* Početni heap se nalazi odmah nakon binarnog fajla programa u memoriji, i proširuje se korišćenjem poziva sistema `sbrk`.
* Pod-heapovi, korišćeni od strane sekundarnih arena, kreiraju se kroz `mmap`, poziv sistema koji mapira određenu memorijsku regiju.
2. **Rezervacija Memorije sa `mmap`**:
* Kada menadžer heap-a kreira pod-heap, rezerviše veliki blok memorije kroz `mmap`. Ova rezervacija ne alocira memoriju odmah; jednostavno označava region koji druge sistemskih procesi ili alokacije ne bi trebali koristiti.
* Podrazumevana veličina rezervisana za pod-heap je 1 MB za 32-bitne procese i 64 MB za 64-bitne procese.
3. **Postepeno Proširenje sa `mprotect`**:
* Rezervisani memorijski region je početno označen kao `PROT_NONE`, što znači da kernel ne mora alocirati fizičku memoriju za ovaj prostor još.
* Da bi "proširio" pod-heap, menadžer heap-a koristi `mprotect` da promeni dozvole stranice sa `PROT_NONE` na `PROT_READ | PROT_WRITE`, što podstiče kernel da alocira fizičku memoriju na prethodno rezervisane adrese. Ovaj postepeni pristup omogućava pod-heapu da se proširi po potrebi.
* Kada se ceo pod-heap iscrpi, menadžer heap-a kreira novi pod-heap da nastavi sa alokacijom.
### Metapodaci
Kao što je ranije komentarisano, ovi blokovi takođe imaju neke metapodatke, veoma dobro predstavljene na ovoj slici:
<figure><img src="../../.gitbook/assets/image (1242).png" alt=""><figcaption><p><a href="https://azeria-labs.com/wp-content/uploads/2019/03/chunk-allocated-CS.png">https://azeria-labs.com/wp-content/uploads/2019/03/chunk-allocated-CS.png</a></p></figcaption></figure>
Metapodaci obično su 0x08B što ukazuje na trenutnu veličinu bloka koristeći poslednja 3 bita da bi ukazali na:
* `A`: Ako je 1, dolazi iz pod-heapa, ako je 0, nalazi se u glavnoj areni
* `M`: Ako je 1, ovaj blok je deo prostora alociranog sa mmap i nije deo heap-a
* `P`: Ako je 1, prethodni blok je u upotrebi
Zatim, prostor za korisničke podatke, i na kraju 0x08B da bi ukazao na veličinu prethodnog bloka kada je blok dostupan (ili za skladištenje korisničkih podataka kada je alociran).
Osim toga, kada su dostupni, korisnički podaci se koriste da sadrže i neke podatke:
* Pokazivač na sledeći blok
* Pokazivač na prethodni blok
* Veličina sledećeg bloka na listi
* Veličina prethodnog bloka na listi
<figure><img src="../../.gitbook/assets/image (1243).png" alt=""><figcaption><p><a href="https://azeria-labs.com/wp-content/uploads/2019/03/chunk-allocated-CS.png">https://azeria-labs.com/wp-content/uploads/2019/03/chunk-allocated-CS.png</a></p></figcaption></figure>
Primetite kako povezivanje liste na ovaj način sprečava potrebu za imanjem niza gde je svaki pojedinačni blok registrovan.
## Zaštita od Oslobađanja
Kako bi se zaštitili od slučajne ili namjerne zloupotrebe funkcije `free`, pre izvršavanja svojih akcija vrši neke provere:
* Proverava da li je adresa [poravnata](https://sourceware.org/git/gitweb.cgi?p=glibc.git;a=blob;f=malloc/malloc.c;h=6e766d11bc85b6480fa5c9f2a76559f8acf9deb5;hb=HEAD#l4182) na granici od 8 bajtova ili 16 bajtova na granici od 64 bita (`(adresa % 16) == 0`), pošto _malloc_ osigurava da su sve alokacije poravnate.
* Proverava da li polje veličine bloka nije nemoguće - ili zato što je [premalo](https://sourceware.org/git/gitweb.cgi?p=glibc.git;a=blob;f=malloc/malloc.c;h=6e766d11bc85b6480fa5c9f2a76559f8acf9deb5;hb=HEAD#l4318), preveliko, nije poravnato, ili [bi preklapalo kraj adresnog prostora procesa](https://sourceware.org/git/gitweb.cgi?p=glibc.git;a=blob;f=malloc/malloc.c;h=6e766d11bc85b6480fa5c9f2a76559f8acf9deb5;hb=HEAD#l4175).
* Proverava da li blok leži [unutar granica arene](https://sourceware.org/git/gitweb.cgi?p=glibc.git;a=blob;f=malloc/malloc.c;h=6e766d11bc85b6480fa5c9f2a76559f8acf9deb5;hb=HEAD#l4318).
* Proverava da li je blok [već označen kao slobodan](https://sourceware.org/git/gitweb.cgi?p=glibc.git;a=blob;f=malloc/malloc.c;h=6e766d11bc85b6480fa5c9f2a76559f8acf9deb5;hb=HEAD#l4182) proverom odgovarajućeg bita "P" koji se nalazi u metapodacima na početku sledećeg bloka.
## Bins
Da bi se poboljšala efikasnost skladištenja delova, svaki deo nije samo u jednoj povezanoj listi, već postoje različite vrste. To su kante i postoji 5 vrsta kanti: [62](https://sourceware.org/git/gitweb.cgi?p=glibc.git;a=blob;f=malloc/malloc.c;h=6e766d11bc85b6480fa5c9f2a76559f8acf9deb5;hb=HEAD#l1407) male kante, 63 velike kante, 1 nesortirana kanta, 10 brzih kanti i 64 kante tcache po niti.
Početna adresa za svaku nesortiranu, malu i veliku kantu je unutar istog niza. Indeks 0 se ne koristi, 1 je nesortirana kanta, kante 2-64 su male kante, a kante 65-127 su velike kante.
### Male kante
Male kante su brže od velikih kanti, ali sporije od brzih kanti.
Svaka kanta od 62 će imati **delove iste veličine**: 16, 24, ... (sa maksimalnom veličinom od 504 bajta u 32 bitnom i 1024 u 64 bitnom režimu). Ovo pomaže u brzini pronalaženja kante gde treba alocirati prostor i ubacivanju i uklanjanju unosa sa ovih lista.
### Velike kante
Za razliku od malih kanti, koje upravljaju delovima fiksnih veličina, svaka **velika kanta upravlja opsegom veličina delova**. Ovo je fleksibilnije, omogućavajući sistemu da se prilagodi **različitim veličinama** bez potrebe za posebnom kantom za svaku veličinu.
U alokatoru memorije, velike kante počinju tamo gde se završavaju male kante. Opsezi za velike kante postaju progresivno veći, što znači da prva kanta može obuhvatiti delove od 512 do 576 bajtova, dok sledeća obuhvata 576 do 640 bajtova. Ovaj obrazac se nastavlja, pri čemu najveća kanta sadrži sve delove iznad 1MB.
Velike kante su sporije za rad u poređenju sa malim kantama jer moraju **sortirati i pretraživati listu delova različitih veličina kako bi pronašle najbolje odgovarajući** za alokaciju. Kada se deo ubaci u veliku kantu, mora biti sortiran, a prilikom alokacije memorije, sistem mora pronaći odgovarajući deo. Ovaj dodatni rad ih čini **sporijim**, ali budući da su velike alokacije manje uobičajene od malih, to je prihvatljiva trgovina.
Postoje:
* 32 kante opsega 64B
* 16 kanti opsega 512B
* 8 kanti opsega 4096B
* 4 kante opsega 32768B
* 2 kante opsega 262144B
* 1 kanta za preostale veličine
### Nesortirana kanta
Nesortirana kanta je **brza keš memorija** koju koristi menadžer hipa kako bi ubrzao alokaciju memorije. Evo kako funkcioniše: Kada program oslobodi memoriju, menadžer hipa je ne stavlja odmah u određenu kantu. Umesto toga, prvo pokušava **da je spoji sa bilo kojim susednim slobodnim delovima** kako bi stvorio veći blok slobodne memorije. Zatim, smešta ovaj novi deo u opštu kantu nazvanu "nesortirana kanta".
Kada program **zatraži memoriju**, menadžer hipa **prvo proverava nesortiranu kantu** da vidi da li postoji deo odgovarajuće veličine. Ako pronađe jedan, odmah ga koristi, što je brže od pretrage kroz druge kante. Ako ne pronađe odgovarajući deo, premesti oslobođene delove u njihove odgovarajuće kante, bilo male ili velike, na osnovu njihove veličine.
Dakle, nesortirana kanta je način da se ubrza alokacija memorije brzim ponovnim korišćenjem nedavno oslobođene memorije i smanjenjem potrebe za vremenski zahtevnim pretragama i spajanjima.
{% hint style="danger" %}
Imajte na umu da čak i ako su delovi različitih kategorija, povremeno, ako dostupan deo se sudara sa drugim dostupnim delom (čak i ako su različitih kategorija), biće spojeni.
{% endhint %}
### Brze kante
Brze kante su dizajnirane da **ubrzaju alokaciju memorije za male delove** čuvanjem nedavno oslobođenih delova u strukturi brzog pristupa. Ove kante koriste pristup poslednji unutra, prvi napolje (LIFO), što znači da je **najskorije oslobođeni deo prvi** koji će biti ponovo korišćen kada postoji nova zahtev za alokacijom. Ovo ponašanje je korisno za brzinu, jer je brže ubaciti i ukloniti sa vrha steka (LIFO) u poređenju sa redom (FIFO).
Dodatno, **brze kante koriste jednostruko povezane liste**, a ne dvostruko povezane, što dodatno poboljšava brzinu. Budući da se delovi u brzim kantama ne spajaju sa susedima, nema potrebe za složenom strukturom koja omogućava uklanjanje iz sredine. Jednostruko povezana lista je jednostavnija i brža za ove operacije.
U osnovi, ovde se dešava da je zaglavlje (pokazivač na prvi deo koji treba proveriti) uvek usmereno ka poslednjem oslobođenom delu te veličine. Dakle:
* Kada se alocira novi deo te veličine, zaglavlje pokazuje na slobodan deo za korišćenje. Pošto ovaj slobodan deo pokazuje na sledeći deo za korišćenje, ova adresa je sačuvana u zaglavlju tako da sledeća alokacija zna gde da dobije dostupan deo
* Kada se deo oslobodi, slobodan deo će sačuvati adresu trenutno dostupnog dela i adresa ovog novootvorenog dela će biti smeštena u zaglavlje
{% hint style="danger" %}
Delovi u brzim kantama nisu automatski postavljeni kao dostupni tako da se zadržavaju kao delovi brzih kanti neko vreme umesto da mogu da se spoje sa drugim delovima.
{% endhint %}
### Tcache (Kante po niti)
Iako niti pokušavaju da imaju svoj sopstveni hip (videti [Arenas](./#arenas) i [Pod-hipovi](./#subheaps)), postoji mogućnost da će proces sa puno niti (kao što je veb server) **završiti deljenjem hipa sa drugim nitima**. U ovom slučaju, glavno rešenje je korišćenje **brava**, koje mogu **znatno usporiti niti**.
Stoga, tcache je slična brzoj kanti po niti na način da je **jednostruko povezana lista** koja ne spaja delove. Svaka nit ima **64 jednostruko povezane tcache kante**. Svaka kanta može imati maksimalno [7 delova iste veličine](https://sourceware.org/git/?p=glibc.git;a=blob;f=malloc/malloc.c;h=2527e2504761744df2bdb1abdc02d936ff907ad2;hb=d5c3fafc4307c9b7a4c7d5cb381fcdbfad340bcc#l323) u opsegu od [24 do 1032B na 64-bitnim sistemima i od 12 do 516B na 32-bitnim sistemima](https://sourceware.org/git/?p=glibc.git;a=blob;f=malloc/malloc.c;h=2527e2504761744df2bdb1abdc02d936ff907ad2;hb=d5c3fafc4307c9b7a4c7d5cb381fcdbfad340bcc#l315).
Kada **nit oslobodi** deo, **ako nije prevelik** da bi bio alociran u tcache i odgovarajuća tcache kanta **nije puna** (već 7 delova), **biće alociran tamo**. Ako ne može ići u tcache, moraće da sačeka da se hip zaključa kako bi mogao da izvrši globalnu operaciju oslobađanja.
Kada se **deo alocira**, ako postoji slobodan deo potrebne veličine u **tcache, biće korišćen**, ako ne, moraće da sačeka da se hip zaključa kako bi pronašao jedan u globalnim kantama ili napravio novi.\
Postoji i optimizacija, u ovom slučaju, dok ima zaključan hip, nit **će popuniti svoj tcache sa delovima hipa (7) tražene veličine**, tako da ako zatreba više, moći će da ih pronađe u tcache-u.
### Redosled binova
#### Za alokaciju:
1. Ako je dostupan blok u Tcache tog veličine, koristi Tcache
2. Ako je veoma velik, koristi mmap
3. Dobijanje zaključavanja hipa arene i:
1. Ako je dovoljno malih blokova od tražene veličine dostupno u brzim binovima, koristi ga i popuni tcache iz brzih binova
2. Proveri svaki unos u nesortiranoj listi tražeći jedan dovoljno velik blok i popuni tcache ako je moguće
3. Proveri male ili velike binove (u skladu sa traženom veličinom) i popuni tcache ako je moguće
4. Kreiraj novi blok od dostupne memorije
1. Ako nema dostupne memorije, dobij više koristeći `sbrk`
2. Ako se glavna memorija hipa ne može proširiti više, kreiraj novi prostor koristeći mmap
5. Ako ništa nije uspelo, vrati null
**Za oslobađanje:**
1. Ako je pokazivač Null, završi
2. Izvrši provere ispravnosti `free` u bloku kako bi se pokušalo verifikovati da je ispravan blok
1. Ako je dovoljno mali i tcache nije pun, stavi ga tamo
2. Ako je postavljen bit M (ne hip), koristi `munmap`
3. Dobij zaključavanje hipa arene:
1. Ako se uklapa u brz bin, stavi ga tamo
2. Ako je blok > 64KB, odmah konsoliduj brze binove i stavi rezultirajuće spojene blokove u nesortirani bin.
3. Spoji blok unazad i unapred sa susednim oslobođenim blokovima u malim, velikim i nesortiranim binovima ako ih ima.
4. Ako je na vrhu glave, spoji ga u neiskorišćenu memoriju
5. Ako nije prethodno navedeno, čuvaj ga u nesortiranoj listi
\
Brzi primer hipa sa [https://guyinatuxedo.github.io/25-heap/index.html](https://guyinatuxedo.github.io/25-heap/index.html) ali u arm64:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void main(void)
{
char *ptr;
ptr = malloc(0x10);
strcpy(ptr, "panda");
}
```
Postavite prekidnu tačku na kraju glavne funkcije i saznajmo gde je informacija sačuvana:
<figure><img src="../../.gitbook/assets/image (1239).png" alt=""><figcaption></figcaption></figure>
Moguće je videti da je string panda sačuvan na adresi `0xaaaaaaac12a0` (koja je bila adresa data kao odgovor od strane malloc unutar `x0`). Proveravajući 0x10 bajtova pre toga, moguće je videti da `0x0` predstavlja da **prethodni blok nije korišćen** (dužina 0) i da je dužina ovog bloka `0x21`.
Dodatni prostor rezervisan (0x21-0x10=0x11) dolazi od **dodatnih zaglavlja** (0x10) i 0x1 ne znači da je rezervisano 0x21B već poslednja 3 bita dužine trenutnog zaglavlja imaju neka posebna značenja. Pošto je dužina uvek poravnata na granicu od 16 bajtova (na 64-bitnim mašinama), ovi bitovi zapravo nikada neće biti korišćeni od strane broja dužine.
```
0x1: Previous in Use - Specifies that the chunk before it in memory is in use
0x2: Is MMAPPED - Specifies that the chunk was obtained with mmap()
0x4: Non Main Arena - Specifies that the chunk was obtained from outside of the main arena
```
##
## Reference
* [https://azeria-labs.com/heap-exploitation-part-1-understanding-the-glibc-heap-implementation/](https://azeria-labs.com/heap-exploitation-part-1-understanding-the-glibc-heap-implementation/)
* [https://azeria-labs.com/heap-exploitation-part-2-glibc-heap-free-bins/](https://azeria-labs.com/heap-exploitation-part-2-glibc-heap-free-bins/)