-
malloc - unlinkHack/Pwnable 2016. 12. 1. 02:17123456#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는 매우 취약했다 하지만 아래와 같이 패치되었다
1234567891011121314151617181920212223242526272829#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 != NULL, 0)) { \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