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ใ‚’ใ‚ตใƒใƒผใƒˆใ™ใ‚‹

ๅŸบๆœฌๆƒ…ๅ ฑ

ใƒใƒฃใƒณใ‚ฏใฎไฟๅญ˜ๅŠน็އใ‚’ๅ‘ไธŠใ•ใ›ใ‚‹ใŸใ‚ใซใ€ๅ„ใƒใƒฃใƒณใ‚ฏใฏๅ˜ไธ€ใฎใƒชใƒณใ‚ฏใƒชใ‚นใƒˆใซใ ใ‘ๅญ˜ๅœจใ™ใ‚‹ใฎใงใฏใชใใ€ใ„ใใคใ‹ใฎใ‚ฟใ‚คใƒ—ใŒใ‚ใ‚Šใพใ™ใ€‚ใ“ใ‚ŒใŒใƒ“ใƒณใงใ‚ใ‚Šใ€5็จฎ้กžใฎใƒ“ใƒณใŒใ‚ใ‚Šใพใ™: 62 ๅฐใƒ“ใƒณใ€63 ๅคงใƒ“ใƒณใ€1 ๆœชๆ•ด็†ใƒ“ใƒณใ€10 ้ซ˜้€Ÿใƒ“ใƒณใ€ใ‚นใƒฌใƒƒใƒ‰ใ”ใจใซ64 tcacheใƒ“ใƒณใงใ™ใ€‚

ๆœชๆ•ด็†ใ€ๅฐใƒ“ใƒณใ€ๅคงใƒ“ใƒณใฎๅ„ใƒ“ใƒณใธใฎๅˆๆœŸใ‚ขใƒ‰ใƒฌใ‚นใฏๅŒใ˜้…ๅˆ—ๅ†…ใซใ‚ใ‚Šใพใ™ใ€‚ใ‚คใƒณใƒ‡ใƒƒใ‚ฏใ‚น0ใฏๆœชไฝฟ็”จใ€1ใฏๆœชๆ•ด็†ใƒ“ใƒณใ€ใƒ“ใƒณ2-64ใฏๅฐใƒ“ใƒณใ€ใƒ“ใƒณ65-127ใฏๅคงใƒ“ใƒณใงใ™ใ€‚

Tcache (ใ‚นใƒฌใƒƒใƒ‰ใ”ใจใฎใ‚ญใƒฃใƒƒใ‚ทใƒฅ) ใƒ“ใƒณ

ใ‚นใƒฌใƒƒใƒ‰ใฏใใ‚Œใžใ‚Œ็‹ฌ่‡ชใฎใƒ’ใƒผใƒ—ใ‚’ๆŒใจใ†ใจใ—ใพใ™ใŒ๏ผˆใ‚ขใƒชใƒผใƒŠใŠใ‚ˆใณใ‚ตใƒ–ใƒ’ใƒผใƒ—ใ‚’ๅ‚็…ง๏ผ‰ใ€ๅคšใใฎใ‚นใƒฌใƒƒใƒ‰ใ‚’ๆŒใคใƒ—ใƒญใ‚ปใ‚น๏ผˆใ‚ฆใ‚งใƒ–ใ‚ตใƒผใƒใƒผใฎใ‚ˆใ†ใช๏ผ‰ใฏไป–ใฎใ‚นใƒฌใƒƒใƒ‰ใจใƒ’ใƒผใƒ—ใ‚’ๅ…ฑๆœ‰ใ™ใ‚‹ๅฏ่ƒฝๆ€งใŒใ‚ใ‚Šใพใ™ใ€‚ใ“ใฎๅ ดๅˆใ€ไธปใช่งฃๆฑบ็ญ–ใฏใƒญใƒƒใ‚ซใƒผใฎไฝฟ็”จใงใ‚ใ‚Šใ€ใ“ใ‚Œใซใ‚ˆใ‚Šใ‚นใƒฌใƒƒใƒ‰ใŒๅคงๅน…ใซ้…ใใชใ‚‹ๅฏ่ƒฝๆ€งใŒใ‚ใ‚Šใพใ™ใ€‚

