RCTF 2019 is a Jeopardy-style Online Capture the Flag Competition presented by Team ROIS.

May 18 - May 20 2019

RCTF 2019

I only had a chance to poke at this one a bit, and ended up only solving one easy challenge.

Draw (Misc)

I'm god's child.

Flag format: RCTF_[A-Za-z]
cs pu lt 90 fd 500 rt 90 pd fd 100 rt 90 repeat 18[fd 5 rt 10] lt 135 fd 50 lt 135 pu bk 100 pd setcolor pick [ red orange yellow green blue violet ] repeat 18[fd 5 rt 10] rt 90 fd 60 rt 90 bk 30 rt 90 fd 60 pu lt 90 fd 100 pd rt 90 fd 50 bk 50 setcolor pick [ red orange yellow green blue violet ] lt 90 fd 50 rt 90 fd 50 pu fd 50 pd fd 25 bk 50 fd 25 rt 90 fd 50 pu setcolor pick [ red orange yellow green blue violet ] fd 100 rt 90 fd 30 rt 45 pd fd 50 bk 50 rt 90 fd 50 bk 100 fd 50 rt 45 pu fd 50 lt 90 pd fd 50 bk 50 rt 90 setcolor pick [ red orange yellow green blue violet ] fd 50 pu lt 90 fd 100 pd fd 50 rt 90 fd 25 bk 25 lt 90 bk 25 rt 90 fd 25 setcolor pick [ red orange yellow green blue violet ] pu fd 25 lt 90 bk 30 pd rt 90 fd 25 pu fd 25 lt 90 pd fd 50 bk 25 rt 90 fd 25 lt 90 fd 25 bk 50 pu bk 100 lt 90 setcolor pick [ red orange yellow green blue violet ] fd 100 pd rt 90 arc 360 20 pu rt 90 fd 50 pd arc 360 15 pu fd 15 setcolor pick [ red orange yellow green blue violet ] lt 90 pd bk 50 lt 90 fd 25 pu home bk 100 lt 90 fd 100 pd arc 360 20 pu home

This is clearly a set of instructions for some sort of drawing program, and a search using the instructions indicates that it is a set of MicroWorlds Logo commands. There is a Logo interpreter at https://www.calormen.com/jslogo/, and running these instructions draws this:

So, our flag is RCTF_HeyLogo

Disk (Misc)

An otaku used VeraCrypt to encrypt his favorites.

Password: rctf
Flag format: rctf{a-zA-Z0-9_}

The zipped attachment contains encrypt.vmdk, but attempts to open it in Virtual Box failed (could not get the storage format of the medium). Some searching indicates that this is the result of the VMDK file being incomplete, or it is not a VMDK file. An attempt to convert the VMDK to a VDI using Vboxmanage clonehd resulted in the same error. Opening the file in Hex Fiend, it opens with the KDMV header, and there is a lot of empty space in here. Running strings on the file, though, turns up:

Invalid partition table
Error loading operating system
Missing operating system

and two large repeating blocks of:

This isn’t accepted as a flag (nor is rctf{unseCure_quick_form4t_vo1ume}).

So, looking a little closer at VeraCrypt – it is a disk encryption software product. Mounting the disk in VeraCrypt, and using the provided password (rctf), returns a failure due to: incorrect password, incorrect volume PIM number, incorrect PRF (hash), or not a valid volume.

