Bins & Memory Allocations

Tip

ๅญฆไน ๅ’Œๅฎž่ทต AWS ้ป‘ๅฎขๆŠ€ๆœฏ๏ผšHackTricks Training AWS Red Team Expert (ARTE)
ๅญฆไน ๅ’Œๅฎž่ทต GCP ้ป‘ๅฎขๆŠ€ๆœฏ๏ผšHackTricks Training GCP Red Team Expert (GRTE) ๅญฆไน ๅ’Œๅฎž่ทต Azure ้ป‘ๅฎขๆŠ€ๆœฏ๏ผšHackTricks Training Azure Red Team Expert (AzRTE)

ๆ”ฏๆŒ HackTricks

ๅŸบๆœฌไฟกๆฏ

ไธบไบ†ๆ้ซ˜ๅ—ๅญ˜ๅ‚จ็š„ๆ•ˆ็އ๏ผŒๆฏไธชๅ—ไธไป…ๅœจไธ€ไธช้“พ่กจไธญ๏ผŒ่€Œๆ˜ฏๆœ‰ๅ‡ ็ง็ฑปๅž‹ใ€‚่ฟ™ไบ›ๆ˜ฏ bins๏ผŒๆœ‰ 5 ็ง็ฑปๅž‹็š„ bins๏ผš62 ๅฐ bins๏ผŒ63 ๅคง bins๏ผŒ1 ไธชๆœชๆŽ’ๅบ bin๏ผŒ10 ไธชๅฟซ้€Ÿ bins ๅ’Œๆฏไธช็บฟ็จ‹ 64 ไธช tcache binsใ€‚

ๆฏไธชๆœชๆŽ’ๅบใ€ๅฐๅž‹ๅ’Œๅคงๅž‹ bins ็š„ๅˆๅง‹ๅœฐๅ€ๅœจๅŒไธ€ไธชๆ•ฐ็ป„ๅ†…ใ€‚็ดขๅผ• 0 ๆœชไฝฟ็”จ๏ผŒ1 ๆ˜ฏๆœชๆŽ’ๅบ bin๏ผŒbins 2-64 ๆ˜ฏๅฐ bins๏ผŒbins 65-127 ๆ˜ฏๅคง binsใ€‚

Tcache๏ผˆๆฏ็บฟ็จ‹็ผ“ๅญ˜๏ผ‰Bins

ๅฐฝ็ฎก็บฟ็จ‹ๅฐ่ฏ•ๆ‹ฅๆœ‰่‡ชๅทฑ็š„ๅ †๏ผˆๅ‚่ง Arenas ๅ’Œ Subheaps๏ผ‰๏ผŒไฝ†ๆœ‰ๅฏ่ƒฝไธ€ไธชๆœ‰ๅพˆๅคš็บฟ็จ‹็š„่ฟ›็จ‹๏ผˆๅฆ‚ web ๆœๅŠกๅ™จ๏ผ‰ไผšไธŽๅ…ถไป–็บฟ็จ‹ๅ…ฑไบซๅ †ใ€‚ๅœจ่ฟ™็งๆƒ…ๅ†ตไธ‹๏ผŒไธป่ฆ่งฃๅ†ณๆ–นๆกˆๆ˜ฏไฝฟ็”จ ้”๏ผŒ่ฟ™ๅฏ่ƒฝไผš ๆ˜พ่‘—ๅ‡ๆ…ข็บฟ็จ‹็š„้€Ÿๅบฆใ€‚

ๅ› ๆญค๏ผŒtcache ็ฑปไผผไบŽๆฏไธช็บฟ็จ‹็š„ๅฟซ้€Ÿ bin๏ผŒๅ› ไธบๅฎƒๆ˜ฏไธ€ไธช ๅ•้“พ่กจ๏ผŒไธๅˆๅนถๅ—ใ€‚ๆฏไธช็บฟ็จ‹ๆœ‰ 64 ไธชๅ•้“พ่กจ tcache binsใ€‚ๆฏไธช bin ๆœ€ๅคšๅฏไปฅๆœ‰ 7 ไธช็›ธๅŒๅคงๅฐ็š„ๅ—๏ผŒๅคงๅฐ่Œƒๅ›ดไธบ 24 ๅˆฐ 1032B ๅœจ 64 ไฝ็ณป็ปŸไธŠๅ’Œ 12 ๅˆฐ 516B ๅœจ 32 ไฝ็ณป็ปŸไธŠใ€‚

ๅฝ“ไธ€ไธช็บฟ็จ‹้‡Šๆ”พไธ€ไธชๅ—ๆ—ถ๏ผŒๅฆ‚ๆžœๅฎƒไธๅคชๅคงไปฅ่‡ณไบŽๆ— ๆณ•ๅœจ tcache ไธญๅˆ†้…๏ผŒๅนถไธ”็›ธๅบ”็š„ tcache bin ๆฒกๆœ‰ๆปก๏ผˆๅทฒ็ปๆœ‰ 7 ไธชๅ—๏ผ‰๏ผŒๅฎƒๅฐ†่ขซๅˆ†้…ๅˆฐ้‚ฃ้‡Œใ€‚ๅฆ‚ๆžœๆ— ๆณ•่ฟ›ๅ…ฅ tcache๏ผŒๅฎƒๅฐ†้œ€่ฆ็ญ‰ๅพ…ๅ †้”ๆ‰่ƒฝๅœจๅ…จๅฑ€่Œƒๅ›ดๅ†…ๆ‰ง่กŒ้‡Šๆ”พๆ“ไฝœใ€‚

ๅฝ“ ๅˆ†้…ไธ€ไธชๅ—ๆ—ถ๏ผŒๅฆ‚ๆžœๅœจ Tcache ไธญๆœ‰ไธ€ไธชๆ‰€้œ€ๅคงๅฐ็š„็ฉบ้—ฒๅ—๏ผŒๅฎƒๅฐ†ไฝฟ็”จๅฎƒ๏ผŒๅฆ‚ๆžœๆฒกๆœ‰๏ผŒๅฎƒๅฐ†้œ€่ฆ็ญ‰ๅพ…ๅ †้”ๆ‰่ƒฝๅœจๅ…จๅฑ€ bins ไธญๆ‰พๅˆฐไธ€ไธชๆˆ–ๅˆ›ๅปบไธ€ไธชๆ–ฐ็š„ใ€‚
่ฟ˜ๆœ‰ไธ€ไธชไผ˜ๅŒ–๏ผŒๅœจ่ฟ™็งๆƒ…ๅ†ตไธ‹๏ผŒๅฝ“ๆ‹ฅๆœ‰ๅ †้”ๆ—ถ๏ผŒ็บฟ็จ‹ ๅฐ†็”จ่ฏทๆฑ‚ๅคงๅฐ็š„ๅ †ๅ—ๅกซๅ……ไป–็š„ Tcache๏ผˆ7 ไธช๏ผ‰๏ผŒไปฅไพฟๅœจ้œ€่ฆๆ›ดๅคšๆ—ถ๏ผŒๅฏไปฅๅœจ Tcache ไธญๆ‰พๅˆฐๅฎƒไปฌใ€‚

