Double Free
Reading time: 5 minutes
tip
Ucz się i ćwicz AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Ucz się i ćwicz GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Wsparcie HackTricks
- Sprawdź plany subskrypcyjne!
- Dołącz do 💬 grupy Discord lub grupy telegram lub śledź nas na Twitterze 🐦 @hacktricks_live.
- Dziel się trikami hackingowymi, przesyłając PR-y do HackTricks i HackTricks Cloud repozytoriów github.
Podstawowe informacje
Jeśli zwolnisz blok pamięci więcej niż raz, może to zakłócić dane alokatora i otworzyć drzwi do ataków. Oto jak to się dzieje: gdy zwalniasz blok pamięci, wraca on do listy wolnych kawałków (np. "szybki bin"). Jeśli zwolnisz ten sam blok dwa razy z rzędu, alokator to wykrywa i zgłasza błąd. Ale jeśli zwolnisz inny kawałek pomiędzy, sprawdzenie podwójnego zwolnienia jest omijane, co prowadzi do uszkodzenia.
Teraz, gdy poprosisz o nową pamięć (używając malloc
), alokator może dać ci blok, który został zwolniony dwa razy. Może to prowadzić do dwóch różnych wskaźników wskazujących na to samo miejsce w pamięci. Jeśli atakujący kontroluje jeden z tych wskaźników, może zmienić zawartość tej pamięci, co może powodować problemy z bezpieczeństwem lub nawet umożliwić im wykonanie kodu.
Przykład:
#include <stdio.h>
#include <stdlib.h>
int main() {
// Allocate memory for three chunks
char *a = (char *)malloc(10);
char *b = (char *)malloc(10);
char *c = (char *)malloc(10);
char *d = (char *)malloc(10);
char *e = (char *)malloc(10);
char *f = (char *)malloc(10);
char *g = (char *)malloc(10);
char *h = (char *)malloc(10);
char *i = (char *)malloc(10);
// Print initial memory addresses
printf("Initial allocations:\n");
printf("a: %p\n", (void *)a);
printf("b: %p\n", (void *)b);
printf("c: %p\n", (void *)c);
printf("d: %p\n", (void *)d);
printf("e: %p\n", (void *)e);
printf("f: %p\n", (void *)f);
printf("g: %p\n", (void *)g);
printf("h: %p\n", (void *)h);
printf("i: %p\n", (void *)i);
// Fill tcache
free(a);
free(b);
free(c);
free(d);
free(e);
free(f);
free(g);
// Introduce double-free vulnerability in fast bin
free(h);
free(i);
free(h);
// Reallocate memory and print the addresses
char *a1 = (char *)malloc(10);
char *b1 = (char *)malloc(10);
char *c1 = (char *)malloc(10);
char *d1 = (char *)malloc(10);
char *e1 = (char *)malloc(10);
char *f1 = (char *)malloc(10);
char *g1 = (char *)malloc(10);
char *h1 = (char *)malloc(10);
char *i1 = (char *)malloc(10);
char *i2 = (char *)malloc(10);
// Print initial memory addresses
printf("After reallocations:\n");
printf("a1: %p\n", (void *)a1);
printf("b1: %p\n", (void *)b1);
printf("c1: %p\n", (void *)c1);
printf("d1: %p\n", (void *)d1);
printf("e1: %p\n", (void *)e1);
printf("f1: %p\n", (void *)f1);
printf("g1: %p\n", (void *)g1);
printf("h1: %p\n", (void *)h1);
printf("i1: %p\n", (void *)i1);
printf("i2: %p\n", (void *)i2);
return 0;
}
W tym przykładzie, po wypełnieniu tcache kilkoma zwolnionymi kawałkami (7), kod zwalnia kawałek h
, następnie kawałek i
, a potem h
ponownie, co powoduje podwójne zwolnienie (znane również jako Fast Bin dup). Otwiera to możliwość uzyskania nakładających się adresów pamięci podczas ponownego przydzielania, co oznacza, że dwa lub więcej wskaźników może wskazywać na tę samą lokalizację pamięci. Manipulowanie danymi przez jeden wskaźnik może następnie wpłynąć na drugi, co stwarza krytyczne ryzyko bezpieczeństwa i potencjał do wykorzystania.
Wykonując to, zauważ, jak i1
i i2
uzyskały ten sam adres:
Initial allocations:
a: 0xaaab0f0c22a0
b: 0xaaab0f0c22c0
c: 0xaaab0f0c22e0
d: 0xaaab0f0c2300
e: 0xaaab0f0c2320
f: 0xaaab0f0c2340
g: 0xaaab0f0c2360
h: 0xaaab0f0c2380
i: 0xaaab0f0c23a0
After reallocations:
a1: 0xaaab0f0c2360
b1: 0xaaab0f0c2340
c1: 0xaaab0f0c2320
d1: 0xaaab0f0c2300
e1: 0xaaab0f0c22e0
f1: 0xaaab0f0c22c0
g1: 0xaaab0f0c22a0
h1: 0xaaab0f0c2380
i1: 0xaaab0f0c23a0
i2: 0xaaab0f0c23a0
Przykłady
- Dragon Army. Hack The Box
- Możemy przydzielać tylko kawałki o rozmiarze Fast-Bin, z wyjątkiem rozmiaru
0x70
, co zapobiega zwykłemu nadpisaniu__malloc_hook
. - Zamiast tego używamy adresów PIE, które zaczynają się od
0x56
jako celu dla Fast Bin dup (1/2 szansy). - Jednym z miejsc, w których przechowywane są adresy PIE, jest
main_arena
, który znajduje się w Glibc i blisko__malloc_hook
. - Celujemy w konkretny offset
main_arena
, aby przydzielić tam kawałek i kontynuować przydzielanie kawałków, aż dotrzemy do__malloc_hook
, aby uzyskać wykonanie kodu. - zero_to_hero. PicoCTF
- Używając Tcache bins i przepełnienia null-byte, możemy osiągnąć sytuację podwójnego zwolnienia:
- Przydzielamy trzy kawałki o rozmiarze
0x110
(A
,B
,C
) - Zwalniamy
B
- Zwalniamy
A
i przydzielamy ponownie, aby wykorzystać przepełnienie null-byte - Teraz pole rozmiaru
B
wynosi0x100
, zamiast0x111
, więc możemy je zwolnić ponownie - Mamy jeden Tcache-bin o rozmiarze
0x110
i jeden o rozmiarze0x100
, które wskazują na ten sam adres. Mamy więc podwójne zwolnienie. - Wykorzystujemy podwójne zwolnienie, używając Tcache poisoning
Odniesienia
tip
Ucz się i ćwicz AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Ucz się i ćwicz GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Wsparcie HackTricks
- Sprawdź plany subskrypcyjne!
- Dołącz do 💬 grupy Discord lub grupy telegram lub śledź nas na Twitterze 🐦 @hacktricks_live.
- Dziel się trikami hackingowymi, przesyłając PR-y do HackTricks i HackTricks Cloud repozytoriów github.