hacktricks/binary-exploitation/libc-heap
2024-06-16 09:03:34 +00:00
..
heap-memory-functions Translated ['binary-exploitation/arbitrary-write-2-exec/aw2exec-__malloc 2024-06-16 09:03:34 +00:00
use-after-free Translated ['binary-exploitation/arbitrary-write-2-exec/aw2exec-__malloc 2024-06-16 09:03:34 +00:00
bins-and-memory-allocations.md Translated ['binary-exploitation/arbitrary-write-2-exec/aw2exec-__malloc 2024-06-16 09:03:34 +00:00
double-free.md Translated ['binary-exploitation/arbitrary-write-2-exec/aw2exec-__malloc 2024-06-16 09:03:34 +00:00
fast-bin-attack.md Translated ['binary-exploitation/arbitrary-write-2-exec/aw2exec-__malloc 2024-06-16 09:03:34 +00:00
heap-overflow.md Translated ['binary-exploitation/arbitrary-write-2-exec/aw2exec-__malloc 2024-06-16 09:03:34 +00:00
house-of-einherjar.md Translated ['binary-exploitation/arbitrary-write-2-exec/aw2exec-__malloc 2024-06-16 09:03:34 +00:00
house-of-force.md Translated ['binary-exploitation/arbitrary-write-2-exec/aw2exec-__malloc 2024-06-16 09:03:34 +00:00
house-of-lore.md Translated ['binary-exploitation/arbitrary-write-2-exec/aw2exec-__malloc 2024-06-16 09:03:34 +00:00
house-of-orange.md Translated ['binary-exploitation/arbitrary-write-2-exec/aw2exec-__malloc 2024-06-16 09:03:34 +00:00
house-of-rabbit.md Translated ['binary-exploitation/arbitrary-write-2-exec/aw2exec-__malloc 2024-06-16 09:03:34 +00:00
house-of-roman.md Translated ['binary-exploitation/arbitrary-write-2-exec/aw2exec-__malloc 2024-06-16 09:03:34 +00:00
house-of-spirit.md Translated ['binary-exploitation/arbitrary-write-2-exec/aw2exec-__malloc 2024-06-16 09:03:34 +00:00
large-bin-attack.md Translated ['binary-exploitation/arbitrary-write-2-exec/aw2exec-__malloc 2024-06-16 09:03:34 +00:00
off-by-one-overflow.md Translated ['binary-exploitation/arbitrary-write-2-exec/aw2exec-__malloc 2024-06-16 09:03:34 +00:00
overwriting-a-freed-chunk.md Translated ['binary-exploitation/arbitrary-write-2-exec/aw2exec-__malloc 2024-06-16 09:03:34 +00:00
README.md Translated ['binary-exploitation/arbitrary-write-2-exec/aw2exec-__malloc 2024-06-16 09:03:34 +00:00
tcache-bin-attack.md Translated ['binary-exploitation/arbitrary-write-2-exec/aw2exec-__malloc 2024-06-16 09:03:34 +00:00
unlink-attack.md Translated ['binary-exploitation/arbitrary-write-2-exec/aw2exec-__malloc 2024-06-16 09:03:34 +00:00
unsorted-bin-attack.md Translated ['binary-exploitation/arbitrary-write-2-exec/aw2exec-__malloc 2024-06-16 09:03:34 +00:00

Heap

Heap Temelleri

Heap, bir programın malloc, calloc gibi fonksiyonları çağırarak veri istediğinde verileri depolayabileceği yerdir. Ayrıca, bu belleğe artık ihtiyaç duyulmadığında free fonksiyonu çağrılarak serbest bırakılır.

Görüldüğü gibi, bu bellek, binary belleğe yüklendikten hemen sonra ( [heap] bölümünü kontrol edin) bulunmaktadır:

Temel Parça Tahsisi

Heap'e depolanacak veri istendiğinde, heap'in bir kısmı buna ayrılır. Bu alan bir bine ait olacak ve yalnızca istenen veri + bin başlıklarının alanı + minimum bin boyutu ofseti parçaya ayrılacaktır. Amaç, her parçanın nerede olduğunu bulmayı karmaşık hale getirmeden mümkün olduğunca az bellek ayırmaktır. Bunun için, kullanılan/her parçanın nerede olduğunu bilmek için parça bilgileri kullanılır.

Kullanılan bine bağlı olarak alanı ayırmak için farklı yöntemler vardır, ancak genel bir metodoloji şöyledir:

  • Program belirli miktarda bellek isteyerek başlar.
  • İstek karşılayacak kadar büyük bir parça parça listesinde varsa, kullanılır.
  • Bu, isteğin bir kısmı için kullanılabilir parçanın kullanılacağı anlamına gelebilir ve geri kalanı parça listesine eklenir.
  • Liste içinde uygun bir parça yoksa ancak ayrılmış heap belleğinde hala yer varsa, heap yöneticisi yeni bir parça oluşturur.
  • Yeni bir parça tahsis etmek için yeterli heap alanı yoksa, heap yöneticisi çekirdeğe heap'e ayrılan belleği genişletmesini ister ve ardından bu belleği kullanarak yeni parçayı oluşturur.
  • Her şey başarısız olursa, malloc null döner.

İstenen belleğin bir eşiği geçerse, mmap kullanılarak istenen bellek eşlenir.

Arenalar

Çoklu iş parçacıklı uygulamalarda, heap yöneticisinin çökmelere yol açabilecek yarış koşullarını önlemesi gerekir. Başlangıçta, bunu sadece bir iş parçacığının aynı anda heap'e erişebileceğinden emin olmak için bir global kilitle yapardı, ancak bu, kilitleme nedeniyle performans sorunlarına yol açtı.

Bunu ele almak için, ptmalloc2 heap tahsisçısı, her birinin kendi veri yapıları ve kilidi olan ayrı bir heap olarak hareket eden "arenaları" tanıttı, böylece farklı arenaları kullansalar bile birden fazla iş parçacığının birbirini etkilemeden heap işlemleri yapmasına izin verir.

Varsayılan "ana" arena, tek iş parçacıklı uygulamalar için heap işlemlerini yönetir. Yeni iş parçacıkları eklendiğinde, heap yöneticisi çekişmeyi azaltmak için onlara ikincil arenalar atar. Her yeni iş parçacığını kullanılmayan bir arenaya eklemeye çalışır, gerektiğinde yeni arenalar oluşturur, 32 bit sistemler için CPU çekirdek sayısının 2 katı ve 64 bit sistemler için 8 katı kadar bir sınıra ulaşana kadar. Sınır aşıldığında, iş parçacıkları arenaları paylaşmak zorunda kalır, potansiyel çekişmelere yol açar.

Ana arenanın aksine, genişleyen brk sistem çağrısını kullanan ana arenalar, çoklu iş parçacıklı işlemler için belleği yönetme esnekliği sağlayan mmap ve mprotect kullanarak "alt heap"ler oluşturur.

Alt Heap'ler

Alt heap'ler, çoklu iş parçacıklı uygulamalardaki ikincil arenalar için bellek rezervleri olarak hizmet eder, böylece bunlar ana heap'ten ayrı olarak kendi heap bölgelerini büyütebilir ve yönetebilir. İşte alt heap'lerin başlangıç heap'inden nasıl farklı olduğu ve nasıl çalıştığı:

  1. Başlangıç Heap'i vs. Alt Heap'ler:
  • Başlangıç heap'i, programın binary'sinin hemen ardında bulunur ve sbrk sistem çağrısını kullanarak genişler.
  • İkincil arenalar tarafından kullanılan alt heap'ler, belirli bir bellek bölgesini eşleyen mmap kullanılarak oluşturulur.
  1. mmap ile Bellek Rezervasyonu:
  • Heap yöneticisi bir alt heap oluşturduğunda, mmap aracılığıyla büyük bir bellek bloğu rezerve eder. Bu rezervasyon hemen bellek tahsis etmez; sadece diğer sistem işlemlerinin veya tahsislerin kullanmaması gereken bir bölgeyi belirler.
  • Varsayılan olarak, 32 bit işlemler için bir alt heap için ayrılan boyut 1 MB, 64 bit işlemler için ise 64 MB'dir.
  1. mprotect ile Aşamalı Genişleme:
  • Rezerve edilen bellek bölgesi başlangıçta PROT_NONE olarak işaretlenir, bu da çekirdeğin bu alana henüz fiziksel bellek tahsis etmesi gerekmeyeceğini gösterir.
  • Alt heap'i "genişletmek" için, heap yöneticisi mprotect kullanarak sayfa izinlerini PROT_NONEdan PROT_READ | PROT_WRITE'a değiştirir, böylece çekirdek önceden rezerve edilen adreslere fiziksel bellek tahsis etmeye zorlanır. Bu adım adım yaklaşım, alt heap'in ihtiyaç duyuldukça genişlemesine olanak tanır.
  • Tüm alt heap tükenene kadar, heap yöneticisi devam etmek için yeni bir alt heap oluşturur.

heap_info

Bu yapı, heap'in ilgili bilgilerini ayırır. Ayrıca, daha fazla tahsis yapıldıktan sonra heap belleğinin sürekli olmayabileceği durumları da saklar.

// From https://github.com/bminor/glibc/blob/a07e000e82cb71238259e674529c37c12dc7d423/malloc/arena.c#L837

typedef struct _heap_info
{
mstate ar_ptr; /* Arena for this heap. */
struct _heap_info *prev; /* Previous heap. */
size_t size;   /* Current size in bytes. */
size_t mprotect_size; /* Size in bytes that has been mprotected
PROT_READ|PROT_WRITE.  */
size_t pagesize; /* Page size used when allocating the arena.  */
/* Make sure the following data is properly aligned, particularly
that sizeof (heap_info) + 2 * SIZE_SZ is a multiple of
MALLOC_ALIGNMENT. */
char pad[-3 * SIZE_SZ & MALLOC_ALIGN_MASK];
} heap_info;

malloc_state

Her heap (ana arena veya diğer thread'lerin arenaları) bir malloc_state yapısına sahiptir.
Önemli bir nokta, ana arena malloc_state yapısının libc içinde global bir değişken olduğudur (bu nedenle libc bellek alanında bulunur).
Thread'lerin arenalarının malloc_state yapıları durumunda, bunlar kendi thread "heap"lerinin içinde bulunur.

Bu yapıdan (aşağıdaki C koduna bakınız) dikkat çekici bazı şeyler vardır:

  • __libc_lock_define (, mutex); Bu, bu yapıya sadece 1 thread'in erişmesini sağlamak içindir
  • Bayraklar:

#define NONCONTIGUOUS_BIT (2U)

#define contiguous(M) (((M)->flags & NONCONTIGUOUS_BIT) == 0) #define noncontiguous(M) (((M)->flags & NONCONTIGUOUS_BIT) != 0) #define set_noncontiguous(M) ((M)->flags |= NONCONTIGUOUS_BIT) #define set_contiguous(M) ((M)->flags &= ~NONCONTIGUOUS_BIT)

* `mchunkptr bins[NBINS * 2 - 2];` küçük, büyük ve sırasız **bins**'lerin **ilk ve son parçalarına işaretçiler** içerir (-2, çünkü indeks 0 kullanılmaz)
* Dolayısıyla, bu bins'lerin **ilk parçası** bu yapıya **ters işaretçiye sahip olacak** ve bu bins'lerin **son parçası** bu yapıya **ileri işaretçiye sahip olacak**. Temelde, eğer bu adresleri **ana arenada sızdırabilirseniz**, **libc** içindeki yapıya bir işaretçiye sahip olacaksınız.
* `struct malloc_state *next;` ve `struct malloc_state *next_free;` yapılarının bağlı listeleri vardır
* `top` parçası son "parça"dır, yani temelde **tüm heap hatırlama alanıdır**. Top parçası "boş" olduğunda, heap tamamen kullanılmış olur ve daha fazla alan istenmesi gerekir.
* `last reminder` parçası, tam bir boyutta parça bulunamadığı durumlarda ve bu nedenle daha büyük bir parça bölündüğünde, buraya kalan kısım yerleştirilir.
```c
// From https://github.com/bminor/glibc/blob/a07e000e82cb71238259e674529c37c12dc7d423/malloc/malloc.c#L1812

struct malloc_state
{
/* Serialize access.  */
__libc_lock_define (, mutex);

/* Flags (formerly in max_fast).  */
int flags;

/* Set if the fastbin chunks contain recently inserted free blocks.  */
/* Note this is a bool but not all targets support atomics on booleans.  */
int have_fastchunks;

/* Fastbins */
mfastbinptr fastbinsY[NFASTBINS];

/* Base of the topmost chunk -- not otherwise kept in a bin */
mchunkptr top;

/* The remainder from the most recent split of a small request */
mchunkptr last_remainder;

/* Normal bins packed as described above */
mchunkptr bins[NBINS * 2 - 2];

/* Bitmap of bins */
unsigned int binmap[BINMAPSIZE];

/* Linked list */
struct malloc_state *next;

/* Linked list for free arenas.  Access to this field is serialized
by free_list_lock in arena.c.  */
struct malloc_state *next_free;

/* Number of threads attached to this arena.  0 if the arena is on
the free list.  Access to this field is serialized by
free_list_lock in arena.c.  */
INTERNAL_SIZE_T attached_threads;

/* Memory allocated from the system in this arena.  */
INTERNAL_SIZE_T system_mem;
INTERNAL_SIZE_T max_system_mem;
};

malloc_chunk

Bu yapı belirli bir bellek parçasını temsil eder. Çeşitli alanlar ayrılmış ve ayrılmamış parçalar için farklı anlamlara sahiptir.

// https://github.com/bminor/glibc/blob/master/malloc/malloc.c
struct malloc_chunk {
INTERNAL_SIZE_T      mchunk_prev_size;  /* Size of previous chunk, if it is free. */
INTERNAL_SIZE_T      mchunk_size;       /* Size in bytes, including overhead. */
struct malloc_chunk* fd;                /* double links -- used only if this chunk is free. */
struct malloc_chunk* bk;
/* Only used for large blocks: pointer to next larger size.  */
struct malloc_chunk* fd_nextsize; /* double links -- used only if this chunk is free. */
struct malloc_chunk* bk_nextsize;
};

typedef struct malloc_chunk* mchunkptr;

Daha önce belirtildiği gibi, bu parçaların da bazı meta verileri bulunmaktadır, bu meta veriler aşağıdaki resimde çok iyi temsil edilmiştir:

https://azeria-labs.com/wp-content/uploads/2019/03/chunk-allocated-CS.png

Meta veriler genellikle mevcut parça boyutunu belirten 0x08B değerini gösterir ve son 3 bit şunları belirtmek için kullanılır:

  • A: 1 ise alt heap'ten gelir, 0 ise ana arenada bulunur
  • M: 1 ise bu parça mmap ile ayrılan bir alana aittir ve heap'in bir parçası değildir
  • P: 1 ise önceki parça kullanımdadır

Ardından, kullanıcı verileri için alan ve son olarak parça kullanımda olduğunda önceki parça boyutunu belirtmek için 0x08B değeri bulunur (veya ayrıldığında kullanıcı verilerini saklamak için).

Ayrıca, kullanılabilir olduğunda, kullanıcı verileri aynı zamanda bazı verileri de içerecek şekilde kullanılır:

  • fd: Bir sonraki parçanın işaretçisi
  • bk: Önceki parçanın işaretçisi
  • fd_nextsize: Kendisinden daha küçük olan listenin ilk parçasına işaretçi
  • bk_nextsize: Kendisinden daha büyük olan listenin ilk parçasına işaretçi

https://azeria-labs.com/wp-content/uploads/2019/03/chunk-allocated-CS.png

{% hint style="info" %} Listeyi bu şekilde bağlamak, her bir parçanın kaydedilmesi gereken bir dizinin oluşturulmasına gerek olmadan listeyi oluşturmanın gerekliliğini ortadan kaldırır. {% endhint %}

Parça İşaretçileri

malloc kullanıldığında yazılabilir içeriğe işaret eden bir işaretçi döndürülür (başlık alanından hemen sonra), ancak parçalar yönetilirken, başlık alanının (meta veriler) başlangıcına bir işaretçiye ihtiyaç vardır. Bu dönüşümler için aşağıdaki fonksiyonlar kullanılır:

// https://github.com/bminor/glibc/blob/master/malloc/malloc.c

/* Convert a chunk address to a user mem pointer without correcting the tag.  */
#define chunk2mem(p) ((void*)((char*)(p) + CHUNK_HDR_SZ))

/* Convert a user mem pointer to a chunk address and extract the right tag.  */
#define mem2chunk(mem) ((mchunkptr)tag_at (((char*)(mem) - CHUNK_HDR_SZ)))

/* The smallest possible chunk */
#define MIN_CHUNK_SIZE        (offsetof(struct malloc_chunk, fd_nextsize))

/* The smallest size we can malloc is an aligned minimal chunk */

#define MINSIZE  \
(unsigned long)(((MIN_CHUNK_SIZE+MALLOC_ALIGN_MASK) & ~MALLOC_ALIGN_MASK))

Hizalama ve minimum boyut

Parçanın işaretçisi ve 0x0f değeri 0 olmalıdır.

// From https://github.com/bminor/glibc/blob/a07e000e82cb71238259e674529c37c12dc7d423/sysdeps/generic/malloc-size.h#L61
#define MALLOC_ALIGN_MASK (MALLOC_ALIGNMENT - 1)

// https://github.com/bminor/glibc/blob/a07e000e82cb71238259e674529c37c12dc7d423/sysdeps/i386/malloc-alignment.h
#define MALLOC_ALIGNMENT 16


// https://github.com/bminor/glibc/blob/master/malloc/malloc.c
/* Check if m has acceptable alignment */
#define aligned_OK(m)  (((unsigned long)(m) & MALLOC_ALIGN_MASK) == 0)

#define misaligned_chunk(p) \
((uintptr_t)(MALLOC_ALIGNMENT == CHUNK_HDR_SZ ? (p) : chunk2mem (p)) \
& MALLOC_ALIGN_MASK)


/* pad request bytes into a usable size -- internal version */
/* Note: This must be a macro that evaluates to a compile time constant
if passed a literal constant.  */
#define request2size(req)                                         \
(((req) + SIZE_SZ + MALLOC_ALIGN_MASK < MINSIZE)  ?             \
MINSIZE :                                                      \
((req) + SIZE_SZ + MALLOC_ALIGN_MASK) & ~MALLOC_ALIGN_MASK)

/* Check if REQ overflows when padded and aligned and if the resulting
value is less than PTRDIFF_T.  Returns the requested size or
MINSIZE in case the value is less than MINSIZE, or 0 if any of the
previous checks fail.  */
static inline size_t
checked_request2size (size_t req) __nonnull (1)
{
if (__glibc_unlikely (req > PTRDIFF_MAX))
return 0;

/* When using tagged memory, we cannot share the end of the user
block with the header for the next chunk, so ensure that we
allocate blocks that are rounded up to the granule size.  Take
care not to overflow from close to MAX_SIZE_T to a small
number.  Ideally, this would be part of request2size(), but that
must be a macro that produces a compile time constant if passed
a constant literal.  */
if (__glibc_unlikely (mtag_enabled))
{
/* Ensure this is not evaluated if !mtag_enabled, see gcc PR 99551.  */
asm ("");

req = (req + (__MTAG_GRANULE_SIZE - 1)) &
~(size_t)(__MTAG_GRANULE_SIZE - 1);
}

return request2size (req);
}

Parça verilerini alın ve meta verileri değiştirin

Bu işlevler, bir parça işaretçisi alarak çalışır ve meta verileri kontrol etmek/ayarlamak için kullanışlıdır:

  • Parça bayraklarını kontrol edin
// From https://github.com/bminor/glibc/blob/master/malloc/malloc.c


/* size field is or'ed with PREV_INUSE when previous adjacent chunk in use */
#define PREV_INUSE 0x1

/* extract inuse bit of previous chunk */
#define prev_inuse(p)       ((p)->mchunk_size & PREV_INUSE)


/* size field is or'ed with IS_MMAPPED if the chunk was obtained with mmap() */
#define IS_MMAPPED 0x2

/* check for mmap()'ed chunk */
#define chunk_is_mmapped(p) ((p)->mchunk_size & IS_MMAPPED)


/* size field is or'ed with NON_MAIN_ARENA if the chunk was obtained
from a non-main arena.  This is only set immediately before handing
the chunk to the user, if necessary.  */
#define NON_MAIN_ARENA 0x4

/* Check for chunk from main arena.  */
#define chunk_main_arena(p) (((p)->mchunk_size & NON_MAIN_ARENA) == 0)

/* Mark a chunk as not being on the main arena.  */
#define set_non_main_arena(p) ((p)->mchunk_size |= NON_MAIN_ARENA)
  • Boyutlar ve diğer parçaların işaretçileri
/*
Bits to mask off when extracting size

Note: IS_MMAPPED is intentionally not masked off from size field in
macros for which mmapped chunks should never be seen. This should
cause helpful core dumps to occur if it is tried by accident by
people extending or adapting this malloc.
*/
#define SIZE_BITS (PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)

/* Get size, ignoring use bits */
#define chunksize(p) (chunksize_nomask (p) & ~(SIZE_BITS))

/* Like chunksize, but do not mask SIZE_BITS.  */
#define chunksize_nomask(p)         ((p)->mchunk_size)

/* Ptr to next physical malloc_chunk. */
#define next_chunk(p) ((mchunkptr) (((char *) (p)) + chunksize (p)))

/* Size of the chunk below P.  Only valid if !prev_inuse (P).  */
#define prev_size(p) ((p)->mchunk_prev_size)

/* Set the size of the chunk below P.  Only valid if !prev_inuse (P).  */
#define set_prev_size(p, sz) ((p)->mchunk_prev_size = (sz))

/* Ptr to previous physical malloc_chunk.  Only valid if !prev_inuse (P).  */
#define prev_chunk(p) ((mchunkptr) (((char *) (p)) - prev_size (p)))

/* Treat space at ptr + offset as a chunk */
#define chunk_at_offset(p, s)  ((mchunkptr) (((char *) (p)) + (s)))
  • İnceleme yapın.
/* extract p's inuse bit */
#define inuse(p)							      \
((((mchunkptr) (((char *) (p)) + chunksize (p)))->mchunk_size) & PREV_INUSE)

/* set/clear chunk as being inuse without otherwise disturbing */
#define set_inuse(p)							      \
((mchunkptr) (((char *) (p)) + chunksize (p)))->mchunk_size |= PREV_INUSE

#define clear_inuse(p)							      \
((mchunkptr) (((char *) (p)) + chunksize (p)))->mchunk_size &= ~(PREV_INUSE)


/* check/set/clear inuse bits in known places */
#define inuse_bit_at_offset(p, s)					      \
(((mchunkptr) (((char *) (p)) + (s)))->mchunk_size & PREV_INUSE)

#define set_inuse_bit_at_offset(p, s)					      \
(((mchunkptr) (((char *) (p)) + (s)))->mchunk_size |= PREV_INUSE)

#define clear_inuse_bit_at_offset(p, s)					      \
(((mchunkptr) (((char *) (p)) + (s)))->mchunk_size &= ~(PREV_INUSE))
  • Başlık ve altbilgiyi ayarlayın (parça numaraları kullanıldığında)
/* Set size at head, without disturbing its use bit */
#define set_head_size(p, s)  ((p)->mchunk_size = (((p)->mchunk_size & SIZE_BITS) | (s)))

/* Set size/use field */
#define set_head(p, s)       ((p)->mchunk_size = (s))

/* Set size at footer (only when chunk is not in use) */
#define set_foot(p, s)       (((mchunkptr) ((char *) (p) + (s)))->mchunk_prev_size = (s))
  • Parçanın içindeki gerçek kullanılabilir veri boyutunu alın.
#pragma GCC poison mchunk_size
#pragma GCC poison mchunk_prev_size

/* This is the size of the real usable data in the chunk.  Not valid for
dumped heap chunks.  */
#define memsize(p)                                                    \
(__MTAG_GRANULE_SIZE > SIZE_SZ && __glibc_unlikely (mtag_enabled) ? \
chunksize (p) - CHUNK_HDR_SZ :                                    \
chunksize (p) - CHUNK_HDR_SZ + (chunk_is_mmapped (p) ? 0 : SIZE_SZ))

/* If memory tagging is enabled the layout changes to accommodate the granule
size, this is wasteful for small allocations so not done by default.
Both the chunk header and user data has to be granule aligned.  */
_Static_assert (__MTAG_GRANULE_SIZE <= CHUNK_HDR_SZ,
"memory tagging is not supported with large granule.");

static __always_inline void *
tag_new_usable (void *ptr)
{
if (__glibc_unlikely (mtag_enabled) && ptr)
{
mchunkptr cp = mem2chunk(ptr);
ptr = __libc_mtag_tag_region (__libc_mtag_new_tag (ptr), memsize (cp));
}
return ptr;
}

Örnekler

Hızlı Heap Örneği

https://guyinatuxedo.github.io/25-heap/index.html adresindeki hızlı heap örneği, ancak arm64'te:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void main(void)
{
char *ptr;
ptr = malloc(0x10);
strcpy(ptr, "panda");
}

Ana fonksiyonun sonunda bir kesme noktası belirleyin ve bilginin nerede saklandığını bulalım:

Görülebileceği gibi, dize panda 0xaaaaaaac12a0 adresinde saklandı (bu adres, x0 içinde malloc tarafından yanıt olarak verilen adresdi). Onun 0x10 byte öncesini kontrol etmek mümkün olduğunda, 0x0'ın önceki parçanın kullanılmadığını (uzunluğu 0) ve bu parçanın uzunluğunun 0x21 olduğunu görmek mümkündür.

Ekstra boşluklar ayrılmıştır (0x21-0x10=0x11) eklenen başlıklardan (0x10) ve 0x1, 0x21B ayrılmış olduğu anlamına gelmez, ancak mevcut başlığın uzunluğunun son 3 bitinin bazı özel anlamları vardır. Uzunluk her zaman 16 bayt hizalı olduğundan (64 bit makinelerde), bu bitler aslında uzunluk numarası tarafından asla kullanılmayacak.

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

Çoklu İş Parçacığı Örneği

Çoklu İş Parçacığı ```c #include #include #include #include #include <sys/types.h>

void* threadFuncMalloc(void* arg) { printf("Hello from thread 1\n"); char* addr = (char*) malloc(1000); printf("After malloc and before free in thread 1\n"); free(addr); printf("After free in thread 1\n"); }

void* threadFuncNoMalloc(void* arg) { printf("Hello from thread 2\n"); }

int main() { pthread_t t1; void* s; int ret; char* addr;

printf("Before creating thread 1\n"); getchar(); ret = pthread_create(&t1, NULL, threadFuncMalloc, NULL); getchar();

printf("Before creating thread 2\n"); ret = pthread_create(&t1, NULL, threadFuncNoMalloc, NULL);

printf("Before exit\n"); getchar();

return 0; }

</details>

Önceki örneği hata ayıkladığınızda başlangıçta sadece 1 arena olduğunu görmek mümkündür:

<figure><img src="../../.gitbook/assets/image (1).png" alt=""><figcaption></figcaption></figure>

Ardından, ilk ipliği çağıran, yani malloc'u çağıran iplik çağrıldıktan sonra yeni bir arena oluşturulur:

<figure><img src="../../.gitbook/assets/image (1) (1).png" alt=""><figcaption></figcaption></figure>

ve içinde bazı parçalar bulunabilir:

<figure><img src="../../.gitbook/assets/image (2).png" alt=""><figcaption></figcaption></figure>

## Bins & Bellek Tahsisleri/Boşaltmaları

Bakın hangi kovaların olduğuna ve nasıl düzenlendiğine ve belleğin nasıl tahsis edildiğine ve boşaltıldığına:

{% content-ref url="bins-and-memory-allocations.md" %}
[bins-and-memory-allocations.md](bins-and-memory-allocations.md)
{% endcontent-ref %}

## Heap Fonksiyonları Güvenlik Kontrolleri

Heap ile ilgili fonksiyonlar, işlemlerini gerçekleştirmeden önce belirli kontroller yapacak ve heap'in bozulmadığından emin olmaya çalışacaktır:

{% content-ref url="heap-memory-functions/heap-functions-security-checks.md" %}
[heap-functions-security-checks.md](heap-memory-functions/heap-functions-security-checks.md)
{% endcontent-ref %}

## Referanslar

* [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/)