tcache가 없는 glibc 2.23 (ubuntu 16.04) 버전으로 실습을 진행했다.
fastbin_dup.c
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
int main()
{
fprintf(stderr, "This file demonstrates a simple double-free attack with fastbins.\n");
fprintf(stderr, "Allocating 3 buffers.\n");
int *a = malloc(8);
int *b = malloc(8);
int *c = malloc(8);
fprintf(stderr, "1st malloc(8): %p\n", a);
fprintf(stderr, "2nd malloc(8): %p\n", b);
fprintf(stderr, "3rd malloc(8): %p\n", c);
fprintf(stderr, "Freeing the first one...\n");
free(a);
fprintf(stderr, "If we free %p again, things will crash because %p is at the top of the free list.\n", a, a);
// free(a);
fprintf(stderr, "So, instead, we'll free %p.\n", b);
free(b);
fprintf(stderr, "Now, we can free %p again, since it's not the head of the free list.\n", a);
free(a);
fprintf(stderr, "Now the free list has [ %p, %p, %p ]. If we malloc 3 times, we'll get %p twice!\n", a, b, a, a);
a = malloc(8);
b = malloc(8);
c = malloc(8);
fprintf(stderr, "1st malloc(8): %p\n", a);
fprintf(stderr, "2nd malloc(8): %p\n", b);
fprintf(stderr, "3rd malloc(8): %p\n", c);
assert(a == c);
}
이 파일은 fastbin을 이용한 간단한 double free 공격을 보여준다.
실행 결과는 위와 같고, 코드를 단계별로 나누어서 분석할 것이다.
fprintf(stderr, "Allocating 3 buffers.\n");
int *a = malloc(8);
int *b = malloc(8);
int *c = malloc(8);
먼저, 3개의 chunk를 할당한다.
3개의 chunk가 잘 할당된 것을 확인 할 수 있다.
fprintf(stderr, "Freeing the first one...\n");
free(a);
a chunk(0x248e010)를 free한다.
fprintf(stderr, "If we free %p again, things will crash because %p is at the top of the free list.\n", a, a);
// free(a);
다음 코드에서는 에러가 나는 상태를 주석처리로 설명해놓은 부분이다. 만약 이 주석 부분을 해제하고 컴파일을 하면 해당 부분에서 에러가 난다. 그 이유는 현재 a 청크는 fastbin의 최상위에 있기 때문이다. 따라서, 다음 코드와 같이 b chunk를 free하여 다시 a chunk를 free할 수 있도록 한다.
fprintf(stderr, "So, instead, we'll free %p.\n", b);
free(b);
fprintf(stderr, "Now, we can free %p again, since it's not the head of the free list.\n", a);
free(a);
fprintf(stderr, "Now the free list has [ %p, %p, %p ]. If we malloc 3 times, we'll get %p twice!\n", a, b, a, a);
위와 같이 free를 진행하게 되면, a chunk를 다시 한번 더 free 시킬 수 있다. 이때 double free bug가 발생하게 되고, fastbin의 chunk는 다음과 같이 구성된다.
a(0x248e010)
→ b(0x248e030)
→ a(0x248e010)
a = malloc(8);
b = malloc(8);
c = malloc(8);
fprintf(stderr, "1st malloc(8): %p\n", a);
fprintf(stderr, "2nd malloc(8): %p\n", b);
fprintf(stderr, "3rd malloc(8): %p\n", c);
해당 fastbin에서 앞서 해제했던 크기로 재할당시, a와 c에 동일한 chunk를 할당하게된다.
이러한 double free를 이용해서 공격자가 원하는 주소를 할당 받을 수도 있다. 이는 how2heap의 다음 과정(fastbin_dup_into_stack)에서 double free bug를 통해 스택의 주소를 할당 받는 것을 실습한다.
Uploaded by N2T