ใ—ใŸใŒใฃใฆใ€tcacheใฏใ‚นใƒฌใƒƒใƒ‰ใ”ใจใฎ้ซ˜้€Ÿใƒ“ใƒณใซไผผใฆใŠใ‚Šใ€ใƒใƒฃใƒณใ‚ฏใ‚’ใƒžใƒผใ‚ธใ—ใชใ„ๅ˜ไธ€ใฎใƒชใƒณใ‚ฏใƒชใ‚นใƒˆใงใ™ใ€‚ๅ„ใ‚นใƒฌใƒƒใƒ‰ใซใฏ64ใฎๅ˜ไธ€ใƒชใƒณใ‚ฏtcacheใƒ“ใƒณใŒใ‚ใ‚Šใพใ™ใ€‚ๅ„ใƒ“ใƒณใฏใ€64ใƒ“ใƒƒใƒˆใ‚ทใ‚นใƒ†ใƒ ใง24ใ‹ใ‚‰1032Bใ€32ใƒ“ใƒƒใƒˆใ‚ทใ‚นใƒ†ใƒ ใง12ใ‹ใ‚‰516Bใฎ็ฏ„ๅ›ฒใฎ ๅŒใ‚ตใ‚คใ‚บใฎใƒใƒฃใƒณใ‚ฏใ‚’ๆœ€ๅคง7ใคๆŒใคใ“ใจใŒใงใใพใ™ใ€‚

ใ‚นใƒฌใƒƒใƒ‰ใŒใƒใƒฃใƒณใ‚ฏใ‚’่งฃๆ”พใ™ใ‚‹ใจใใ€tcacheใซๅ‰ฒใ‚Šๅฝ“ใฆใ‚‹ใซใฏๅคงใใ™ใŽใชใ„ๅ ดๅˆใ€ใŠใ‚ˆใณ่ฉฒๅฝ“ใ™ใ‚‹tcacheใƒ“ใƒณใŒๆบ€ๆฏใงใชใ„ๅ ดๅˆ๏ผˆใ™ใงใซ7ใคใฎใƒใƒฃใƒณใ‚ฏใŒใ‚ใ‚‹ๅ ดๅˆ๏ผ‰ใ€ใใ“ใซๅ‰ฒใ‚Šๅฝ“ใฆใ‚‰ใ‚Œใพใ™ใ€‚tcacheใซ่กŒใ‘ใชใ„ๅ ดๅˆใ€ใ‚ฐใƒญใƒผใƒใƒซใซ่งฃๆ”พๆ“ไฝœใ‚’ๅฎŸ่กŒใ™ใ‚‹ใŸใ‚ใซใƒ’ใƒผใƒ—ใƒญใƒƒใ‚ฏใ‚’ๅพ…ใคๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚

ใƒใƒฃใƒณใ‚ฏใŒๅ‰ฒใ‚Šๅฝ“ใฆใ‚‰ใ‚Œใ‚‹ใจใใ€ๅฟ…่ฆใชใ‚ตใ‚คใ‚บใฎ็ฉบใใƒใƒฃใƒณใ‚ฏใŒTcacheใซใ‚ใ‚Œใฐใใ‚Œใ‚’ไฝฟ็”จใ—ใ€ใใ†ใงใชใ‘ใ‚Œใฐใ€ใ‚ฐใƒญใƒผใƒใƒซใƒ“ใƒณใง่ฆ‹ใคใ‘ใ‚‹ใ‹ๆ–ฐใ—ใ„ใ‚‚ใฎใ‚’ไฝœๆˆใ™ใ‚‹ใŸใ‚ใซใƒ’ใƒผใƒ—ใƒญใƒƒใ‚ฏใ‚’ๅพ…ใคๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚
ใพใŸใ€ๆœ€้ฉๅŒ–ใ‚‚ใ‚ใ‚Šใ€ใ“ใฎๅ ดๅˆใ€ใƒ’ใƒผใƒ—ใƒญใƒƒใ‚ฏใ‚’ไฟๆŒใ—ใฆใ„ใ‚‹้–“ใ€ใ‚นใƒฌใƒƒใƒ‰ใฏ่ฆๆฑ‚ใ•ใ‚ŒใŸใ‚ตใ‚คใ‚บใฎใƒ’ใƒผใƒ—ใƒใƒฃใƒณใ‚ฏ๏ผˆ7๏ผ‰ใงTcacheใ‚’ๆบ€ใŸใ—ใพใ™ใฎใงใ€ใ•ใ‚‰ใซๅฟ…่ฆใชๅ ดๅˆใฏ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; }

