Double Free

Unterstütze HackTricks

Grundinformationen

Wenn du einen Block Speicher mehr als einmal freigibst, kann das die Daten des Allocators durcheinanderbringen und die Tür zu Angriffen öffnen. So passiert es: Wenn du einen Block Speicher freigibst, geht er zurück in eine Liste freier Blöcke (z. B. den "fast bin"). Wenn du denselben Block zweimal hintereinander freigibst, erkennt der Allocator dies und wirft einen Fehler. Aber wenn du dazwischen einen anderen Block freigibst, wird die Double-Free-Prüfung umgangen, was zu einer Beschädigung führt.

Wenn du jetzt neuen Speicher anforderst (mit malloc), könnte der Allocator dir einen Block geben, der zweimal freigegeben wurde. Dies kann dazu führen, dass zwei verschiedene Zeiger auf denselben Speicherort zeigen. Wenn ein Angreifer einen dieser Zeiger kontrolliert, kann er den Inhalt dieses Speichers ändern, was zu Sicherheitsproblemen führen oder ihm sogar ermöglichen kann, Code auszuführen.

Beispiel:

#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;
}

In diesem Beispiel, nachdem der Tcache mit mehreren freigegebenen Chunks (7) gefüllt wurde, freed der Code Chunk h, dann Chunk i und dann h erneut, was zu einem Double Free führt (auch bekannt als Fast Bin dup). Dies eröffnet die Möglichkeit, überlappende Speicheradressen beim Reallokieren zu erhalten, was bedeutet, dass zwei oder mehr Zeiger auf denselben Speicherort zeigen können. Das Manipulieren von Daten über einen Zeiger kann dann den anderen beeinflussen, was ein kritisches Sicherheitsrisiko und Potenzial für Ausnutzung schafft.

Beim Ausführen, beachten Sie, wie i1 und i2 die gleiche Adresse erhalten haben:

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

Beispiele

  • Wir können nur Fast-Bin-große Chunks außer der Größe 0x70 zuweisen, was das übliche __malloc_hook Überschreiben verhindert.

  • Stattdessen verwenden wir PIE-Adressen, die mit 0x56 beginnen, als Ziel für Fast Bin dup (1/2 Chance).

  • Ein Ort, an dem PIE-Adressen gespeichert sind, ist in main_arena, das sich innerhalb von Glibc und in der Nähe von __malloc_hook befindet.

  • Wir zielen auf einen bestimmten Offset von main_arena, um dort einen Chunk zuzuweisen und weiterhin Chunks zuzuweisen, bis wir __malloc_hook erreichen, um Codeausführung zu erhalten.

  • Mit Tcache-Bins und einem Null-Byte-Overflow können wir eine Double-Free-Situation erreichen:

  • Wir weisen drei Chunks der Größe 0x110 zu (A, B, C)

  • Wir geben B frei

  • Wir geben A frei und weisen erneut zu, um den Null-Byte-Overflow zu nutzen

  • Jetzt ist das Größenfeld von B 0x100, anstatt 0x111, sodass wir es erneut freigeben können

  • Wir haben einen Tcache-Bin der Größe 0x110 und einen der Größe 0x100, die auf dieselbe Adresse zeigen. Also haben wir einen Double Free.

  • Wir nutzen den Double Free mit Tcache poisoning

Referenzen

Support HackTricks

Last updated