Tag → ctf

Proprietary Format

Google CTF 2018

The villains are communicating with their own proprietary file format. Figure out what it is.

$ nc proprietary.ctfcompetition.com 1337

We get a server that will talk to us on a port and a flag.ctf file that’s definitely not a binary. It’s a black-box reversing challenge! I was @-mentioned as the person who might want to due to solving bananaScript (CSAW CTF Quals 2017) as a black box, although that gave a binary that it was possible in theory to reverse. Here black-box reversing is the only option.

For the first few lines of input that the server wants, it responds with quite helpful error messages to help you appease it. If the first line you give it is not P6, it complains:

Cat Chat

Google CTF 2018

You discover this cat enthusiast chat app, but the annoying thing about it is that you’re always banned when you start talking about dogs. Maybe if you would somehow get to know the admin’s password, you could fix that.

This challenge is a simple chat app written in NodeJS. The home page redirects you to a chat room labeled with a random UUID. Anybody can join the same chat room with the URL.

Fresh Cat Chat room

In a chat room, you can chat and issue two commands, /name to set your name and /report to report that somebody is talking about dogs. After anybody in the chat room issues /report, the admin shows up, listens for a while, and bans anybody who mentions the word “dog”.

There are two more commands, /secret and /ban, which are in the server source code and also described in comments in the HTML source if you didn’t notice:

JS Safe 2.0

Google CTF 2018

You stumbled upon someone’s “JS Safe” on the web. It’s a simple HTML file that can store secrets in the browser’s localStorage. This means that you won’t be able to extract any secret from it (the secrets are on the computer of the owner), but it looks like it was hand-crafted to work only with the password of the owner…

The challenge consists of a fancy HTML file with a cute but irrelevant animated cube and some embedded JavaScript.

Screenshot of JS Safe 2.0 with a text box and a cube


DEF CON CTF Qualifiers 2018

The hardest challenge of not very many I solved in this CTF. What a struggle! I have a long way to improve. It was pretty fun though. (I solved “You Already Know”, and got the essence of “ghettohackers: Throwback”, but didn’t guess the right flag format and believe I was asleep when they released the hint about it.)

The challenge consists of a simple PHP script that opens a MySQL connection and then feeds our input into a custom PHP extension shellme.so.

$link = mysqli_connect('localhost', 'shellql', 'shellql', 'shellql');
if (isset($_POST['shell']))
if (strlen($_POST['shell']) <= 1000)
echo $_POST['shell'];

The extension basically just executes $_POST['shell'] as shellcode after a strict SECCOMP call, prctl(22, 1). This means that we can only use the four syscalls read, write, and exit, and sigreturn, where the latter two aren’t particularly useful.

Disassembled innermost function of interest in shellme.so
Disassembled innermost function of interest in shellme.so

The goal is to read the flag from the open MySQL connection.


PlaidCTF 2018

We are presented with a big zip file of SML code, which implements an interpreter for a small ML-like language with a form of taint analysis in its type checker, called Wolf. Concretely, every type in Wolf’s type system has an associated secrecy: it is either “private” or “public”, and in theory, the type system makes it impossible to do any computation on private data to get a public result.

Of course, this is a CTF, so the challenge is all about breaking the theoretical guarantees of the type system. When we submit code, it’s evaluated in a context with a private integer variable flag; our code is typechecked, executed, and printed, but only if its type is public. The goal is to break the type system and write code that produces a public value that depends on flag, so that we can exfiltrate flag itself.

In all, there are three progressively harder Wolf problems, named Pupper, Doggo, and Woofer. Doggo and Woofer are each encrypted with the flag of the challenge before it, so that you need to solve them in order (unless you can somehow blindly exploit servers running SML programs).

Wolf Overview

Let’s first go over the Wolf syntax and semantics. (There are small differences between the three problems, but they’re syntactically identical and only semantically differ in cases that we’ll naturally get to.) The examples folder has some examples of valid code:

let x = (5 :> private int) in

Messy Desk

PlaidCTF 2018

This challenge is a video of somebody’s messy desk, with what is apparently the audio from a Futurama clip. The desk is indeed extremely messy and full of things that aren’t particularly useful for us, but close examination reveals a QR code reflected in the globe in the middle.

The challenge is all about getting that QR code. After trying our best to clean up the image, we ended up with this:

Maximally enhanced image of the QR code
Maximally enhanced image of the QR code

Thoroughly Stripped

CSAW CTF 2017 Finals (Forensics, 200 pts)

Woo, first CTF writeup. I got the opportunity to participate in the 2017 CSAW CTF finals with Don’t Hack Alone.

Dumped by my core, left to bleed out bytes on the heap, I was stripped of my dignity… The last thing I could do was to let other programs strip me of my null-bytes just so my memory could live on.

We are provided with a core dump. Examining the flavor-text and the dump, we notice that the dump has no null bytes; we conjecture that they have been stripped out.

Next, we examine the hexdump and look for any clues. There are a bunch of ASCII strings, but they look like normal debugging symbols. One thing that jumps out is that there are a couple fairly convincing regular striped patterns that become vertically aligned if you display 20 bytes in each line. Once we do that, we notice the following section. (This dump is from xxb but xxd -c 20 thoroughlyStripped is quite sufficient.)



(Okay, this post is backdated.)

Disassembling the executable produces a huge amount of code. There are some basic obfuscations like a lot of trivial identity functions nested in each other, and a few functions that wrap around identity functions but just add some constant multiple of 16. Most of the meat is in one very large function, though. If you disassemble this function with IDA, you see a lot of variable initializations and then a lot of interesting loops that are quite similar: