<summary><strong>Naučite hakovanje AWS-a od nule do heroja sa</strong><ahref="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
* Ako želite da vidite svoju **kompaniju reklamiranu na HackTricks-u** ili da **preuzmete HackTricks u PDF formatu** proverite [**PLANOVE ZA PRIJATELJSTVO**](https://github.com/sponsors/carlospolop)!
* **Pridružite se** 💬 [**Discord grupi**](https://discord.gg/hRep4RUj7f) ili [**telegram grupi**](https://t.me/peass) ili nas **pratite** na **Twitteru** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
* **Podelite svoje hakovanje trikove slanjem PR-ova na** [**HackTricks**](https://github.com/carlospolop/hacktricks) i [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repozitorijume.
Kako bi se poboljšala efikasnost skladištenja blokova, svaki blok nije samo u jednoj povezanoj listi, već postoje različite vrste. To su alokacije memorije i postoji 5 vrsta alokacija: [62](https://sourceware.org/git/gitweb.cgi?p=glibc.git;a=blob;f=malloc/malloc.c;h=6e766d11bc85b6480fa5c9f2a76559f8acf9deb5;hb=HEAD#l1407) male alokacije, 63 velike alokacije, 1 nesortirana alokacija, 10 brzih alokacija i 64 tcache alokacije po niti.
Početna adresa za svaku nesortiranu, malu i veliku alokaciju je unutar istog niza. Indeks 0 nije korišćen, 1 je nesortirana alokacija, alokacije 2-64 su male alokacije, a alokacije 65-127 su velike alokacije.
Iako niti pokušavaju da imaju svoj sopstveni stek (videti [Arene](bins-and-memory-allocations.md#arenas) i [Podstekove](bins-and-memory-allocations.md#subheaps)), postoji mogućnost da će proces sa puno niti (kao što je veb server) **završiti deljenjem steka sa drugim nitima**. U tom slučaju, glavno rešenje je korišćenje **brava**, koje mogu **znatno usporiti niti**.
Stoga, tcache je sličan brzoj alokaciji po niti na način da je to **jednostruko povezana lista** koja ne spaja blokove. Svaka nit ima **64 jednostruko povezane tcache alokacije**. Svaka alokacija može imati maksimalno [7 blokova iste veličine](https://sourceware.org/git/?p=glibc.git;a=blob;f=malloc/malloc.c;h=2527e2504761744df2bdb1abdc02d936ff907ad2;hb=d5c3fafc4307c9b7a4c7d5cb381fcdbfad340bcc#l323) u rasponu od [24 do 1032B na 64-bitnim sistemima i 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 blok, ako nije prevelik da bi bio alokovan u tcache i odgovarajuća tcache alokacija **nije puna** (već 7 blokova), **biće alokovan tamo**. Ako ne može ići u tcache, moraće da sačeka da se stek otključa kako bi mogao da izvrši globalnu operaciju oslobađanja.
Kada se **blok alokira**, ako postoji slobodan blok potrebne veličine u **Tcache-u, koristiće ga**, ako ne, moraće da sačeka da se stek otključa kako bi pronašao jedan u globalnim alokacijama ili kreirao novi.\
Postoji i optimizacija, u ovom slučaju, dok ima otključan stek, nit **će popuniti svoj Tcache sa stek blokovima (7) tražene veličine**, tako da ako mu je potrebno više, moći će da ih pronađe u Tcache-u.
U sledećem kodu je moguće videti **maksimalne binove** i **delove po indeksu**, **`tcache_entry`** strukturu kreiranu kako bi se izbegle duple oslobađanja i **`tcache_perthread_struct`**, strukturu koju svaka nit koristi za čuvanje adresa za svaki indeks bin-a.
```c
// From https://github.com/bminor/glibc/blob/f942a732d37a96217ef828116ebe64a644db18d7/malloc/malloc.c
/* We want 64 entries. This is an arbitrary limit, which tunables can reduce. */
Brze kante su dizajnirane da **ubrzaju dodelu memorije za male delove** tako što čuvaju nedavno oslobođene delove u strukturi sa brzim pristupom. 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, ono što se dešava ovde je da zaglavlje (pokazivač na prvi deo koji treba proveriti) uvek pokazuje na poslednji oslobođeni deo 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 se čuva 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 stavljena u zaglavlje.
Maksimalna veličina povezane liste je `0x80` i organizovane su tako da deo veličine `0x20-0x2f` bude u indeksu `0`, deo veličine `0x30-0x3f` bi bio u indeksu `1`...
Delovi u brzim kantama nisu označeni kao dostupni tako da se čuvaju kao delovi brzih kanti neko vreme umesto da mogu da se spoje sa drugim slobodnim delovima koji ih okružuju.
<summary>Dodajte primer brze binarne čestice</summary>
```c
#include <stdlib.h>
#include <stdio.h>
int main(void)
{
char *chunks[8];
int i;
// Loop to allocate memory 8 times
for (i = 0; i <8;i++){
chunks[i] = malloc(24);
if (chunks[i] == NULL) { // Check if malloc failed
fprintf(stderr, "Memory allocation failed at iteration %d\n", i);
return 1;
}
printf("Address of chunk %d: %p\n", i, (void *)chunks[i]);
}
// Loop to free the allocated memory
for (i = 0; i <8;i++){
free(chunks[i]);
}
return 0;
}
```
Zabeležite kako alociramo i oslobađamo 8 blokova iste veličine tako da popunjavaju tcache, a osmi je smešten u brzom bloku.
Kompajlirajte ga i debagujte sa prekidnom tačkom u ret opcode-u glavne funkcije. Zatim, pomoću gef-a možete videti popunjavanje tcache bin-a i jedan blok u brzom binu:
```bash
gef➤ heap bins
──────────────────────────────────────────────────────────────────────────────── Tcachebins for thread 1 ────────────────────────────────────────────────────────────────────────────────
───────────────────────────────────────────────────────────────────────── Fastbins for arena at 0xfffff7f90b00 ─────────────────────────────────────────────────────────────────────────
Neuređena kanta je **keš** koji koristi menadžer hipa kako bi ubrzao dodelu memorije. Evo kako funkcioniše: Kada program oslobodi deo, i ako taj deo ne može biti dodeljen u tcache ili brzoj kanti i ne sudara se sa vršnim delom, menadžer hipa ga ne stavlja odmah u određenu malu ili veliku kantu. Umesto toga, prvo pokušava da ga **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 "neuređena kanta".
Kada program **zatraži memoriju**, menadžer hipa **proverava neuređenu kantu** da vidi da li postoji deo dovoljne veličine. Ako pronađe jedan, odmah ga koristi. Ako ne pronađe odgovarajući deo u neuređenoj kanti, premesti sve delove sa ove liste u njihove odgovarajuće kante, bilo male ili velike, na osnovu njihove veličine.
Imajte na umu da ako se veći deo podeli na 2 polovine i ako je preostali deo veći od MINSIZE, biće vraćen nazad u neuređenu kantu. 
Dakle, neuređena kanta je način ubrzanja dodele memorije tako što brzo ponovno koristi nedavno oslobođenu memoriju i smanjuje potrebu za dugotrajnim pretragama i spajanjima.
Imajte na umu da čak i ako su delovi različitih kategorija, ako dostupan deo sudara sa drugim dostupnim delom (čak i ako su originalno pripadali različitim kantama), biće spojeni.
if (chunks[i] == NULL) { // Check if malloc failed
fprintf(stderr, "Memory allocation failed at iteration %d\n", i);
return 1;
}
printf("Address of chunk %d: %p\n", i, (void *)chunks[i]);
}
// Loop to free the allocated memory
for (i = 0; i <8;i++){
free(chunks[i]);
}
return 0;
}
```
Primetite kako alociramo i oslobađamo 9 blokova iste veličine tako da **popunjavaju tcache**, a osmi je smešten u unsorted bin jer je **prevelik za fastbin**, dok deveti nije oslobođen tako da deveti i osmi **ne budu spojeni sa vršnim blokom**.
Kompajlirajte i debagujte sa prekidnom tačkom u ret opcode-u iz glavne funkcije. Zatim pomoću gef-a možete videti popunjen tcache bin i jedan blok u unsorted binu:
```bash
gef➤ heap bins
──────────────────────────────────────────────────────────────────────────────── Tcachebins for thread 1 ────────────────────────────────────────────────────────────────────────────────
───────────────────────────────────────────────────────────────────────── Fastbins for arena at 0xfffff7f90b00 ─────────────────────────────────────────────────────────────────────────
Fastbins[idx=0, size=0x20] 0x00
Fastbins[idx=1, size=0x30] 0x00
Fastbins[idx=2, size=0x40] 0x00
Fastbins[idx=3, size=0x50] 0x00
Fastbins[idx=4, size=0x60] 0x00
Fastbins[idx=5, size=0x70] 0x00
Fastbins[idx=6, size=0x80] 0x00
─────────────────────────────────────────────────────────────────────── Unsorted Bin for arena at 0xfffff7f90b00 ───────────────────────────────────────────────────────────────────────
Mali binovi su brži od velikih binova, ali sporiji od brzih binova.
Svaki bin 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 binova gde treba alocirati prostor i ubacivanju i uklanjanju unosa sa ovih lista.
Ovako se računa veličina malog bina prema indeksu bina:
* Najmanja veličina: 2\*4\*indeks (npr. indeks 5 -> 40)
* Najveća veličina: 2\*8\*indeks (npr. indeks 5 -> 80)
```c
// From https://github.com/bminor/glibc/blob/a07e000e82cb71238259e674529c37c12dc7d423/malloc/malloc.c#L1711
if (chunks[i] == NULL) { // Check if malloc failed
fprintf(stderr, "Memory allocation failed at iteration %d\n", i);
return 1;
}
printf("Address of chunk %d: %p\n", i, (void *)chunks[i]);
}
// Loop to free the allocated memory
for (i = 0; i <8;i++){
free(chunks[i]);
}
chunks[9] = malloc(0x110);
return 0;
}
```
Primetite kako alociramo i oslobađamo 9 blokova iste veličine tako da **popunjavaju tcache**, a osmi je smešten u unsorted bin jer je **prevelik za fastbin**, dok deveti nije oslobođen pa deveti i osmi **neće biti spojeni sa vršnim blokom**. Zatim alociramo veći blok od 0x110 što dovodi do toga da **blok u unsorted binu pređe u small bin**.
Kompajlirajte i debagujte sa prekidnom tačkom u ret opcode-u glavne funkcije. Zatim, pomoću gef-a, možete videti popunjen tcache bin i jedan blok u small binu:
```bash
gef➤ heap bins
──────────────────────────────────────────────────────────────────────────────── Tcachebins for thread 1 ────────────────────────────────────────────────────────────────────────────────
───────────────────────────────────────────────────────────────────────── Fastbins for arena at 0xfffff7f90b00 ─────────────────────────────────────────────────────────────────────────
Fastbins[idx=0, size=0x20] 0x00
Fastbins[idx=1, size=0x30] 0x00
Fastbins[idx=2, size=0x40] 0x00
Fastbins[idx=3, size=0x50] 0x00
Fastbins[idx=4, size=0x60] 0x00
Fastbins[idx=5, size=0x70] 0x00
Fastbins[idx=6, size=0x80] 0x00
─────────────────────────────────────────────────────────────────────── Unsorted Bin for arena at 0xfffff7f90b00 ───────────────────────────────────────────────────────────────────────
[+] Found 0 chunks in unsorted bin.
──────────────────────────────────────────────────────────────────────── Small Bins for arena at 0xfffff7f90b00 ────────────────────────────────────────────────────────────────────────
Za razliku od malih kanti, koje upravljaju komadićima fiksnih veličina, **svaka velika kanta obrađuje opseg veličina komadića**. 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 sve veći, što znači da prva kanta može pokrivati komadiće od 512 do 576 bajtova, dok sledeća pokriva od 576 do 640 bajtova. Ovaj obrazac se nastavlja, pri čemu najveća kanta sadrži sve komadiće iznad 1MB.
Velike kante sporije rade u poređenju sa malim kantama jer moraju **sortirati i pretraživati listu različitih veličina komadića kako bi pronašle najbolje odgovarajuće** za alokaciju. Kada se komadić ubaci u veliku kantu, mora biti sortiran, a prilikom alokacije memorije, sistem mora pronaći odgovarajući komadić. Ovaj dodatni rad ih čini **sporijim**, ali budući da su velike alokacije manje uobičajene od malih, to je prihvatljiva trgovina.
Dve velike alokacije se vrše, zatim jedna se oslobađa (stavlja se u unsorted bin) i vrši se veća alokacija (premeštanje oslobođene u nesortirani bin u veliki bin).
Kompajlirajte to i debagujte sa prekidnom tačkom u ret opcode-u glavne funkcije. Zatim, pomoću gef-a možete videti popunjenost tcache bina i jedan chunk u velikom binu:
```bash
gef➤ heap bin
──────────────────────────────────────────────────────────────────────────────── Tcachebins for thread 1 ────────────────────────────────────────────────────────────────────────────────
All tcachebins are empty
───────────────────────────────────────────────────────────────────────── Fastbins for arena at 0xfffff7f90b00 ─────────────────────────────────────────────────────────────────────────
Fastbins[idx=0, size=0x20] 0x00
Fastbins[idx=1, size=0x30] 0x00
Fastbins[idx=2, size=0x40] 0x00
Fastbins[idx=3, size=0x50] 0x00
Fastbins[idx=4, size=0x60] 0x00
Fastbins[idx=5, size=0x70] 0x00
Fastbins[idx=6, size=0x80] 0x00
─────────────────────────────────────────────────────────────────────── Unsorted Bin for arena at 0xfffff7f90b00 ───────────────────────────────────────────────────────────────────────
[+] Found 0 chunks in unsorted bin.
──────────────────────────────────────────────────────────────────────── Small Bins for arena at 0xfffff7f90b00 ────────────────────────────────────────────────────────────────────────
[+] Found 0 chunks in 0 small non-empty bins.
──────────────────────────────────────────────────────────────────────── Large Bins for arena at 0xfffff7f90b00 ────────────────────────────────────────────────────────────────────────
// From https://github.com/bminor/glibc/blob/a07e000e82cb71238259e674529c37c12dc7d423/malloc/malloc.c#L1711
/*
Top
The top-most available chunk (i.e., the one bordering the end of
available memory) is treated specially. It is never included in
any bin, is used only if no other chunk is available, and is
released back to the system if it is very large (see
M_TRIM_THRESHOLD). Because top initially
points to its own bin with initial zero size, thus forcing
extension on the first malloc request, we avoid having any special
code in malloc to check whether it even exists yet. But we still
need to do so when getting memory from system, so we make
initial_top treat the bin as a legal but unusable chunk during the
interval between initialization and the first call to
sysmalloc. (This is somewhat delicate, since it relies on
the 2 preceding words to be zero during this interval as well.)
*/
/* Conveniently, the unsorted bin can be used as dummy top on first call */
#define initial_top(M) (unsorted_chunks (M))
```
Osnovno, ovo je deo koji sadrži sav trenutno dostupan heap. Kada se izvrši malloc, ako nema dostupnog slobodnog chunk-a za korišćenje, ovaj top chunk će smanjiti svoju veličinu pružajući potreban prostor. Pokazivač na Top Chunk se čuva u strukturi `malloc_state`.
Štaviše, na početku, moguće je koristiti nesortirani chunk kao top chunk.
<details>
<summary>Posmatrajte primer Top Chunk-a</summary>
```c
#include <stdlib.h>
#include <stdio.h>
int main(void)
{
char *chunk;
chunk = malloc(24);
printf("Address of the chunk: %p\n", (void *)chunk);
gets(chunk);
return 0;
}
```
Nakon kompajliranja i debagovanja sa prekidnom tačkom u ret opcode-u glavne funkcije, primetio sam da je malloc vratio adresu: `0xaaaaaaac12a0` i ovo su delovi:
Chunk(addr=0xaaaaaaac1ae0, size=0x20530, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA) ← top chunk
```
Gde se može videti da je vrhunski blok na adresi `0xaaaaaaac1ae0`. To nije iznenađenje jer je poslednji alocirani blok bio na `0xaaaaaaac12a0` sa veličinom `0x410` i `0xaaaaaaac12a0 + 0x410 = 0xaaaaaaac1ae0`.\
Takođe je moguće videti dužinu vrhunskog bloka na njegovom zaglavlju bloka:
Kada se koristi malloc i deo je podeljen (na primer, iz nevezane liste ili iz vršnog bloka), deo koji je kreiran od ostatka podeljenog dela naziva se Poslednje podsećanje i njegov pokazivač se čuva u strukturi `malloc_state`.
<summary><strong>Naučite hakovanje AWS-a od nule do heroja sa</strong><ahref="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
* Ako želite da vidite svoju **kompaniju reklamiranu na HackTricks-u** ili da **preuzmete HackTricks u PDF formatu** proverite [**PLANOVE ZA PRIJAVU**](https://github.com/sponsors/carlospolop)!
* **Pridružite se** 💬 [**Discord grupi**](https://discord.gg/hRep4RUj7f) ili [**telegram grupi**](https://t.me/peass) ili nas **pratite** na **Twitteru** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**