ใ‚ณใƒณใƒ‘ใ‚คใƒซใ—ใฆใ€main้–ขๆ•ฐใฎ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 ๆง‹้€ ไฝ“ใ€ๅ„ใ‚นใƒฌใƒƒใƒ‰ใŒใƒ“ใƒณใฎๅ„ใ‚คใƒณใƒ‡ใƒƒใ‚ฏใ‚นใธใฎใ‚ขใƒ‰ใƒฌใ‚นใ‚’ๆ ผ็ดใ™ใ‚‹ใŸใ‚ใซไฝฟ็”จใ™ใ‚‹ 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 ใซใฏใ€ใ‚ตใ‚คใ‚บใซๅฟœใ˜ใŸ่ค‡ๆ•ฐใฎใƒ“ใƒณใŒใ‚ใ‚Šใ€ๅ„ใ‚คใƒณใƒ‡ใƒƒใ‚ฏใ‚นใฎๆœ€ๅˆใฎใƒใƒฃใƒณใ‚ฏใธใฎใƒใ‚คใƒณใ‚ฟใจใ‚คใƒณใƒ‡ใƒƒใ‚ฏใ‚นใ”ใจใฎใƒใƒฃใƒณใ‚ฏใฎ้‡ใฏใƒใƒฃใƒณใ‚ฏๅ†…ใซใ‚ใ‚Šใพใ™ใ€‚ใ“ใ‚Œใฏใ€ใ“ใฎๆƒ…ๅ ฑใ‚’ๆŒใคใƒใƒฃใƒณใ‚ฏ๏ผˆ้€šๅธธใฏๆœ€ๅˆใฎใ‚‚ใฎ๏ผ‰ใ‚’็‰นๅฎšใ™ใ‚‹ใ“ใจใงใ€ใ™ในใฆใฎ tcache ๅˆๆœŸใƒใ‚คใƒณใƒˆใจ Tcache ใƒใƒฃใƒณใ‚ฏใฎ้‡ใ‚’่ฆ‹ใคใ‘ใ‚‹ใ“ใจใŒใงใใ‚‹ใ“ใจใ‚’ๆ„ๅ‘ณใ—ใพใ™ใ€‚

ใƒ•ใ‚กใ‚นใƒˆใƒ“ใƒณ

ใƒ•ใ‚กใ‚นใƒˆใƒ“ใƒณใฏใ€ๅฐใ•ใชใƒใƒฃใƒณใ‚ฏใฎใƒกใƒขใƒชๅ‰ฒใ‚Šๅฝ“ใฆใ‚’้ซ˜้€ŸๅŒ–ใ™ใ‚‹ใŸใ‚ใซ่จญ่จˆใ•ใ‚Œใฆใ„ใพใ™ใ€‚ๆœ€่ฟ‘่งฃๆ”พใ•ใ‚ŒใŸใƒใƒฃใƒณใ‚ฏใ‚’่ฟ…้€Ÿใซใ‚ขใ‚ฏใ‚ปใ‚นใงใใ‚‹ๆง‹้€ ใซไฟๆŒใ—ใพใ™ใ€‚ใ“ใ‚Œใ‚‰ใฎใƒ“ใƒณใฏใ€ๅพŒๅ…ฅใ‚Œๅ…ˆๅ‡บใ—๏ผˆLIFO๏ผ‰ใ‚ขใƒ—ใƒญใƒผใƒใ‚’ไฝฟ็”จใ—ใฆใŠใ‚Šใ€ๆœ€ใ‚‚ๆœ€่ฟ‘่งฃๆ”พใ•ใ‚ŒใŸใƒใƒฃใƒณใ‚ฏใŒๆœ€ๅˆใซๅ†ๅˆฉ็”จใ•ใ‚Œใพใ™ใ€‚ใ“ใ‚Œใฏใ€ใ‚นใ‚ฟใƒƒใ‚ฏใฎไธŠ้ƒจใ‹ใ‚‰ใฎๆŒฟๅ…ฅใจๅ‰Š้™คใŒใ‚ญใƒฅใƒผ๏ผˆFIFO๏ผ‰ใจๆฏ”่ผƒใ—ใฆ้€Ÿใ„ใŸใ‚ใ€้€Ÿๅบฆใซใจใฃใฆๆœ‰ๅˆฉใงใ™ใ€‚

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