ๆทปๅŠ ไธ€ไธช tcache ๅ—็คบไพ‹ ```c #include #include

int main(void) { char *chunk; chunk = malloc(24); printf(โ€œAddress of the chunk: %p\nโ€, (void *)chunk); gets(chunk); free(chunk); return 0; }

ๅฐ†ๅ…ถ็ผ–่ฏ‘ๅนถๅœจไธปๅ‡ฝๆ•ฐ็š„ ret ๆ“ไฝœ็ ๅค„่ฎพ็ฝฎๆ–ญ็‚น่ฟ›่กŒ่ฐƒ่ฏ•ใ€‚็„ถๅŽไฝฟ็”จ gef๏ผŒๆ‚จๅฏไปฅ็œ‹ๅˆฐๆญฃๅœจไฝฟ็”จ็š„ tcache bin๏ผš
```bash
gefโžค  heap bins
โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ Tcachebins for thread 1 โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
Tcachebins[idx=0, size=0x20, count=1] โ†  Chunk(addr=0xaaaaaaac12a0, size=0x20, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)

Tcache ็ป“ๆž„ๅ’Œๅ‡ฝๆ•ฐ

ๅœจไปฅไธ‹ไปฃ็ ไธญ๏ผŒๅฏไปฅ็œ‹ๅˆฐ max bins ๅ’Œ chunks per index๏ผŒไธบไบ†้ฟๅ…ๅŒ้‡้‡Šๆ”พ่€Œๅˆ›ๅปบ็š„ tcache_entry ็ป“ๆž„๏ผŒไปฅๅŠๆฏไธช็บฟ็จ‹็”จๆฅๅญ˜ๅ‚จๆฏไธช bin ็ดขๅผ•ๅœฐๅ€็š„ tcache_perthread_struct ็ป“ๆž„ใ€‚

tcache_entry ๅ’Œ tcache_perthread_struct ```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. */

define TCACHE_MAX_BINS 64

define MAX_TCACHE_SIZE tidx2usize (TCACHE_MAX_BINS-1)

/* Only used to pre-fill the tunables. */

define tidx2usize(idx) (((size_t) idx) * MALLOC_ALIGNMENT + MINSIZE - SIZE_SZ)

/* When โ€œxโ€ is from chunksize(). */

define csize2tidx(x) (((x) - MINSIZE + MALLOC_ALIGNMENT - 1) / MALLOC_ALIGNMENT)

/* When โ€œxโ€ is a user-provided size. */

define usize2tidx(x) csize2tidx (request2size (x))

/* With rounding and alignment, the bins areโ€ฆ idx 0 bytes 0..24 (64-bit) or 0..12 (32-bit) idx 1 bytes 25..40 or 13..20 idx 2 bytes 41..56 or 21..28 etc. */

/* This is another arbitrary limit, which tunables can change. Each tcache bin will hold at most this number of chunks. */

define TCACHE_FILL_COUNT 7

/* Maximum chunks in tcache bins for tunables. This value must fit the range of tcache->counts[] entries, else they may overflow. */

define MAX_TCACHE_COUNT UINT16_MAX

[โ€ฆ]

typedef struct tcache_entry { struct tcache_entry next; / This field exists to detect double frees. */ uintptr_t key; } tcache_entry;

/* There is one of these for each thread, which contains the per-thread cache (hence โ€œtcache_perthread_structโ€). Keeping overall size low is mildly important. Note that COUNTS and ENTRIES are redundant (we could have just counted the linked list each time), this is for performance reasons. */ typedef struct tcache_perthread_struct { uint16_t counts[TCACHE_MAX_BINS]; tcache_entry *entries[TCACHE_MAX_BINS]; } tcache_perthread_struct;

</details>

ๅ‡ฝๆ•ฐ `__tcache_init` ๆ˜ฏๅˆ›ๅปบๅ’Œๅˆ†้… `tcache_perthread_struct` ๅฏน่ฑก็ฉบ้—ด็š„ๅ‡ฝๆ•ฐใ€‚

<details>

<summary>tcache_init ไปฃ็ </summary>
```c
// From https://github.com/bminor/glibc/blob/f942a732d37a96217ef828116ebe64a644db18d7/malloc/malloc.c#L3241C1-L3274C2

static void
tcache_init(void)
{
mstate ar_ptr;
void *victim = 0;
const size_t bytes = sizeof (tcache_perthread_struct);

if (tcache_shutting_down)
return;

arena_get (ar_ptr, bytes);
victim = _int_malloc (ar_ptr, bytes);
if (!victim && ar_ptr != NULL)
{
ar_ptr = arena_get_retry (ar_ptr, bytes);
victim = _int_malloc (ar_ptr, bytes);
}


if (ar_ptr != NULL)
__libc_lock_unlock (ar_ptr->mutex);

/* In a low memory situation, we may not be able to allocate memory
- in which case, we just keep trying later.  However, we
typically do this very early, so either there is sufficient
memory, or there isn't enough memory to do non-trivial
allocations anyway.  */
if (victim)
{
tcache = (tcache_perthread_struct *) victim;
memset (tcache, 0, sizeof (tcache_perthread_struct));
}

}

Tcache ็ดขๅผ•

Tcache ๆœ‰ๅ‡ ไธช bins๏ผŒๅ…ทไฝ“ๅ–ๅ†ณไบŽๅคงๅฐๅ’ŒๆŒ‡ๅ‘ ๆฏไธช็ดขๅผ•็ฌฌไธ€ไธชๅ—็š„ๅˆๅง‹ๆŒ‡้’ˆไปฅๅŠๆฏไธช็ดขๅผ•็š„ๅ—ๆ•ฐ้‡ไฝไบŽไธ€ไธชๅ—ๅ†…้ƒจใ€‚่ฟ™ๆ„ๅ‘ณ็€้€š่ฟ‡ๅฎšไฝๅŒ…ๅซ่ฟ™ไบ›ไฟกๆฏ็š„ๅ—๏ผˆ้€šๅธธๆ˜ฏ็ฌฌไธ€ไธช๏ผ‰๏ผŒๅฏไปฅๆ‰พๅˆฐๆ‰€ๆœ‰ tcache ๅˆๅง‹็‚นๅ’Œ Tcache ๅ—็š„ๆ•ฐ้‡ใ€‚

