ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • malloc - unlink
    Hack/Pwnable 2016. 12. 1. 02:17
    1
    2
    3
    4
    5
    6
    #define unlink(P, BK, FD) {                                            \
      FD = P->fd;                                                          \
      BK = P->bk;                                                          \
      FD->bk = BK;                                                         \
      BK->fd = FD;                                                         \
    }
    cs



    unlink는 free가 연속적으로 될때 병합시키기위해 호출되는 매크로이다.


    P는 현재 청크이고, 위 인스트럭션은 아래와 같이 나타난다.


    FD = *P + 8;
    BK = *P + 12;
    FD + 12 = BK;
    BK + 8 = FD;


    위를 보면 FD와 BK 포인터를 조작할 수 있게되면 FD+12 위치를 BK로 덮을 수 있다는 얘기가 된다.


    그래서 항상 double free bug 공격을 할 때, fd-12 위치를 넣어주는 이유도 +12가 되기때문에 fd에 제대로 작성하기위해 -12를 넣어주는것이다.


    이는 32비트에서의 얘기고 64비트는 아래와같이 FD+24위치를 BK로 덮을 수 있다.


    FD = *P + 16; BK = *P + 24; FD + 16 = BK; BK + 24 = FD;


    FD와 BK가 검증없이 호출되던 전의 unlink는 매우 취약했다 하지만 아래와 같이 패치되었다


    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
    #define unlink(P, BK, FD) {                                            \
      FD = P->fd;                                                          \
      BK = P->bk;                                                          \
      if (__builtin_expect (FD->bk != P || BK->fd != P, 0))                \
        malloc_printerr (check_action, "corrupted double-linked list", P); \
      else {                                                               \
        FD->bk = BK;                                                       \
        BK->fd = FD;                                                       \
        if (!in_smallbin_range (P->size)                       \
        && __builtin_expect (P->fd_nextsize != NULL0)) {           \
          assert (P->fd_nextsize->bk_nextsize == P);               \
          assert (P->bk_nextsize->fd_nextsize == P);               \
          if (FD->fd_nextsize == NULL) {                       \
        if (P->fd_nextsize == P)                       \
          FD->fd_nextsize = FD->bk_nextsize = FD;               \
        else {                                   \
          FD->fd_nextsize = P->fd_nextsize;                   \
          FD->bk_nextsize = P->bk_nextsize;                   \
          P->fd_nextsize->bk_nextsize = FD;                   \
          P->bk_nextsize->fd_nextsize = FD;                   \
        }                                   \
          }    else {                                   \
        P->fd_nextsize->bk_nextsize = P->bk_nextsize;               \
        P->bk_nextsize->fd_nextsize = P->fd_nextsize;               \
          }                                       \
        }                                       \
      }                                                                    \
    }
     
    cs



    if (__builtin_expect (FD->bk != P || BK->fd != P, 0))                \
        malloc_printerr (check_action, "corrupted double-linked list", P);


    해당 부분이 핵심인데, FD->bk가 청크가 아니거나 BK->fd가 청크가 아니라면 corrupted double-linked list 에러가 발생한다.


    이를 우회하는것이 bss에 있는 주소같은경우, malloc pointer 주소를 알기때문에 이 주소를 넣어 우회를 할 수 있다.


    조건이 맞을경우 아래와 같은 코드로 unlink가 그대로 진행된다.


        FD->bk = BK;                                                       \
        BK->fd = FD; 



    그리고 밑에 if문은 small_bin이 아닐경우에서의 코드인데, 해당 청크의 size와 fd_nexsize가 NULL이 아니면 아래 코드가 실행된다.


    똑같이 P->fd_netsize->bk_nextsize == P 조건과 P->bk_nextsize->fd_nextsize == P 즉, 해당 청크 포인터 주소가 아니면 Abort를 띄운다.



    또한, FD->fd_nextsize가 NULL이면, fd_nextsize가 청크포인터인지 검사한후, 똑같이 Unlink로 병합이 진행된다.

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

    malloc - do_check_free_chunk()  (0) 2016.12.01
    malloc - do_check_chunk()  (0) 2016.12.01
    malloc chunk2mem  (0) 2016.12.01
    malloc분석  (0) 2016.12.01
    [BlackHat Heap] GNU libc's double free() protection  (0) 2016.11.30

    댓글

Designed by Tistory.