ๅŸบๆœฌ็š„ใซใ€ใ“ใ“ใง่ตทใ“ใ‚‹ใ“ใจใฏใ€ใƒ˜ใƒƒใƒ€ใƒผ๏ผˆๆœ€ๅˆใฎใƒใƒฃใƒณใ‚ฏใ‚’ใƒใ‚งใƒƒใ‚ฏใ™ใ‚‹ใŸใ‚ใฎใƒใ‚คใƒณใ‚ฟ๏ผ‰ใŒๅธธใซใใฎใ‚ตใ‚คใ‚บใฎๆœ€ๆ–ฐใฎ่งฃๆ”พใ•ใ‚ŒใŸใƒใƒฃใƒณใ‚ฏใ‚’ๆŒ‡ใ—ใฆใ„ใ‚‹ใจใ„ใ†ใ“ใจใงใ™ใ€‚ใ—ใŸใŒใฃใฆ๏ผš

  • ใใฎใ‚ตใ‚คใ‚บใฎๆ–ฐใ—ใ„ใƒใƒฃใƒณใ‚ฏใŒๅ‰ฒใ‚Šๅฝ“ใฆใ‚‰ใ‚Œใ‚‹ใจใ€ใƒ˜ใƒƒใƒ€ใƒผใฏไฝฟ็”จใ™ใ‚‹ใŸใ‚ใฎ็ฉบใใƒใƒฃใƒณใ‚ฏใ‚’ๆŒ‡ใ—ใฆใ„ใพใ™ใ€‚ใ“ใฎ็ฉบใใƒใƒฃใƒณใ‚ฏใŒๆฌกใซไฝฟ็”จใ™ใ‚‹ใƒใƒฃใƒณใ‚ฏใ‚’ๆŒ‡ใ—ใฆใ„ใ‚‹ใŸใ‚ใ€ใ“ใฎใ‚ขใƒ‰ใƒฌใ‚นใฏใƒ˜ใƒƒใƒ€ใƒผใซไฟๅญ˜ใ•ใ‚Œใ€ๆฌกใฎๅ‰ฒใ‚Šๅฝ“ใฆใŒๅˆฉ็”จๅฏ่ƒฝใชใƒใƒฃใƒณใ‚ฏใ‚’ๅ–ๅพ—ใ™ใ‚‹ๅ ดๆ‰€ใ‚’็Ÿฅใ‚‹ใ“ใจใŒใงใใพใ™ใ€‚
  • ใƒใƒฃใƒณใ‚ฏใŒ่งฃๆ”พใ•ใ‚Œใ‚‹ใจใ€็ฉบใใƒใƒฃใƒณใ‚ฏใฏ็พๅœจใฎๅˆฉ็”จๅฏ่ƒฝใชใƒใƒฃใƒณใ‚ฏใธใฎใ‚ขใƒ‰ใƒฌใ‚นใ‚’ไฟๅญ˜ใ—ใ€ใ“ใฎๆ–ฐใ—ใ่งฃๆ”พใ•ใ‚ŒใŸใƒใƒฃใƒณใ‚ฏใธใฎใ‚ขใƒ‰ใƒฌใ‚นใŒใƒ˜ใƒƒใƒ€ใƒผใซ็ฝฎใ‹ใ‚Œใพใ™ใ€‚

ใƒชใƒณใ‚ฏใƒชใ‚นใƒˆใฎๆœ€ๅคงใ‚ตใ‚คใ‚บใฏ 0x80 ใงใ‚ใ‚Šใ€ใ‚ตใ‚คใ‚บ 0x20 ใฎใƒใƒฃใƒณใ‚ฏใฏใ‚คใƒณใƒ‡ใƒƒใ‚ฏใ‚น 0 ใซใ€ใ‚ตใ‚คใ‚บ 0x30 ใฎใƒใƒฃใƒณใ‚ฏใฏใ‚คใƒณใƒ‡ใƒƒใ‚ฏใ‚น 1 ใซ้…็ฝฎใ•ใ‚Œใพใ™โ€ฆ

Caution

ใƒ•ใ‚กใ‚นใƒˆใƒ“ใƒณใฎใƒใƒฃใƒณใ‚ฏใฏๅˆฉ็”จๅฏ่ƒฝใจใ—ใฆ่จญๅฎšใ•ใ‚Œใฆใ„ใชใ„ใŸใ‚ใ€ๅ‘จๅ›ฒใฎไป–ใฎ็ฉบใใƒใƒฃใƒณใ‚ฏใจใƒžใƒผใ‚ธใงใใ‚‹ไปฃใ‚ใ‚Šใซใ€ใ—ใฐใ‚‰ใใฎ้–“ใƒ•ใ‚กใ‚นใƒˆใƒ“ใƒณใƒใƒฃใƒณใ‚ฏใจใ—ใฆไฟๆŒใ•ใ‚Œใพใ™ใ€‚

