본문 바로가기
시스템 해킹/HEAP

Double Free BUG unlink

by sonysame 2018. 2. 17.

Double Free Bug는 free()함수가 수행되는 과정 중 unlink라는 매크로


에 의해 발생한다!



32비트

FD+12->BK
BK+8->FD


64비트

FD+24->BK

BK+16->FD


unlink가 이루어지는 경우


1) free된 chunk가 다시 malloc되는 경우!


bin리스트는 double linked list로 관리되는데(fast bin은 single linked list) 

double linked list중 중간에 있는 chunk가 나가게 되면 그 앞과 뒤를 다시 연결해주는 작업이 필요하다!


2) chunk의 사이즈가 증가하여 다른 bin리스트로 이동하는 경우!


어떤 chunk가 free되었을 때, 연속된 위치의 다른 chunk가 free되어 있다면 두 chunk를 합병하여 하나로 만들어준다.

이때는 chunk의 사이즈가 증가하기 때문에 원래 속해있던 bin 리스트에서 해당 chunk를 제거하고 다시 적절한 bin리스트에 넣어주어야 한다


#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <stdio.h>
 
void winner()
{
        printf("that wasn't too bad now, was it? @ %d\n", time(NULL));
}
 
int main(int argc, char **argv)
{
        char *a, *b, *c;
 
        a = malloc(32);
        b = malloc(32);
        c = malloc(32);
 
        strcpy(a, argv[1]);
        strcpy(b, argv[2]);
        strcpy(c, argv[3]);
 
        free(c);
        free(b);
        free(a);
 
        printf("dynamite failed?\n");
}


이런코드가 있다고 하자!


일단, free(c)가 이루어지고!

free(b)에서 p비트를 0으로 바꾸어 이전 청크가 free로 간주되게끔!

그러면 합병이 이루어져서 a에서 unlink가 불러진다

a의 위치는 어떻게 찾냐!

b에서 previous chunk size를 이용하는데, previous chunk size에 -4를 주면

b+4위치에 a가 있다고 간주된다.

b+4는 chunk size부분이고, b+8에는 fd, b+12에는 bk가 들어간다!

unlink를 이용할떄!

[fd+12]=bk

[bk+8]=fd 가 되므로,

fd에는 printf의 GOT-12를 넣는다. bk에는 쉘코드의 주소를 넣어준다!


하지만 실패할 수 있다!


bk+8이 writeable하지 않을 수도 있기 때문!




다른 예제를 살펴보자!

  1 #include <string.h>

  2 #include <stdlib.h>

  3 #include <stdio.h>

  4 

  5 int main(int argc, char *argv[])

  6 {

  7   char * p = malloc(128);

  8   char * q = malloc(256);

  9 

 10   read(0, p, 200);

 11 

 12   free(q);

 13   free(p);

 14 }

 15


free(q)에서 지금 p비트가 0으로 바뀌었다!
즉, p가 free된 상태로 간주한다는 것이다.

그렇다면, 이전 청크가 free되어 있으므로, p와 q가 합병되면서 unlink가 불러지는데,

이때는 이전 청크로 간주된 p가 지워지는 작업이 생긴다.

p의 위치를 찾아야 하는데,

q의 prev_size를 이용하는데, 지금 -4로 되어 있으므로, p는 q+4에서 시작을 한다.

q+4의 위치는 size=0xfffffffa이고, CCCC는 FD이고, DDDD는 BK가 된다.


unlink의 과정은 

[FD+8]=bk

[BK+4]=fd가 되므로,


[CCCC+8]=DDDD

[DDDD+4]=CCCC가 된다!


여기서는 왜!!!!!! 12가 아닌 8인가!! 그것은 이게 gcc를 이용해서 직접 컴파일 한 것이 아니라 이미 컴파일 된 바이너리 였고, free함수가 아닌 만들어 놓은 free함수를 이용했기 때문! 코딩이 그렇게 되어 있다!

아무튼, 두번째 free에 가기도 전에! 첫번째 free에서 빵 터진다!




CCCC+8과 DDDD+4이 writeable한 곳이라면! DDDD+4에 CCCC를 넣을 수 있다!





'시스템 해킹 > HEAP' 카테고리의 다른 글

how2heap-fastbin_dup_into_stack  (0) 2018.02.18
Heap Overflow  (0) 2018.02.17
Use After Free  (0) 2018.02.16
malloc free 실습 fastbin unsortbin 정리!  (0) 2018.02.16
Fast bin  (0) 2018.02.16