ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Use-After-Free GOT Overwrite
    Hack/Pwnable 2016. 10. 2. 04:08
    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
    44
    45
    46
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
     
    struct Box {
        int size;
        char *buf;
    };
     
    struct Box * create_box(int size)
    {
        struct Box * box;
        box = malloc(sizeof(struct Box));
        box-> size = size;
        box-> buf = malloc(size);
        return box;
    }
     
    void free_box (struct Box * box)
    {
        free (box->buf);
        free (box);
    }
     
    int main (int argc, char * argv [])
    {
        struct Box * box;
        int size;
        char * newbuf;
     
        box = create_box (100);
        printf ( "+ box = % p \n", box);
        strncpy (box-> buf, argv[1], 100);
        printf ( "+ box-> buf = % p \n", box->buf);
        free_box (box);
     
        size = atoi (argv [2]);
        newbuf = malloc (size);
        printf ( "+ newbuf = %p \n", newbuf);
        strncpy (newbuf, argv[3], size);
     
        strncpy (box-> buf, argv[4], 100);
     
        free (newbuf);
        return 0;
    }
    cs

    Code by Hatena Blog


    코드는 할당받고 free하고 다시 인풋을받는 구조뿐밖에없다.

    여기서 중요한것은 마지막 strncpy로 box멤버인 buf를 다시 받는것이다.

    당연히 UAF가 발생하는 코드이다.

    (gdb) disas main

    Dump of assembler code for function main:

       0x08048533 <+0>: push   %ebp

       0x08048534 <+1>: mov    %esp,%ebp

       0x08048536 <+3>: and    $0xfffffff0,%esp

       0x08048539 <+6>: sub    $0x20,%esp

       0x0804853c <+9>: movl   $0x64,(%esp)

       0x08048543 <+16>: call   0x80484dd <create_box>

       0x08048548 <+21>: mov    %eax,0x1c(%esp)

       0x0804854c <+25>: mov    0x1c(%esp),%eax

       0x08048550 <+29>: mov    %eax,0x4(%esp)

       0x08048554 <+33>: movl   $0x80486d0,(%esp)

       0x0804855b <+40>: call   0x8048370 <printf@plt>

       0x08048560 <+45>: mov    0xc(%ebp),%eax

       0x08048563 <+48>: add    $0x4,%eax

       0x08048566 <+51>: mov    (%eax),%edx

       0x08048568 <+53>: mov    0x1c(%esp),%eax

       0x0804856c <+57>: mov    0x4(%eax),%eax

       0x0804856f <+60>: movl   $0x64,0x8(%esp)

       0x08048577 <+68>: mov    %edx,0x4(%esp)

       0x0804857b <+72>: mov    %eax,(%esp)

       0x0804857e <+75>: call   0x80483c0 <strncpy@plt>

       0x08048583 <+80>: mov    0x1c(%esp),%eax

       0x08048587 <+84>: mov    0x4(%eax),%eax

    ---Type <return> to continue, or q <return> to quit---

       0x0804858a <+87>: mov    %eax,0x4(%esp)

       0x0804858e <+91>: movl   $0x80486de,(%esp)

       0x08048595 <+98>: call   0x8048370 <printf@plt>

       0x0804859a <+103>: mov    0x1c(%esp),%eax

       0x0804859e <+107>: mov    %eax,(%esp)

       0x080485a1 <+110>: call   0x8048512 <free_box>

       0x080485a6 <+115>: mov    0xc(%ebp),%eax

       0x080485a9 <+118>: add    $0x8,%eax

       0x080485ac <+121>: mov    (%eax),%eax

       0x080485ae <+123>: mov    %eax,(%esp)

       0x080485b1 <+126>: call   0x80483d0 <atoi@plt>

       0x080485b6 <+131>: mov    %eax,0x18(%esp)

       0x080485ba <+135>: mov    0x18(%esp),%eax

       0x080485be <+139>: mov    %eax,(%esp)

       0x080485c1 <+142>: call   0x8048390 <malloc@plt>

       0x080485c6 <+147>: mov    %eax,0x14(%esp)

       0x080485ca <+151>: mov    0x14(%esp),%eax

       0x080485ce <+155>: mov    %eax,0x4(%esp)

       0x080485d2 <+159>: movl   $0x80486f2,(%esp)

       0x080485d9 <+166>: call   0x8048370 <printf@plt>

       0x080485de <+171>: mov    0x18(%esp),%edx

       0x080485e2 <+175>: mov    0xc(%ebp),%eax

       0x080485e5 <+178>: add    $0xc,%eax

    ---Type <return> to continue, or q <return> to quit---

       0x080485e8 <+181>: mov    (%eax),%eax

       0x080485ea <+183>: mov    %edx,0x8(%esp)

       0x080485ee <+187>: mov    %eax,0x4(%esp)

       0x080485f2 <+191>: mov    0x14(%esp),%eax

       0x080485f6 <+195>: mov    %eax,(%esp)

       0x080485f9 <+198>: call   0x80483c0 <strncpy@plt>

       0x080485fe <+203>: mov    0xc(%ebp),%eax

       0x08048601 <+206>: add    $0x10,%eax

       0x08048604 <+209>: mov    (%eax),%edx

       0x08048606 <+211>: mov    0x1c(%esp),%eax

       0x0804860a <+215>: mov    0x4(%eax),%eax

       0x0804860d <+218>: movl   $0x64,0x8(%esp)

       0x08048615 <+226>: mov    %edx,0x4(%esp)

       0x08048619 <+230>: mov    %eax,(%esp)

       0x0804861c <+233>: call   0x80483c0 <strncpy@plt>

       0x08048621 <+238>: mov    0x14(%esp),%eax

       0x08048625 <+242>: mov    %eax,(%esp)

       0x08048628 <+245>: call   0x8048380 <free@plt>

       0x0804862d <+250>: mov    $0x0,%eax

       0x08048632 <+255>: leave  

       0x08048633 <+256>: ret    

    End of assembler dump.

    (gdb) 


    각각 인풋하는곳에 브레이크포인트를걸고 힙 상황을 구경할것이다.

    (ni 해주기 귀찮다면 strncpy@plt 다음 인스트럭션에 브레이크포인트를 걸어준다)



    call strncpy@plt가 호출될때마다 값을 힙에 할당영역에 써넣을것이다.



    보기쉽게 AAAA와 BBBB, CCCC를 넣어주었다.


    각각의 힙 위치에 할당이된것을 알 수 있다.


    힙에 어떻게 값이 쓰여졌는지 확인을 해보자



    `box와 box->buf의 힙이 순서대로 보인다.


    box에선 인풋을 해준것이 없기때문에 유저데이터가 존재하지않는다. 하지만 box->buf에선 우리가 argv[1]값을 AAAA로 넣어주었기때문에 0x41414141이 들어갔다.


    그 다음 상황을 보면, free되고나서 새로운 malloc을 할당해주는 모습이다.




    box를 free하고, 새로운 데이터가 할당된곳은 동일한 곳이다. newbuf는 전의 box주소를 갖게된다.


    argv[3]인 BBBB가 정상적으로 채워졌고, 힙의 상황은 newbuf 다음 box->buf가 오게된다.


    이제 uaf가 발생하는 코드인데, free해주고 나서 다시 box->buf를 입력함으로 인해 갚을 덮어써버린다.




    box->buf가 기존에있던 0x41414141에서 argv[4]였던 CCCC가 덮어써졌다.


    말그대로 free한후 데이터를 사용했기때문에 uaf가 발생하게된다.


    이제 위 상황을 통틀어 8바이트를 할당하고 각각 8바이트의 값을 넣어줄것이다.




    원래 free할 주소가 들어갈곳에 0x43434343이 써졌기때문에 세그폴트가 발생한다.


    이제 이것을 응용해서 exploit을 하여 쉘을 획득해볼것이다.


    들어가는값이 0x43434343으로 변조되면 해당 주소가없기때문에 세그폴트가 발생한다.


    이를 free@got로 바꾸고 쉘코드를 담아 free@got값은 shellcode가있는 힙주소로 할당해볼것이다.


    페이로드는 아래와 같이 구성한다.


    ./uaf shellcode + 8 + AAAAfree@got + 쉘코드있는주소 


    그럼 free@got가 쉘코드있는주소로 할당될것이다.


    아까와같이 브레이크포인트를 각각의 인풋마다 걸어준다.




    첫번째인풋으로 쉘코드가 0x804b018에 정상적으로 들어간다.



    두번째 인풋마저도 잘 들어간다.  free할 주소는 0x804a010 즉, free@got값이 들어가있다.


    여기 까진 문제가 없지만 free@got값이 프리청크에 존재하면, uaf취약점을 통해 argv[4]에있는값이 free@got를 덮어쓰게될것이다.




    uaf취약점 전과 후를 보면 free@got가 쉘코드가있는 주소로 overwrite된것을 확인 할 수 있다.


    이렇게 그 다음의 free가 호출된다면 0x804b018가 호출되어 쉘코드가 실행될 것이다.





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

    Heap Exploit - House of Force  (0) 2016.10.11
    ringzer0 pwnx64  (0) 2016.10.02
    Heap with GDB!  (5) 2016.09.15
    first_fit use after free  (0) 2016.09.13
    fast_dup double free attack  (0) 2016.09.13

    댓글

Designed by Tistory.