// 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)
ใƒ•ใ‚กใ‚นใƒˆใƒ“ใƒณใƒใƒฃใƒณใ‚ฏใฎไพ‹ใ‚’่ฟฝๅŠ  ```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ใŒๆบ€ใŸใ•ใ‚Œใ€8ใค็›ฎใฎใƒใƒฃใƒณใ‚ฏใŒใƒ•ใ‚กใ‚นใƒˆใƒใƒฃใƒณใ‚ฏใซๆ ผ็ดใ•ใ‚Œใพใ™ใ€‚

ใ‚ณใƒณใƒ‘ใ‚คใƒซใ—ใฆใ€`main`้–ขๆ•ฐใฎ`ret`ใ‚ชใƒšใ‚ณใƒผใƒ‰ใซใƒ–ใƒฌใƒผใ‚ฏใƒใ‚คใƒณใƒˆใ‚’่จญๅฎšใ—ใฆใƒ‡ใƒใƒƒใ‚ฐใ—ใพใ™ใ€‚ๆฌกใซใ€`gef`ใ‚’ไฝฟ็”จใ™ใ‚‹ใจใ€tcacheใƒ“ใƒณใŒๆบ€ๆฏใงใ€1ใคใฎใƒใƒฃใƒณใ‚ฏใŒใƒ•ใ‚กใ‚นใƒˆใƒ“ใƒณใซใ‚ใ‚‹ใ“ใจใŒใ‚ใ‹ใ‚Šใพใ™ใ€‚
```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ใ‚„ใƒ•ใ‚กใ‚นใƒˆใƒ“ใƒณใซๅ‰ฒใ‚Šๅฝ“ใฆใ‚‰ใ‚Œใšใ€ใƒˆใƒƒใƒ—ใƒใƒฃใƒณใ‚ฏใจ่ก็ชใ—ใชใ„ๅ ดๅˆใ€ใƒ’ใƒผใƒ—ใƒžใƒใƒผใ‚ธใƒฃใƒผใฏใ™ใใซ็‰นๅฎšใฎๅฐใ•ใชใƒ“ใƒณใ‚„ๅคงใใชใƒ“ใƒณใซๅ…ฅใ‚Œใพใ›ใ‚“ใ€‚ไปฃใ‚ใ‚Šใซใ€ใพใš้šฃๆŽฅใ™ใ‚‹็ฉบใใƒใƒฃใƒณใ‚ฏใจใƒžใƒผใ‚ธใ—ใ‚ˆใ†ใจใ—ใพใ™ใ€‚ใ“ใ‚Œใซใ‚ˆใ‚Šใ€ใ‚ˆใ‚Šๅคงใใช็ฉบใใƒกใƒขใƒชใƒ–ใƒญใƒƒใ‚ฏใŒไฝœๆˆใ•ใ‚Œใพใ™ใ€‚ใใฎๅพŒใ€ใ“ใฎๆ–ฐใ—ใ„ใƒใƒฃใƒณใ‚ฏใฏใ€Œๆœชๆ•ด็†ใƒ“ใƒณใ€ใจๅ‘ผใฐใ‚Œใ‚‹ไธ€่ˆฌ็š„ใชใƒ“ใƒณใซ้…็ฝฎใ•ใ‚Œใพใ™ใ€‚

