Fastbin Consolidate
Fastbin Consolidate?
fastbin의 처리 로직 때문에 생기는 취약점이다.
malloc으로 큰 크기의 요청이 들어오면 fastbin에 있던 청크들을 병합 시킨 뒤 unsorted bin으로 넣는다.
그 다음 unsorted bin을 정리하는 과정에서 적절한 bin(small, large)으로 이동시킨다.
→ 큰 크기의 요청을 받아 unsorted bin으로 이동되어 fastbin에서 사라진 청크를 다시 free함으로써 double free가 발생한다
1. 청크 할당
glibc 2.23 fastbin에서 unsorted bin으로 청크를 옮기는 과정은 다음과 같다.
if ((unsigned long) (nb) <= (unsigned long) (get_max_fast ()))
- 요청된 크기가 fastbin의 최대 크기보다 작거나 같은지 확인한다.
idx = fastbin_index(nb);
fb = &fastbin(av, idx);
victim = *fb
- 요청된 크기에 맞는 인덱스를 계산하고 해당 fastbin 리스트의 맨 앞에 있는 청크를 victim으로 가져온다.
if (victim == 0)
if (__builtin_expect (fastbin_index (chunksize (victim)) != idx, 0))
{
errstr = "malloc(): memory corruption (fast)";
errout:
- fastbin에 청크가 있다면 꺼내온 청크 victim이 fastbin에 속하는 크기가 맞는지 확인한다.
2.malloc consolidate
// in malloc_consolidate()
// ... 루프 시작 ...
p = fb->fd; // fastbin 리스트의 첫번째 청크
if (p == 0) // 리스트가 비어있으면 다음으로
continue;
fb->fd = 0; // fastbin 리스트 비우기
fastbin에 청크가 있다면 맨 앞에 있는 청크p를 꺼내고 리스트에서 제거한다.
그 다음 꺼내온 청크p 에 대해 일반적인 free와 같이 앞/뒤 청크와 병합을 시도한다.
- 뒤로 병합 : p의 바로 다음 청크가 free인지 확인하고, 맞다면 병합한다.
- 앞으로 병합 : p의 바로 이전 청크가 free 상태인지 확인하고, 맞다면 병합한다.
마지막으로 병합된 청크를 unsorted bin의 맨 앞에 삽입한다.
예제 코드
#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);
}
1. fastbin 청크 등록
void* p1 = malloc(0x10);
void* p2 = malloc(0x10);
free(p1);
fastbin 크기의 힙을 2개 할당하고 첫 번째 청크 p1을 해제한다.

첫 번째 free 후 fastbin 상태이다.
왜 힙을 2개 할당할까?
힙을 하나만 할당하게 된다면 double free를 발생시킬 때 p1은 top chunk와 인접하게 된다.
malloc consolidate는 해제된 청크가 top chunk와 인접해 있으면 top chunk와 병합한다.
따라서 p1을 한 번 더 free하게 되면 top chunk를 해제하려는 시도가 되어 오류가 발생한다.
2. malloc consolidate
void* p3 = malloc(0x400);
0x400이라는 큰 크기의 요청을 하여 malloc consolidate를 호출한다.
malloc consolidate는 fastbin에 있던 p1을 꺼내 병합을 시도한 뒤 unsorted bin으로 옮긴다.

unsorted bin에서 small bin으로 옮겨진 후의 힙 상태이다.
3. double free 검증 우회
free(p1);
p1을 한 번 더 해제하여 double free를 발생시킨다.
malloc consolidate함수로 인해 fastbin이 비워졌기 때문에 free함수는 p1을 다시 fastbin에 넣는다.

smallbin과 fastbin에 같은 청크가 들어있는 것을 볼 수 있다.
double free가 발생하여 smallbin의 청크에는 invalid memory가 뜬 것을 알 수 있다.
4. malloc 할당
char *ptr = malloc(0x10);
char *ptr2 = malloc(0x10);
ptr은 fastbin을 확인하고 p1을 먼저 반환한다.
ptr2는 fastbin은 비어있기 때문에 unsorted bin을 확인하고 p1을 한 번 더 반환한다.

첫 번째 malloc 후 fastbin에 있던 청크가 할당되었다.

두 번째 malloc 후 smallbin에 있던 청크가 할당되었다.
5. p1 == p2
printf("ptr: %p\\n", ptr);
printf("ptr2: %p\\n", ptr2);
최종적으로 ptr과 ptr2는 동일한 주소값을 가지게 된다.

ptr과 ptr2가 같은 주소를 가진 것을 확인할 수 있다.
'Pwnable > Heap' 카테고리의 다른 글
| Unsorted bin attack (0) | 2026.01.19 |
|---|---|
| Unsafe Unlink (0) | 2026.01.15 |
| Fastbin Duplicate (0) | 2026.01.13 |
| Heap - glibc 2.23 (3) (0) | 2026.01.13 |
| Heap - glibc 2.23 (2) (1) | 2026.01.12 |