상세 컨텐츠

본문 제목

ptmalloc2 allocator in GLIBC 2.29

SYSTEM HACKING/Exploit Tech

by koharin 2024. 3. 2. 14:25

본문

728x90
반응형

GLIBC란?

GNU system과 GNU/Linux 시스템의 핵심 라이브러리를 제공하는 GNU C 라이브러리

 

ptmalloc2 구조 (GLIBC 2.29) - Double Free 검증

tcache_entry 구조체

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

GLIBC 2.26과 다르게, GLIBC 2.29에서는 tcache_put, tcache_get 함수에 Double Free 취약점을 검증하는 코드가 추가되었다.

GLIBC 2.26에서는 tcache_entry 구조체에 tcache_entry *next만 있었다면, GLIBC 2.29에서는 tcache_perthread_struct *key 멤버가 추가되었다.

tcache_put 함수

static __always_inline void tcache_put (mchunkptr chunk, size_t tc_idx)
{
  tcache_entry *e = (tcache_entry *) chunk2mem (chunk);
  assert (tc_idx < TCACHE_MAX_BINS);
  /* Mark this chunk as "in the tcache" so the test in _int_free will
     detect a double free.  */
  e->key = tcache; 
  e->next = tcache->entries[tc_idx];
  tcache->entries[tc_idx] = e;
  ++(tcache->counts[tc_idx]);
}

e->key에 tcache_entry 구조체의 주소, 즉 tcache 포인터를 적어놓는다. 

이후 free() 함수 호출로 _init_free() 함수가 호출되면, _init_free() 함수 내부에서 e->key를 Double Free 여부를 확인하는데 사용한다. 

 

tcache_get 함수

static __always_inline void * tcache_get (size_t tc_idx)
{
  tcache_entry *e = tcache->entries[tc_idx];
  assert (tc_idx < TCACHE_MAX_BINS);
  assert (tcache->entries[tc_idx] > 0);
  tcache->entries[tc_idx] = e->next;
  --(tcache->counts[tc_idx]);
  e->key = NULL;
  return (void *) e;
}

e->key에 NULL을 넣음

 

_init_free 함수

tcache_entry *e = (tcache_entry *) chunk2mem (p);

/* This test succeeds on double free.  However, we don't 100%
   trust it (it also matches random payload data at a 1 in
   2^<size_t> chance), so verify it's not an unlikely
   coincidence before aborting.  */
if (__glibc_unlikely (e->key == tcache))
{
	tcache_entry *tmp;
	LIBC_PROBE (memory_tcache_double_free, 2, e, tc_idx);
	for (tmp = tcache->entries[tc_idx]; tmp; tmp = tmp->next)
		if (tmp == e)
			malloc_printerr ("free(): double free detected in tcache 2");
			/* If we get here, it was a coincidence.  We've wasted a
			   few cycles, but don't abort.  */
}

free 함수가 호출되어 힙 청크 해제를 요청하면 __init_free 함수가 호출된다. tcache_put 함수에서는 e->key에 해당 chunk 주소를 넣는다. 만약 e->key에 있는 주소에 대한 해제가 요청되는 경우 double free이므로 에러 출력됨

 

ptmalloc2 구조 (GLIBC 2.29) - unsorted bin attack 검증

unsorted bin attack

unsorted bin의 bk를 임의의 주소로 조작하여 해당 영역에 main_arena 주소를 적는 공격. 이를 통해 libc 주소를 leak할 수 있음.

 

if (__glibc_unlikely (bck->fd != victim)
              || __glibc_unlikely (victim->fd != unsorted_chunks (av)))
            malloc_printerr ("malloc(): unsorted double linked list corrupted");

 

GLIBC 2.29에서의 _int_malloc 함수에서 위 검사로 인하여 unsorted bin 공격을 할 수 없다.

if (__glibc_unlikely (size <= 2 * SIZE_SZ) || __glibc_unlikely (size > av->system_mem))
    malloc_printerr ("malloc(): invalid size (unsorted)");

unsorted bin 청크의 size가 할당한 것보다 작거나 할당 가능한 값보다 큰 경우 오류 메세지 출력하고 비정상 종료한다.

 

ptmalloc2 구조 (GLIBC 2.29) - top chunk 검증

victim = av->top;
size = chunksize (victim);

if (__glibc_unlikely (size > av->system_mem))
    malloc_printerr ("malloc(): corrupted top size");

GLIBC 2.29 버전부터 top 청크 검증이 추가되어 House of Force 공격(top chunk size를 -1로 할당하고 청크를 임의의 영역에 할당하는 공격)이 불가능해졌다.

 

 

728x90
반응형

'SYSTEM HACKING > Exploit Tech' 카테고리의 다른 글

_IO_FILE  (0) 2021.01.01
tcache memory leak  (0) 2020.06.13
House of Force  (0) 2020.06.12
Unsafe Unlink  (0) 2020.06.12
Poison NULL Byte  (0) 2020.06.12

관련글 더보기