ใƒ—ใƒญใ‚ฐใƒฉใƒ ใŒใƒกใƒขใƒชใ‚’่ฆๆฑ‚ใ™ใ‚‹ใจใ€ใƒ’ใƒผใƒ—ใƒžใƒใƒผใ‚ธใƒฃใƒผใฏๆœชๆ•ด็†ใƒ“ใƒณใ‚’ใƒใ‚งใƒƒใ‚ฏใ—ใฆใ€ๅๅˆ†ใชใ‚ตใ‚คใ‚บใฎใƒใƒฃใƒณใ‚ฏใŒใ‚ใ‚‹ใ‹ใฉใ†ใ‹ใ‚’็ขบ่ชใ—ใพใ™ใ€‚่ฆ‹ใคใ‹ใ‚Œใฐใ€ใ™ใใซใใ‚Œใ‚’ไฝฟ็”จใ—ใพใ™ใ€‚ๆœชๆ•ด็†ใƒ“ใƒณใซ้ฉๅˆ‡ใชใƒใƒฃใƒณใ‚ฏใŒ่ฆ‹ใคใ‹ใ‚‰ใชใ„ๅ ดๅˆใฏใ€ใ“ใฎใƒชใ‚นใƒˆๅ†…ใฎใ™ในใฆใฎใƒใƒฃใƒณใ‚ฏใ‚’ใ‚ตใ‚คใ‚บใซๅŸบใฅใ„ใฆๅฏพๅฟœใ™ใ‚‹ใƒ“ใƒณ๏ผˆๅฐใพใŸใฏๅคง๏ผ‰ใซ็งปๅ‹•ใ—ใพใ™ใ€‚

ๆณจๆ„ใ™ในใใฏใ€ใ‚ˆใ‚Šๅคงใใชใƒใƒฃใƒณใ‚ฏใŒ2ใคใฎๅŠๅˆ†ใซๅˆ†ๅ‰ฒใ•ใ‚Œใ€ๆฎ‹ใ‚ŠใŒ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ใŒๆบ€ใŸใ•ใ‚Œ**ใ€8ใค็›ฎใฏ**fastbinใซใฏๅคงใใ™ใŽใ‚‹**ใŸใ‚ใ€ๆœชใ‚ฝใƒผใƒˆใฎใƒ“ใƒณใซๆ ผ็ดใ•ใ‚Œใพใ™ใ€‚ใใ—ใฆ9ใค็›ฎใฏ่งฃๆ”พใ•ใ‚Œใฆใ„ใชใ„ใŸใ‚ใ€9ใค็›ฎใจ8ใค็›ฎใฏ**ใƒˆใƒƒใƒ—ใƒใƒฃใƒณใ‚ฏใจใƒžใƒผใ‚ธใ•ใ‚Œใพใ›ใ‚“**ใ€‚

ใใ‚Œใ‚’ใ‚ณใƒณใƒ‘ใ‚คใƒซใ—ใ€`main`้–ขๆ•ฐใฎ`ret`ใ‚ชใƒšใ‚ณใƒผใƒ‰ใซใƒ–ใƒฌใƒผใ‚ฏใƒใ‚คใƒณใƒˆใ‚’่จญๅฎšใ—ใฆใƒ‡ใƒใƒƒใ‚ฐใ—ใพใ™ใ€‚ๆฌกใซใ€`gef`ใ‚’ไฝฟ็”จใ™ใ‚‹ใจใ€tcacheใƒ“ใƒณใŒๆบ€ๆฏใงใ‚ใ‚Šใ€1ใคใฎใƒใƒฃใƒณใ‚ฏใŒๆœชใ‚ฝใƒผใƒˆใฎใƒ“ใƒณใซใ‚ใ‚‹ใ“ใจใŒใ‚ใ‹ใ‚Šใพใ™ใ€‚
```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ใŒๆบ€ใŸใ•ใ‚Œ**ใ€8ใค็›ฎใฏ**fastbinใซใฏๅคงใใ™ใŽใ‚‹**ใŸใ‚ใ€ๆœชใ‚ฝใƒผใƒˆใฎใƒ“ใƒณใซๆ ผ็ดใ•ใ‚Œใพใ™ใ€‚ใใ—ใฆ9ใค็›ฎใฏ่งฃๆ”พใ•ใ‚Œใฆใ„ใชใ„ใŸใ‚ใ€9ใค็›ฎใจ8ใค็›ฎใฏ**ใƒˆใƒƒใƒ—ใƒใƒฃใƒณใ‚ฏใจใƒžใƒผใ‚ธใ•ใ‚Œใพใ›ใ‚“**ใ€‚ๆฌกใซใ€0x110ใฎใ‚ˆใ‚Šๅคงใใชใƒใƒฃใƒณใ‚ฏใ‚’ๅ‰ฒใ‚Šๅฝ“ใฆใ‚‹ใจใ€**ๆœชใ‚ฝใƒผใƒˆใฎใƒ“ใƒณใฎใƒใƒฃใƒณใ‚ฏใŒๅฐใ•ใชใƒ“ใƒณใซ็งปๅ‹•ใ—ใพใ™**ใ€‚

ใใ‚Œใ‚’ใ‚ณใƒณใƒ‘ใ‚คใƒซใ—ใ€`main`้–ขๆ•ฐใฎ`ret`ใ‚ชใƒšใ‚ณใƒผใƒ‰ใซใƒ–ใƒฌใƒผใ‚ฏใƒใ‚คใƒณใƒˆใ‚’่จญๅฎšใ—ใฆใƒ‡ใƒใƒƒใ‚ฐใ—ใพใ™ใ€‚ๆฌกใซใ€`gef`ใ‚’ไฝฟ็”จใ™ใ‚‹ใจใ€tcacheใƒ“ใƒณใŒๆบ€ๆฏใงใ€1ใคใฎใƒใƒฃใƒณใ‚ฏใŒๅฐใ•ใชใƒ“ใƒณใซใ‚ใ‚‹ใ“ใจใŒใ‚ใ‹ใ‚Šใพใ™ใ€‚
```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ใ‚’่ถ…ใˆใ‚‹ใ™ในใฆใฎใƒใƒฃใƒณใ‚ฏใ‚’ๅซใฟใพใ™ใ€‚

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