ๅฟซ้€Ÿ bins

ๅฟซ้€Ÿ bins ๆ—จๅœจ ๅŠ ้€Ÿๅฐๅ—็š„ๅ†…ๅญ˜ๅˆ†้…๏ผŒ้€š่ฟ‡ๅฐ†ๆœ€่ฟ‘้‡Šๆ”พ็š„ๅ—ไฟๅญ˜ๅœจๅฟซ้€Ÿ่ฎฟ้—ฎ็ป“ๆž„ไธญใ€‚่ฟ™ไบ› bins ไฝฟ็”จๅŽ่ฟ›ๅ…ˆๅ‡บ๏ผˆLIFO๏ผ‰ๆ–นๆณ•๏ผŒ่ฟ™ๆ„ๅ‘ณ็€ ๆœ€่ฟ‘้‡Šๆ”พ็š„ๅ—ๆ˜ฏ็ฌฌไธ€ไธช ๅœจๆœ‰ๆ–ฐ็š„ๅˆ†้…่ฏทๆฑ‚ๆ—ถ่ขซ้‡็”จใ€‚่ฟ™็ง่กŒไธบๅœจ้€ŸๅบฆไธŠๆ˜ฏๆœ‰ๅˆฉ็š„๏ผŒๅ› ไธบไปŽๆ ˆ้กถ๏ผˆLIFO๏ผ‰ๆ’ๅ…ฅๅ’Œ็งป้™คๆฏ”ไปŽ้˜Ÿๅˆ—๏ผˆFIFO๏ผ‰ๆ›ดๅฟซใ€‚

ๆญคๅค–๏ผŒๅฟซ้€Ÿ bins ไฝฟ็”จๅ•้“พ่กจ๏ผŒ่€Œไธๆ˜ฏๅŒ้“พ่กจ๏ผŒ่ฟ™่ฟ›ไธ€ๆญฅๆ้ซ˜ไบ†้€Ÿๅบฆใ€‚็”ฑไบŽๅฟซ้€Ÿ bins ไธญ็š„ๅ—ไธไผšไธŽ้‚ปๅฑ…ๅˆๅนถ๏ผŒๅ› ๆญคไธ้œ€่ฆๅคๆ‚็š„็ป“ๆž„ๆฅๅ…่ฎธไปŽไธญ้—ด็งป้™คใ€‚ๅ•้“พ่กจๅœจ่ฟ™ไบ›ๆ“ไฝœไธญๆ›ด็ฎ€ๅ•ใ€ๆ›ดๅฟซใ€‚

ๅŸบๆœฌไธŠ๏ผŒ่ฟ™้‡Œๅ‘็”Ÿ็š„ไบ‹ๆƒ…ๆ˜ฏ๏ผŒๅคด้ƒจ๏ผˆๆŒ‡ๅ‘็ฌฌไธ€ไธชๅ—็š„ๆŒ‡้’ˆ๏ผ‰ๅง‹็ปˆๆŒ‡ๅ‘่ฏฅๅคงๅฐ็š„ๆœ€ๆ–ฐ้‡Šๆ”พๅ—ใ€‚ๅ› ๆญค๏ผš

  • ๅฝ“ๅˆ†้…ไธ€ไธช่ฏฅๅคงๅฐ็š„ๆ–ฐๅ—ๆ—ถ๏ผŒๅคด้ƒจๆŒ‡ๅ‘ไธ€ไธชๅฏ็”จ็š„็ฉบ้—ฒๅ—ใ€‚็”ฑไบŽ่ฟ™ไธช็ฉบ้—ฒๅ—ๆŒ‡ๅ‘ไธ‹ไธ€ไธชๅฏ็”จๅ—๏ผŒ่ฟ™ไธชๅœฐๅ€่ขซๅญ˜ๅ‚จๅœจๅคด้ƒจ๏ผŒไปฅไพฟไธ‹ไธ€ไธชๅˆ†้…็Ÿฅ้“ๅœจๅ“ช้‡Œ่Žทๅ–ๅฏ็”จๅ—
  • ๅฝ“ไธ€ไธชๅ—่ขซ้‡Šๆ”พๆ—ถ๏ผŒ็ฉบ้—ฒๅ—ๅฐ†ไฟๅญ˜ๅฝ“ๅ‰ๅฏ็”จๅ—็š„ๅœฐๅ€๏ผŒ่€Œ่ฟ™ไธชๆ–ฐ้‡Šๆ”พๅ—็š„ๅœฐๅ€ๅฐ†ๆ”พๅ…ฅๅคด้ƒจ

้“พ่กจ็š„ๆœ€ๅคงๅคงๅฐไธบ 0x80๏ผŒๅฎƒไปฌ็š„็ป„็ป‡ๆ–นๅผๆ˜ฏ๏ผŒๅคงๅฐไธบ 0x20 ็š„ๅ—ๅฐ†ไฝไบŽ็ดขๅผ• 0๏ผŒๅคงๅฐไธบ 0x30 ็š„ๅ—ๅฐ†ไฝไบŽ็ดขๅผ• 1โ€ฆ

Caution

ๅฟซ้€Ÿ bins ไธญ็š„ๅ—ๆœช่ฎพ็ฝฎไธบๅฏ็”จ๏ผŒๅ› ๆญคๅฎƒไปฌไผšๅœจไธ€ๆฎตๆ—ถ้—ดๅ†…ไฟๆŒไธบๅฟซ้€Ÿ bin ๅ—๏ผŒ่€Œไธๆ˜ฏ่ƒฝๅคŸไธŽๅ‘จๅ›ด็š„ๅ…ถไป–็ฉบ้—ฒๅ—ๅˆๅนถใ€‚

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

/*
Fastbins

An array of lists holding recently freed small chunks.  Fastbins
are not doubly linked.  It is faster to single-link them, and
since chunks are never removed from the middles of these lists,
double linking is not necessary. Also, unlike regular bins, they
are not even processed in FIFO order (they use faster LIFO) since
ordering doesn't much matter in the transient contexts in which
fastbins are normally used.

Chunks in fastbins keep their inuse bit set, so they cannot
be consolidated with other free chunks. malloc_consolidate
releases all chunks in fastbins and consolidates them with
other free chunks.
*/

