Double Free

Support HackTricks

Temel Bilgiler

Eğer bir bellek bloğunu birden fazla kez serbest bırakırsanız, bu, ayırıcı verilerini bozabilir ve saldırılara kapı açabilir. İşte bu nasıl olur: bir bellek bloğunu serbest bıraktığınızda, bu, serbest parçaların bir listesine geri döner (örneğin, "hızlı kutu"). Eğer aynı bloğu ardışık olarak iki kez serbest bırakırsanız, ayırıcı bunu tespit eder ve bir hata fırlatır. Ancak eğer araya başka bir parçayı serbest bırakırsanız, çift serbest bırakma kontrolü atlanır, bu da bozulmaya neden olur.

Artık yeni bellek talep ettiğinizde (malloc kullanarak), ayırıcı size iki kez serbest bırakılmış bir bloğu verebilir. Bu, iki farklı işaretçinin aynı bellek konumuna işaret etmesine neden olabilir. Eğer bir saldırgan bu işaretçilerden birini kontrol ederse, o bellek içeriğini değiştirebilir, bu da güvenlik sorunlarına yol açabilir veya hatta kod çalıştırmalarına izin verebilir.

Örnek:

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

Bu örnekte, tcache'i birkaç serbest bırakılmış parça (7) ile doldurduktan sonra, kod h parçasını serbest bırakır, ardından i parçasını serbest bırakır ve sonra tekrar h parçasını serbest bırakır, bu da bir double free'e neden olur (aynı zamanda Fast Bin dup olarak da bilinir). Bu, yeniden tahsis ederken üst üste binen bellek adresleri alma olasılığını açar, bu da iki veya daha fazla işaretçinin aynı bellek konumuna işaret edebileceği anlamına gelir. Bir işaretçi aracılığıyla verileri manipüle etmek, diğerini etkileyebilir ve bu da kritik bir güvenlik riski ve potansiyel bir istismar olanağı yaratır.

Bunu yürütürken, i1 ve i2'nin aynı adresi aldığını not edin:

Başlangıç tahsisleri:
a: 0xaaab0f0c22a0
b: 0xaaab0f0c22c0
c: 0xaaab0f0c22e0
d: 0xaaab0f0c2300
e: 0xaaab0f0c2320
f: 0xaaab0f0c2340
g: 0xaaab0f0c2360
h: 0xaaab0f0c2380
i: 0xaaab0f0c23a0
Yeniden tahsislerden sonra:
a1: 0xaaab0f0c2360
b1: 0xaaab0f0c2340
c1: 0xaaab0f0c2320
d1: 0xaaab0f0c2300
e1: 0xaaab0f0c22e0
f1: 0xaaab0f0c22c0
g1: 0xaaab0f0c22a0
h1: 0xaaab0f0c2380
i1: 0xaaab0f0c23a0
i2: 0xaaab0f0c23a0

Örnekler

  • Sadece 0x70 boyutunun dışında Fast-Bin boyutunda parçalar tahsis edebiliriz, bu da olağan __malloc_hook üzerine yazmayı engeller.

  • Bunun yerine, Fast Bin dup için hedef olarak 0x56 ile başlayan PIE adreslerini kullanıyoruz (1/2 şansı).

  • PIE adreslerinin saklandığı yerlerden biri main_arena'dır, bu Glibc içinde ve __malloc_hook'a yakındır.

  • Orada bir parça tahsis etmek için main_arena'nın belirli bir ofsetini hedef alıyoruz ve __malloc_hook'a ulaşana kadar parçalar tahsis etmeye devam ediyoruz.

  • Tcache kutularını ve bir null-byte taşmasını kullanarak bir double-free durumu elde edebiliriz:

  • 0x110 boyutunda üç parça tahsis ediyoruz (A, B, C)

  • B'yi serbest bırakıyoruz

  • A'yı serbest bırakıyoruz ve null-byte taşmasını kullanmak için tekrar tahsis ediyoruz

  • Artık B'nin boyut alanı 0x100, 0x111 yerine, bu yüzden tekrar serbest bırakabiliriz

  • 0x110 boyutunda bir Tcache-bin ve aynı adrese işaret eden 0x100 boyutunda bir tane var. Yani bir double free'imiz var.

  • Tcache poisoning kullanarak double free'i değerlendiriyoruz.

Referanslar

HackTricks'i Destekleyin

Last updated