혜랑's STORY

[Dreamhack] Heap Allocator Exploit : fastbin dup consolidate 본문

2021 SISS 21기 활동/2학시 시스템

[Dreamhack] Heap Allocator Exploit : fastbin dup consolidate

hyerang0125 2021. 9. 26. 19:10

fastbin dup consolidate

fastbin dup consolidate는 fastbin에 들어간 힙 청크들을 병합시켜 smallbin에 넣어 Double Free 검증을 우회하는 기법이다. smallbin에 들어간 fastbin 크기의 힙 청크를 한 번 더 해제하면 다시 fastbin에 들어가기 대문에 검증을 우회할 수 있다.

_int_malloc
#define have_fastchunks(M)     (((M)->flags & FASTCHUNKS_BIT) == 0)
else
{
    idx= largebin_index (nb);
    if (have_fastchunks (av))
        malloc_consolidate (av);
}

위 코드를 확인해보면, malloc 함수 내부에서 largebin 크기의 할당 요청이 들어올 때 have_fastchunks 매크로를 통해 fastbin에 할당된 청크가 존재하는지 확인하고, 존재한다면 malloc_consolidate 함수를 통해 존재하는 청크들을 병합한다.

이 과정에서 old와 p 포인터를 다르게 만들어 다음 검증을 우회할 수 있다.

if (__builtin_expect (old == p, 0)
{
       errstr = "double free or corruption (fasttop)";
      goto errout;
}

consolidate.c
// gcc -o consolidate consolidate.c
#include <stdio.h>
#include <stdlib.h>
int main() {
  void* p1 = malloc(0x10);
  void* p2 = malloc(0x10);
  free(p1);
  void* p3 = malloc(0x400);
  free(p1);
  char *ptr = malloc(0x10);
  char *ptr2 = malloc(0x10);
  printf("ptr: %p\n", ptr);
  printf("ptr2: %p\n", ptr2);
}

위 코드는 fastbin 크기의 힙을 두 개 할당하고 첫 번째 청크를 해제한다. 만약 첫 번째 청크를 다시 해제한다면 old와 p 포인터가 같으므로 에러가 발생할 것이다.

그러나 largebin 크기의 힙을 할당하면 malloc_consolidate를 호출하여 fastbin에 존재하는 청크를 smallbin에 삽입하고, 다시 첫 번째 청크를 해제하면 이는 fastbin에 삽입되기 때문에 에러 없이 Double Free를 발생시킬 수 있다.

p1이 해제되는 곳에 bp 설정

p1이 해제되면서 fastbin에 들어간 것을 확인할 수 있다.

largebin 크기의 힙을 할당한 후 모습을 보기 위해 main+58dp bp를 설정하고 실행하였다.

largebin 크기의 힙이 할당되면서 fastbin이 smallbin으로 병합된 것을 확인할 수 있다. 다시 0x602000 주소를 해제하면 다음과 같이 fastbin에 들어가게 된다.

이 상태에서 0x10 크기의 힙을 두 번 할당하면 fastbin에 들어간 주소를 먼저 가져오고, 이후 smallbin에 들어간 주소를 가져오기 때문에 두 개의 다른 포인터가 같은 힙 영역을 가리킬 수 있게 된다.

실행시켜보자.

두 개의 주소가 같은 것을 볼 수 있다.