ไปฅไธ‹ใŒใ‚ใ‚Šใพใ™๏ผš

  • 64B็ฏ„ๅ›ฒใฎใƒ“ใƒณใŒ32ๅ€‹๏ผˆๅฐใ•ใชใƒ“ใƒณใจ่ก็ช๏ผ‰
  • 512B็ฏ„ๅ›ฒใฎใƒ“ใƒณใŒ16ๅ€‹๏ผˆๅฐใ•ใชใƒ“ใƒณใจ่ก็ช๏ผ‰
  • 4096B็ฏ„ๅ›ฒใฎใƒ“ใƒณใŒ8ๅ€‹๏ผˆ้ƒจๅˆ†็š„ใซๅฐใ•ใชใƒ“ใƒณใจ่ก็ช๏ผ‰
  • 32768B็ฏ„ๅ›ฒใฎใƒ“ใƒณใŒ4ๅ€‹
  • 262144B็ฏ„ๅ›ฒใฎใƒ“ใƒณใŒ2ๅ€‹
  • ๆฎ‹ใ‚Šใฎใ‚ตใ‚คใ‚บ็”จใฎใƒ“ใƒณใŒ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ใคใฎๅคงใใชใ‚ขใƒญใ‚ฑใƒผใ‚ทใƒงใƒณใŒ่กŒใ‚ใ‚Œใ€ใใฎๅพŒ1ใคใŒ่งฃๆ”พใ•ใ‚Œ๏ผˆๆœชใ‚ฝใƒผใƒˆใƒ“ใƒณใซๅ…ฅใ‚‹๏ผ‰ใ€ใ‚ˆใ‚Šๅคงใใชใ‚ขใƒญใ‚ฑใƒผใ‚ทใƒงใƒณใŒ่กŒใ‚ใ‚Œใพใ™๏ผˆๆœชใ‚ฝใƒผใƒˆใƒ“ใƒณใ‹ใ‚‰ๅคงใใชใƒ“ใƒณใซ่งฃๆ”พใ•ใ‚ŒใŸใ‚‚ใฎใŒ็งปๅ‹•ใ—ใพใ™๏ผ‰ใ€‚

ใใ‚Œใ‚’ใ‚ณใƒณใƒ‘ใ‚คใƒซใ—ใ€main้–ขๆ•ฐใฎretใ‚ชใƒšใ‚ณใƒผใƒ‰ใซใƒ–ใƒฌใƒผใ‚ฏใƒใ‚คใƒณใƒˆใ‚’่จญๅฎšใ—ใฆใƒ‡ใƒใƒƒใ‚ฐใ—ใพใ™ใ€‚ๆฌกใซใ€gefใ‚’ไฝฟ็”จใ™ใ‚‹ใจใ€tcacheใƒ“ใƒณใŒๆบ€ๆฏใงใ‚ใ‚Šใ€1ใคใฎใƒใƒฃใƒณใ‚ฏใŒๅคงใใชใƒ“ใƒณใซใ‚ใ‚‹ใ“ใจใŒใ‚ใ‹ใ‚Šใพใ™ใ€‚

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ใ‚’ใ‚ตใƒใƒผใƒˆใ™ใ‚‹