typedef struct malloc_chunk *mfastbinptr;
#define fastbin(ar_ptr, idx) ((ar_ptr)->fastbinsY[idx])

/* offset 2 to use otherwise unindexable first 2 bins */
#define fastbin_index(sz) \
((((unsigned int) (sz)) >> (SIZE_SZ == 8 ? 4 : 3)) - 2)


/* The maximum fastbin request size we support */
#define MAX_FAST_SIZE     (80 * SIZE_SZ / 4)

#define NFASTBINS  (fastbin_index (request2size (MAX_FAST_SIZE)) + 1)
ๆทปๅŠ ไธ€ไธช fastbin ๅ—็คบไพ‹ ```c #include #include

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

ๆณจๆ„ๆˆ‘ไปฌๅฆ‚ไฝ•ๅˆ†้…ๅ’Œ้‡Šๆ”พ8ไธช็›ธๅŒๅคงๅฐ็š„ๅ—๏ผŒไปฅไพฟๅฎƒไปฌๅกซๆปกtcache๏ผŒ็ฌฌๅ…ซไธชๅ—ๅญ˜ๅ‚จๅœจๅฟซ้€Ÿๅ—ไธญใ€‚

็ผ–่ฏ‘ๅฎƒๅนถๅœจ`main`ๅ‡ฝๆ•ฐ็š„`ret`ๆ“ไฝœ็ ๅค„่ฎพ็ฝฎๆ–ญ็‚น่ฟ›่กŒ่ฐƒ่ฏ•ใ€‚็„ถๅŽไฝฟ็”จ`gef`๏ผŒไฝ ๅฏไปฅ็œ‹ๅˆฐtcache binๅทฒๆปก๏ผŒไธ€ไธชๅ—ๅœจๅฟซ้€Ÿbinไธญ๏ผš
```bash
gefโžค  heap bins
โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ Tcachebins for thread 1 โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
Tcachebins[idx=0, size=0x20, count=7] โ†  Chunk(addr=0xaaaaaaac1770, size=0x20, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)  โ†  Chunk(addr=0xaaaaaaac1750, size=0x20, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)  โ†  Chunk(addr=0xaaaaaaac1730, size=0x20, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)  โ†  Chunk(addr=0xaaaaaaac1710, size=0x20, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)  โ†  Chunk(addr=0xaaaaaaac16f0, size=0x20, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)  โ†  Chunk(addr=0xaaaaaaac16d0, size=0x20, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)  โ†  Chunk(addr=0xaaaaaaac12a0, size=0x20, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ Fastbins for arena at 0xfffff7f90b00 โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
Fastbins[idx=0, size=0x20]  โ†  Chunk(addr=0xaaaaaaac1790, size=0x20, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
Fastbins[idx=1, size=0x30] 0x00

ๆœชๆŽ’ๅบ็š„ๅ †

ๆœชๆŽ’ๅบ็š„ๅ †ๆ˜ฏไธ€ไธช็ผ“ๅญ˜๏ผŒ็”ฑๅ †็ฎก็†ๅ™จ็”จไบŽๅŠ ๅฟซๅ†…ๅญ˜ๅˆ†้…ใ€‚ๅฎƒ็š„ๅทฅไฝœๅŽŸ็†ๅฆ‚ไธ‹๏ผšๅฝ“็จ‹ๅบ้‡Šๆ”พไธ€ไธชๅ—ๆ—ถ๏ผŒๅฆ‚ๆžœ่ฟ™ไธชๅ—ไธ่ƒฝๅœจtcacheๆˆ–ๅฟซ้€Ÿๅ †ไธญๅˆ†้…๏ผŒๅนถไธ”ๆฒกๆœ‰ไธŽ้กถ้ƒจๅ—ๅ‘็”Ÿๅ†ฒ็ช๏ผŒๅ †็ฎก็†ๅ™จไธไผš็ซ‹ๅณๅฐ†ๅ…ถๆ”พๅ…ฅ็‰นๅฎš็š„ๅฐๆˆ–ๅคงๅ †ไธญใ€‚็›ธๅ๏ผŒๅฎƒ้ฆ–ๅ…ˆๅฐ่ฏ•ไธŽไปปไฝ•็›ธ้‚ป็š„็ฉบ้—ฒๅ—ๅˆๅนถ๏ผŒไปฅๅˆ›ๅปบไธ€ไธชๆ›ดๅคง็š„็ฉบ้—ฒๅ†…ๅญ˜ๅ—ใ€‚็„ถๅŽ๏ผŒๅฎƒๅฐ†่ฟ™ไธชๆ–ฐๅ—ๆ”พๅ…ฅไธ€ไธช็งฐไธบโ€œๆœชๆŽ’ๅบๅ †โ€็š„้€š็”จๅ †ไธญใ€‚

ๅฝ“็จ‹ๅบ่ฏทๆฑ‚ๅ†…ๅญ˜ๆ—ถ๏ผŒๅ †็ฎก็†ๅ™จๆฃ€ๆŸฅๆœชๆŽ’ๅบๅ †ไปฅๆŸฅ็œ‹ๆ˜ฏๅฆๆœ‰่ถณๅคŸๅคงๅฐ็š„ๅ—ใ€‚ๅฆ‚ๆžœๆ‰พๅˆฐไธ€ไธช๏ผŒๅฎƒไผš็ซ‹ๅณไฝฟ็”จใ€‚ๅฆ‚ๆžœๅœจๆœชๆŽ’ๅบๅ †ไธญๆ‰พไธๅˆฐๅˆ้€‚็š„ๅ—๏ผŒๅฎƒไผšๅฐ†ๆญคๅˆ—่กจไธญ็š„ๆ‰€ๆœ‰ๅ—็งปๅŠจๅˆฐๅ…ถๅฏนๅบ”็š„ๅ †ไธญ๏ผŒไพๆฎๅฎƒไปฌ็š„ๅคงๅฐๅˆ†ไธบๅฐๅ †ๆˆ–ๅคงๅ †ใ€‚

่ฏทๆณจๆ„๏ผŒๅฆ‚ๆžœไธ€ไธช่พƒๅคง็š„ๅ—่ขซๅˆ†ๆˆไธคๅŠ๏ผŒๅนถไธ”ๅ…ถไฝ™้ƒจๅˆ†ๅคงไบŽMINSIZE๏ผŒๅฎƒๅฐ†่ขซๆ”พๅ›žๆœชๆŽ’ๅบๅ †ไธญใ€‚

ๅ› ๆญค๏ผŒๆœชๆŽ’ๅบๅ †ๆ˜ฏไธ€็ง้€š่ฟ‡ๅฟซ้€Ÿ้‡็”จๆœ€่ฟ‘้‡Šๆ”พ็š„ๅ†…ๅญ˜ๆฅๅŠ ้€Ÿๅ†…ๅญ˜ๅˆ†้…็š„ๆ–นๆณ•๏ผŒไปŽ่€Œๅ‡ๅฐ‘่€—ๆ—ถ็š„ๆœ็ดขๅ’Œๅˆๅนถ็š„้œ€่ฆใ€‚

Caution

่ฏทๆณจๆ„๏ผŒๅณไฝฟๅ—ๅฑžไบŽไธๅŒ็ฑปๅˆซ๏ผŒๅฆ‚ๆžœไธ€ไธชๅฏ็”จๅ—ไธŽๅฆไธ€ไธชๅฏ็”จๅ—ๅ‘็”Ÿๅ†ฒ็ช๏ผˆๅณไฝฟๅฎƒไปฌๆœ€ๅˆๅฑžไบŽไธๅŒ็š„ๅ †๏ผ‰๏ผŒๅฎƒไปฌไนŸไผš่ขซๅˆๅนถใ€‚

ๆทปๅŠ ไธ€ไธชๆœชๆŽ’ๅบๅ—็คบไพ‹ ```c #include #include

int main(void) { char *chunks[9]; int i;

// Loop to allocate memory 8 times for (i = 0; i < 9; i++) { chunks[i] = malloc(0x100); 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; }

ๆณจๆ„ๆˆ‘ไปฌๅฆ‚ไฝ•ๅˆ†้…ๅ’Œ้‡Šๆ”พ9ไธช็›ธๅŒๅคงๅฐ็š„ๅ—๏ผŒไปฅไพฟๅฎƒไปฌ**ๅกซๅ……tcache**๏ผŒ็ฌฌๅ…ซไธชๅ—ๅญ˜ๅ‚จๅœจๆœชๆŽ’ๅบ็š„binไธญ๏ผŒๅ› ไธบๅฎƒ**ๅฏนไบŽfastbinๆฅ่ฏดๅคชๅคง**๏ผŒ่€Œ็ฌฌไนไธชๅ—ๆฒกๆœ‰่ขซ้‡Šๆ”พ๏ผŒๅ› ๆญค็ฌฌไนไธชๅ’Œ็ฌฌๅ…ซไธช**ไธไผšไธŽ้กถ้ƒจๅ—ๅˆๅนถ**ใ€‚

็ผ–่ฏ‘ๅนถๅœจ`main`ๅ‡ฝๆ•ฐ็š„`ret`ๆ“ไฝœ็ ๅค„่ฎพ็ฝฎๆ–ญ็‚น่ฟ›่กŒ่ฐƒ่ฏ•ใ€‚็„ถๅŽไฝฟ็”จ`gef`๏ผŒไฝ ๅฏไปฅ็œ‹ๅˆฐtcache binๅทฒๆปก๏ผŒไธ€ไธชๅ—ๅœจๆœชๆŽ’ๅบ็š„binไธญ๏ผš
```bash
gefโžค  heap bins
โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ Tcachebins for thread 1 โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
Tcachebins[idx=15, size=0x110, count=7] โ†  Chunk(addr=0xaaaaaaac1d10, size=0x110, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)  โ†  Chunk(addr=0xaaaaaaac1c00, size=0x110, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)  โ†  Chunk(addr=0xaaaaaaac1af0, size=0x110, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)  โ†  Chunk(addr=0xaaaaaaac19e0, size=0x110, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)  โ†  Chunk(addr=0xaaaaaaac18d0, size=0x110, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)  โ†  Chunk(addr=0xaaaaaaac17c0, size=0x110, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)  โ†  Chunk(addr=0xaaaaaaac12a0, size=0x110, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ 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 โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
[+] unsorted_bins[0]: fw=0xaaaaaaac1e10, bk=0xaaaaaaac1e10
โ†’   Chunk(addr=0xaaaaaaac1e20, size=0x110, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
[+] Found 1 chunks in unsorted bin.

ๅฐๅž‹ๆกถ

ๅฐๅž‹ๆกถๆฏ”ๅคงๅž‹ๆกถๅฟซ๏ผŒไฝ†ๆฏ”ๅฟซ้€Ÿๆกถๆ…ขใ€‚

62ไธชๆกถไธญ็š„ๆฏไธชๆกถๅฐ†ๅ…ทๆœ‰็›ธๅŒๅคงๅฐ็š„ๅ—๏ผš16ใ€24๏ผŒโ€ฆ(ๅœจ32ไฝไธญๆœ€ๅคงไธบ504ๅญ—่Š‚๏ผŒๅœจ64ไฝไธญๆœ€ๅคงไธบ1024ๅญ—่Š‚)ใ€‚่ฟ™ๆœ‰ๅŠฉไบŽๅŠ ๅฟซๆŸฅๆ‰พๅบ”ๅˆ†้…็ฉบ้—ด็š„ๆกถไปฅๅŠๅœจ่ฟ™ไบ›ๅˆ—่กจไธญๆ’ๅ…ฅๅ’Œๅˆ ้™คๆก็›ฎ็š„้€Ÿๅบฆใ€‚

ๅฐๅž‹ๆกถ็š„ๅคงๅฐๆ˜ฏๆ นๆฎๆกถ็š„็ดขๅผ•่ฎก็ฎ—็š„๏ผš

  • ๆœ€ๅฐๅคงๅฐ๏ผš2*4*index๏ผˆไพ‹ๅฆ‚๏ผŒ็ดขๅผ•5 -> 40๏ผ‰
  • ๆœ€ๅคงๅคงๅฐ๏ผš2*8*index๏ผˆไพ‹ๅฆ‚๏ผŒ็ดขๅผ•5 -> 80๏ผ‰
// From https://github.com/bminor/glibc/blob/a07e000e82cb71238259e674529c37c12dc7d423/malloc/malloc.c#L1711
#define NSMALLBINS         64
#define SMALLBIN_WIDTH    MALLOC_ALIGNMENT
#define SMALLBIN_CORRECTION (MALLOC_ALIGNMENT > CHUNK_HDR_SZ)
#define MIN_LARGE_SIZE    ((NSMALLBINS - SMALLBIN_CORRECTION) * SMALLBIN_WIDTH)

#define in_smallbin_range(sz)  \
((unsigned long) (sz) < (unsigned long) MIN_LARGE_SIZE)

#define smallbin_index(sz) \
((SMALLBIN_WIDTH == 16 ? (((unsigned) (sz)) >> 4) : (((unsigned) (sz)) >> 3))\
+ SMALLBIN_CORRECTION)

้€‰ๆ‹ฉๅฐๅž‹ๅ’Œๅคงๅž‹ๅ†…ๅญ˜ๆฑ ็š„ๅ‡ฝๆ•ฐ๏ผš

#define bin_index(sz) \
((in_smallbin_range (sz)) ? smallbin_index (sz) : largebin_index (sz))
ๆทปๅŠ ไธ€ไธชๅฐๅ—็คบไพ‹ ```c #include #include

int main(void) { char *chunks[10]; int i;

// Loop to allocate memory 8 times for (i = 0; i < 9; i++) { chunks[i] = malloc(0x100); 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; }

ๆณจๆ„ๆˆ‘ไปฌๅฆ‚ไฝ•ๅˆ†้…ๅ’Œ้‡Šๆ”พ9ไธช็›ธๅŒๅคงๅฐ็š„ๅ—๏ผŒไปฅไพฟๅฎƒไปฌ**ๅกซๆปกtcache**๏ผŒ่€Œ็ฌฌๅ…ซไธชๅ—ๅญ˜ๅ‚จๅœจๆœชๆŽ’ๅบ็š„binไธญ๏ผŒๅ› ไธบๅฎƒ**ๅฏนไบŽfastbinๆฅ่ฏดๅคชๅคง**๏ผŒ่€Œ็ฌฌไนไธชๅ—ๆฒกๆœ‰่ขซ้‡Šๆ”พ๏ผŒๅ› ๆญค็ฌฌไนไธชๅ’Œ็ฌฌๅ…ซไธชๅ—**ไธไผšไธŽ้กถ้ƒจๅ—ๅˆๅนถ**ใ€‚็„ถๅŽๆˆ‘ไปฌๅˆ†้…ไธ€ไธชๆ›ดๅคง็š„ๅ—0x110๏ผŒ่ฟ™ไฝฟๅพ—**ๆœชๆŽ’ๅบbinไธญ็š„ๅ—่ฟ›ๅ…ฅๅฐbin**ใ€‚

็ผ–่ฏ‘ๅนถๅœจ`main`ๅ‡ฝๆ•ฐ็š„`ret`ๆ“ไฝœ็ ๅค„่ฎพ็ฝฎๆ–ญ็‚น่ฟ›่กŒ่ฐƒ่ฏ•ใ€‚็„ถๅŽไฝฟ็”จ`gef`๏ผŒไฝ ๅฏไปฅ็œ‹ๅˆฐtcache binๅทฒๆปก๏ผŒไธ”ไธ€ไธชๅ—ๅœจๅฐbinไธญ๏ผš
```bash
gefโžค  heap bins
โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ Tcachebins for thread 1 โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
Tcachebins[idx=15, size=0x110, count=7] โ†  Chunk(addr=0xaaaaaaac1d10, size=0x110, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)  โ†  Chunk(addr=0xaaaaaaac1c00, size=0x110, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)  โ†  Chunk(addr=0xaaaaaaac1af0, size=0x110, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)  โ†  Chunk(addr=0xaaaaaaac19e0, size=0x110, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)  โ†  Chunk(addr=0xaaaaaaac18d0, size=0x110, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)  โ†  Chunk(addr=0xaaaaaaac17c0, size=0x110, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)  โ†  Chunk(addr=0xaaaaaaac12a0, size=0x110, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ 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 โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
[+] small_bins[16]: fw=0xaaaaaaac1e10, bk=0xaaaaaaac1e10
โ†’   Chunk(addr=0xaaaaaaac1e20, size=0x110, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
[+] Found 1 chunks in 1 small non-empty bins.

ๅคงๅž‹ๅ†…ๅญ˜ๅ—

ไธŽ็ฎก็†ๅ›บๅฎšๅคงๅฐๅ—็š„ๅฐๅž‹ๅ†…ๅญ˜ๅ—ไธๅŒ๏ผŒๆฏไธชๅคงๅž‹ๅ†…ๅญ˜ๅ—ๅค„็†ไธ€็ณปๅˆ—ๅ—ๅคงๅฐใ€‚่ฟ™ๆ›ด็ตๆดป๏ผŒๅ…่ฎธ็ณป็ปŸๅฎน็บณๅ„็งๅคงๅฐ๏ผŒ่€Œๆ— ้œ€ไธบๆฏ็งๅคงๅฐๅ•็‹ฌ่ฎพ็ฝฎไธ€ไธชๅ†…ๅญ˜ๅ—ใ€‚

ๅœจๅ†…ๅญ˜ๅˆ†้…ๅ™จไธญ๏ผŒๅคงๅž‹ๅ†…ๅญ˜ๅ—ไปŽๅฐๅž‹ๅ†…ๅญ˜ๅ—็ป“ๆŸ็š„ๅœฐๆ–นๅผ€ๅง‹ใ€‚ๅคงๅž‹ๅ†…ๅญ˜ๅ—็š„่Œƒๅ›ด้€ๆธๅขžๅคง๏ผŒ่ฟ™ๆ„ๅ‘ณ็€็ฌฌไธ€ไธชๅ†…ๅญ˜ๅ—ๅฏ่ƒฝ่ฆ†็›–ไปŽ512ๅˆฐ576ๅญ—่Š‚็š„ๅ—๏ผŒ่€Œไธ‹ไธ€ไธชๅˆ™่ฆ†็›–576ๅˆฐ640ๅญ—่Š‚ใ€‚่ฟ™ไธชๆจกๅผๆŒ็ปญไธ‹ๅŽป๏ผŒๆœ€ๅคง็š„ๅ†…ๅญ˜ๅ—ๅŒ…ๅซๆ‰€ๆœ‰่ถ…่ฟ‡1MB็š„ๅ—ใ€‚

ไธŽๅฐๅž‹ๅ†…ๅญ˜ๅ—็›ธๆฏ”๏ผŒๅคงๅž‹ๅ†…ๅญ˜ๅ—็š„ๆ“ไฝœ้€Ÿๅบฆ่พƒๆ…ข๏ผŒๅ› ไธบๅฎƒไปฌๅฟ…้กปๅฏนไธๅŒๅ—ๅคงๅฐ็š„ๅˆ—่กจ่ฟ›่กŒๆŽ’ๅบๅ’Œๆœ็ดข๏ผŒไปฅๆ‰พๅˆฐๆœ€ไฝณ้€‚้…่ฟ›่กŒๅˆ†้…ใ€‚ๅฝ“ไธ€ไธชๅ—่ขซๆ’ๅ…ฅๅˆฐๅคงๅž‹ๅ†…ๅญ˜ๅ—ๆ—ถ๏ผŒๅฎƒๅฟ…้กป่ขซๆŽ’ๅบ๏ผŒ่€Œๅฝ“ๅ†…ๅญ˜่ขซๅˆ†้…ๆ—ถ๏ผŒ็ณป็ปŸๅฟ…้กปๆ‰พๅˆฐๅˆ้€‚็š„ๅ—ใ€‚่ฟ™้ขๅค–็š„ๅทฅไฝœไฝฟๅฎƒไปฌ้€Ÿๅบฆ่พƒๆ…ข๏ผŒไฝ†็”ฑไบŽๅคงๅž‹ๅˆ†้…ๆฏ”ๅฐๅž‹ๅˆ†้…ๅฐ‘๏ผŒๅ› ๆญค่ฟ™ๆ˜ฏไธ€ไธชๅฏไปฅๆŽฅๅ—็š„ๆƒ่กกใ€‚

ๆœ‰๏ผš

  • 32ไธช64B่Œƒๅ›ด็š„ๅ†…ๅญ˜ๅ—๏ผˆไธŽๅฐๅž‹ๅ†…ๅญ˜ๅ—ๅ†ฒ็ช๏ผ‰
  • 16ไธช512B่Œƒๅ›ด็š„ๅ†…ๅญ˜ๅ—๏ผˆไธŽๅฐๅž‹ๅ†…ๅญ˜ๅ—ๅ†ฒ็ช๏ผ‰
  • 8ไธช4096B่Œƒๅ›ด็š„ๅ†…ๅญ˜ๅ—๏ผˆ้ƒจๅˆ†ไธŽๅฐๅž‹ๅ†…ๅญ˜ๅ—ๅ†ฒ็ช๏ผ‰
  • 4ไธช32768B่Œƒๅ›ด็š„ๅ†…ๅญ˜ๅ—
  • 2ไธช262144B่Œƒๅ›ด็š„ๅ†…ๅญ˜ๅ—
  • 1ไธช็”จไบŽๅ‰ฉไฝ™ๅคงๅฐ็š„ๅ†…ๅญ˜ๅ—
ๅคงๅž‹ๅ†…ๅญ˜ๅ—ๅคงๅฐไปฃ็  ```c // From https://github.com/bminor/glibc/blob/a07e000e82cb71238259e674529c37c12dc7d423/malloc/malloc.c#L1711

#define largebin_index_32(sz)
(((((unsigned long) (sz)) >> 6) <= 38) ? 56 + (((unsigned long) (sz)) >> 6) :
((((unsigned long) (sz)) >> 9) <= 20) ? 91 + (((unsigned long) (sz)) >> 9) :
((((unsigned long) (sz)) >> 12) <= 10) ? 110 + (((unsigned long) (sz)) >> 12) :
((((unsigned long) (sz)) >> 15) <= 4) ? 119 + (((unsigned long) (sz)) >> 15) :
((((unsigned long) (sz)) >> 18) <= 2) ? 124 + (((unsigned long) (sz)) >> 18) :
126)

#define largebin_index_32_big(sz)
(((((unsigned long) (sz)) >> 6) <= 45) ? 49 + (((unsigned long) (sz)) >> 6) :
((((unsigned long) (sz)) >> 9) <= 20) ? 91 + (((unsigned long) (sz)) >> 9) :
((((unsigned long) (sz)) >> 12) <= 10) ? 110 + (((unsigned long) (sz)) >> 12) :
((((unsigned long) (sz)) >> 15) <= 4) ? 119 + (((unsigned long) (sz)) >> 15) :
((((unsigned long) (sz)) >> 18) <= 2) ? 124 + (((unsigned long) (sz)) >> 18) :
126)

// XXX It remains to be seen whether it is good to keep the widths of // XXX the buckets the same or whether it should be scaled by a factor // XXX of two as well. #define largebin_index_64(sz)
(((((unsigned long) (sz)) >> 6) <= 48) ? 48 + (((unsigned long) (sz)) >> 6) :
((((unsigned long) (sz)) >> 9) <= 20) ? 91 + (((unsigned long) (sz)) >> 9) :
((((unsigned long) (sz)) >> 12) <= 10) ? 110 + (((unsigned long) (sz)) >> 12) :
((((unsigned long) (sz)) >> 15) <= 4) ? 119 + (((unsigned long) (sz)) >> 15) :
((((unsigned long) (sz)) >> 18) <= 2) ? 124 + (((unsigned long) (sz)) >> 18) :
126)

#define largebin_index(sz)
(SIZE_SZ == 8 ? largebin_index_64 (sz) \
MALLOC_ALIGNMENT == 16 ? largebin_index_32_big (sz) \
largebin_index_32 (sz))
</details>

<details>

<summary>ๆทปๅŠ ไธ€ไธชๅคงๅ—็คบไพ‹</summary>
```c
#include <stdlib.h>
#include <stdio.h>

int main(void)
{
char *chunks[2];

chunks[0] = malloc(0x1500);
chunks[1] = malloc(0x1500);
free(chunks[0]);
chunks[0] = malloc(0x2000);

return 0;
}

2 ไธชๅคงๅˆ†้…่ขซๆ‰ง่กŒ๏ผŒ็„ถๅŽไธ€ไธช่ขซ้‡Šๆ”พ๏ผˆๅฐ†ๅ…ถๆ”พๅ…ฅๆœชๆŽ’ๅบ็š„ๆกถไธญ๏ผ‰๏ผŒๅนถไธ”่ฟ›่กŒๆ›ดๅคง็š„ๅˆ†้…๏ผˆๅฐ†้‡Šๆ”พ็š„ไปŽๆœชๆŽ’ๅบ็š„ๆกถ็งปๅŠจๅˆฐๅคงๆกถไธญ๏ผ‰ใ€‚

็ผ–่ฏ‘ๅนถๅœจ main ๅ‡ฝๆ•ฐ็š„ ret ๆ“ไฝœ็ ๅค„่ฎพ็ฝฎๆ–ญ็‚น่ฟ›่กŒ่ฐƒ่ฏ•ใ€‚็„ถๅŽไฝฟ็”จ gef๏ผŒไฝ ๅฏไปฅ็œ‹ๅˆฐ tcache ๆกถๅทฒๆปก๏ผŒๅนถไธ”ไธ€ไธชๅ—ๅœจๅคงๆกถไธญ๏ผš

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 โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
[+] large_bins[100]: fw=0xaaaaaaac1290, bk=0xaaaaaaac1290
โ†’   Chunk(addr=0xaaaaaaac12a0, size=0x1510, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
[+] Found 1 chunks in 1 large non-empty bins.

้กถ้ƒจๅ—

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

ๅŸบๆœฌไธŠ๏ผŒ่ฟ™ๆ˜ฏไธ€ไธชๅŒ…ๅซๆ‰€ๆœ‰ๅฝ“ๅ‰ๅฏ็”จๅ †็š„ๅ—ใ€‚ๅฝ“ๆ‰ง่กŒ malloc ๆ—ถ๏ผŒๅฆ‚ๆžœๆฒกๆœ‰ๅฏ็”จ็š„็ฉบ้—ฒๅ—ๅฏ็”จ๏ผŒ่ฟ™ไธช้กถๅ—ๅฐ†ไผšๅ‡ๅฐ‘ๅ…ถๅคงๅฐไปฅๆไพ›ๅฟ…่ฆ็š„็ฉบ้—ดใ€‚
ๆŒ‡ๅ‘้กถๅ—็š„ๆŒ‡้’ˆๅญ˜ๅ‚จๅœจ malloc_state ็ป“ๆž„ไธญใ€‚

ๆญคๅค–๏ผŒๅœจๅผ€ๅง‹ๆ—ถ๏ผŒๅฏไปฅๅฐ†ๆœชๆŽ’ๅบๅ—็”จไฝœ้กถๅ—ใ€‚

่ง‚ๅฏŸ้กถๅ—็คบไพ‹ ```c #include #include

int main(void) { char *chunk; chunk = malloc(24); printf(โ€œAddress of the chunk: %p\nโ€, (void *)chunk); gets(chunk); return 0; }

ๅœจ็ผ–่ฏ‘ๅนถๅœจ `main` ็š„ `ret` ๆ“ไฝœ็ ๅค„่ฐƒ่ฏ•ๆ—ถ๏ผŒๆˆ‘็œ‹ๅˆฐ malloc ่ฟ”ๅ›žไบ†ๅœฐๅ€ `0xaaaaaaac12a0`๏ผŒ่ฟ™ไบ›ๆ˜ฏๅ—๏ผš
```bash
gefโžค  heap chunks
Chunk(addr=0xaaaaaaac1010, size=0x290, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
[0x0000aaaaaaac1010     00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................]
Chunk(addr=0xaaaaaaac12a0, size=0x20, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
[0x0000aaaaaaac12a0     41 41 41 41 41 41 41 00 00 00 00 00 00 00 00 00    AAAAAAA.........]
Chunk(addr=0xaaaaaaac12c0, size=0x410, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
[0x0000aaaaaaac12c0     41 64 64 72 65 73 73 20 6f 66 20 74 68 65 20 63    Address of the c]
Chunk(addr=0xaaaaaaac16d0, size=0x410, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
[0x0000aaaaaaac16d0     41 41 41 41 41 41 41 0a 00 00 00 00 00 00 00 00    AAAAAAA.........]
Chunk(addr=0xaaaaaaac1ae0, size=0x20530, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)  โ†  top chunk

ๅฏไปฅ็œ‹ๅˆฐ้กถ้ƒจๅ—ไฝไบŽๅœฐๅ€ 0xaaaaaaac1ae0ใ€‚่ฟ™ๅนถไธๅฅ‡ๆ€ช๏ผŒๅ› ไธบๆœ€ๅŽๅˆ†้…็š„ๅ—ๅœจ 0xaaaaaaac12a0๏ผŒๅคงๅฐไธบ 0x410๏ผŒๅนถไธ” 0xaaaaaaac12a0 + 0x410 = 0xaaaaaaac1ae0ใ€‚
่ฟ˜ๅฏไปฅๅœจๅ…ถๅ—ๅคดไธญ็œ‹ๅˆฐ้กถ้ƒจๅ—็š„้•ฟๅบฆ๏ผš

gefโžค  x/8wx 0xaaaaaaac1ae0 - 16
0xaaaaaaac1ad0:	0x00000000	0x00000000	0x00020531	0x00000000
0xaaaaaaac1ae0:	0x00000000	0x00000000	0x00000000	0x00000000

ๆœ€ๅŽๅ‰ฉไฝ™

ๅฝ“ไฝฟ็”จ malloc ๅนถไธ”ไธ€ไธชๅ—่ขซๅˆ†ๅ‰ฒ๏ผˆไพ‹ๅฆ‚๏ผŒไปŽๆœชๆŽ’ๅบ็š„ๆกถๆˆ–ไปŽ้กถ้ƒจๅ—๏ผ‰๏ผŒไปŽๅˆ†ๅ‰ฒๅ—็š„ๅ…ถไฝ™้ƒจๅˆ†ๅˆ›ๅปบ็š„ๅ—็งฐไธบๆœ€ๅŽๅ‰ฉไฝ™๏ผŒๅ…ถๆŒ‡้’ˆๅญ˜ๅ‚จๅœจ malloc_state ็ป“ๆž„ไธญใ€‚

ๅˆ†้…ๆต็จ‹

ๆŸฅ็œ‹๏ผš

malloc & sysmalloc

้‡Šๆ”พๆต็จ‹

ๆŸฅ็œ‹๏ผš

free

ๅ †ๅ‡ฝๆ•ฐๅฎ‰ๅ…จๆฃ€ๆŸฅ

ๆฃ€ๆŸฅๅ †ไธญๅธธ็”จๅ‡ฝๆ•ฐๆ‰ง่กŒ็š„ๅฎ‰ๅ…จๆฃ€ๆŸฅ๏ผš

Heap Functions Security Checks

ๅ‚่€ƒๆ–‡็Œฎ

Tip

ๅญฆไน ๅ’Œๅฎž่ทต AWS ้ป‘ๅฎขๆŠ€ๆœฏ๏ผšHackTricks Training AWS Red Team Expert (ARTE)
ๅญฆไน ๅ’Œๅฎž่ทต GCP ้ป‘ๅฎขๆŠ€ๆœฏ๏ผšHackTricks Training GCP Red Team Expert (GRTE) ๅญฆไน ๅ’Œๅฎž่ทต Azure ้ป‘ๅฎขๆŠ€ๆœฏ๏ผšHackTricks Training Azure Red Team Expert (AzRTE)

ๆ”ฏๆŒ HackTricks