The two large repeating blocks got me to look closer at the hex, and there is a short empty stretch between two sections, each filled with unreadable content and a repeating block. This would seem to indicate a hidden volume ( https://www.veracrypt.fr/en/Hidden%20Volume.html). Trying rctf{unseCure_quick_form4t_vo1ume as the password, however, returns the same error as before. Maybe that was it, and there was just a formatting issue, but I decided to keep looking.

From the clues, so far, it looks like the file is a VeraCrypt quick-formatted regular volume and hidden volume. The invalid partition table, however, is likely causing us trouble.

In the documentation for VeraCrypt ( https://www.veracrypt.fr/en/Troubleshooting.html), the issue appears to be solvable using VeraCrypt’s “Restore Volume Header” tool.

To restore the volume header from the backup embedded in the volume by following these steps:
1. Run VeraCrypt.
2. Click Select Device or Select File to select your volume.
3. Select Tools > Restore Volume Header.

This, however, did not solve our problem, and the same error arises.

Printer (Misc)

The supermarket bought a new printer last night. I hacked into their computer and captured the USB traffic on it. Could you help me steal the secret?

Flag format: flag{0-9a-z_} (Convert uppercase to lowercase)

The attached file contains Printer.pcapng, so let’s pop it into Wireshark…

The traffic is all USB, and primarily URB_INTERRUPT in packets. There are several nodes, including host, 1.6.0, 1.6.1, 1.7.0, and 1.7.1. The URB_INTERRUPT packets are all from 1.6.1. These packets differ only in their IRP ID and slightly in some leftover capture data. This looks like mouse movement data.

There are some GET DESCRIPTOR packets, between the host and 1.6.0 and 1.7.0. The Response STRING and Status packets from 1.6.0 to the host indicate a Logitech device of some description. The DEVICE response packet from 1.7.0 shows an unknown device from NXP Semiconductors, a manufacturer of various POS, Industrial, and USB Thermal Printers. The URB_CONTROL in packet from 1.7.0 indicates that it is a barcode printer.

The remaining packets from 1.7.1 are URB_BULK out packets that are much larger than the others (163 and 3332 vs. 28-78 bytes in length). The smaller URB_BULK packet contains printer parameters (Size 47.5mm x 80.1mm; Gap 3mm; Direction 0; Reference 0,0; Offset 0mm). The larger packet contains Bitmap data, with three sets of barcode printing instructions. I can get some image data to display when they are pasted into a sample barcode BMP, but nothing that is readable…

Nextphp (web)

PHP is the best language!

The website just displays some source code:

if (isset($_GET['a'])) {
} else {

This is code to run the code in “a” using a GET request - the eval command will run any valid PHP code fed to it…in this case the result of the GET request for the variable “a”.

So, trying a URL GET request for “a”:

gets us a blank (not a 404) page. And
displays the php configuration info on that page. We have arbitrary code execution, so let’s see what we can see.

gets us:
Array ( [0] => . [1] => .. [2] => index.php [3] => preload.php )

Other directories seem inaccessible, including .. and /

Browsing to /index.php, we get the original source code page. Browsing to /preload.php, returns an empty page, but
returns (my line formatting, ## my comments):

null, 'func' => 'print_r', 'arg' => '1' ];
## set func to “print_r” and arg to “1”

private function run () {
$this->data['ret'] = $this->data['func']($this->data['arg']);
## set this object’s data property ‘ret’ to print_r(1)

public function __serialize(): array {
return $this->data;
## returns a storable representation of the current variable if it’s an array

public function __unserialize(array $data) {
array_merge($this->data, $data);
## adds the data property array to the current variable
## and sends the outcome to the run() function

public function serialize (): string {
return serialize($this->data);
## returns a storable representation of the current variable if it’s a string

public function unserialize($payload) {
$this->data = unserialize($payload);
## set the data property to the unserialized version of the provided $payload variable
## and send the outcome to the run() function

public function __get ($key) {
return $this->data[$key];
## returns the contents of provided position ($key) in the array data to the current variable

public function __set ($key, $value) {
throw new \Exception('No implemented');
## set function not implemented

public function __construct () {
throw new \Exception('No implemented');
## contruct function not implemented


I scored about 120 points for a flag format gimme challenge and the Draw challenge (diminishing point count for the latter and neither appears to have remained on the scoreboard). The top player scored 11509.
That puts me in the tie range of 123-264/405