Writeup – bender_safe (Insomni’hack 2017 Teaser)

This weekend, I participated in the Insomni’hack 2017 Teaser. During this CTF, I got schooled pretty hardcore, but I was able to solve one challenge in the time allocated. I will write this challenge up below.


This challenge is presented as a Linux MIPS binary, as well as a standalone qemu-mips wrapper. You can download this binary here.

This binary presents the user with an “OTP challenge”, for which the user must generate the correct corresponding token:


We begin our adventure by reverse engineering the code. We can determine that this reads 8 bytes of OS-generated random data, and then transforms this into the OTP challenge. From there, it accepts the USB input, and attempts a complicated validation function against the OTP challenge. From the disassembly graph overview alone, it is apparent that the intended solution is angr:


However, upon closer inspection, we can determine there is a minor quirk which allows us to find a solution without resorting to angr – for each “block” of the validation function, a failed check will result in a call to exit, with the exit code being the number of the check that failed. Thankfully, qemu-mips will pass on this exit code to the user.

This means we can trivially brute force the correct answer for any OTP challenge. We simply need to tweak the binary to accept an OTP token from disk (instead of generating it from /dev/urandom):


also read 0x10 instead of 0x8

This allows us to “lock” the OTP challenge to a single user-specified value (whatever we read from the challenge server).

From there, we simply brute force each character in sequence until the exit code changes. When the exit code changes, we “lock” the correctly guessed character in place, and restart the cycle for the next exit code:


This quickly reveals the correct code, and the flag:


You can download the python script for this brute force here – note that it doesn’t always work (qemu can be a bit finicky), if it doesn’t work, generate a new OTP token and try again.

Tools Update – retdec.com / Retargetable Decompiler

During this CTF, I made use of the free decompiler service offered by retdec.com, provided courtesy of AVG. This decompiler will accept an upload of a binary file (including, surprisingly for the cost, non-x86/x64 files), and output a decompiled C file.

Note that free-but-registered users are limited to 10 minutes of maximum decompilation time, which can cause an issue with large files. To get around this, I advise disabling decompiler optimisations. The output looks just like as if someone had pressed F5 in IDA:


As always, I’d like to thank the organisers of the Insomni’hack 2017 Teaser CTF for putting together an enjoyable and challenging event. See you all in AlexCTF!

Posted in Bards, Computers, Jesting | Tagged , | Leave a comment

Late Writeups – cheer_msg, jmper (seccon)

Recently, I progressed through the “cheermsg” and “jmper” challenges from the SECCON CTF event last year. I was not able to solve these during the time allocated for the event. I will document my solves below.

Note that both challenges rely on libc – for ease of testing, I have done these with my CTF VM’s libc, instead of the provided ones.


This challenge was presented as a binary with libc, you can download this here.

Disassembling the challenge, we can determine the vulnerable function is a “write-what-where” in the “message”, stemming from an extremely oddly constructed pointer based on the message length first entered by the user:


By specifying a negative message length, we are able to write to arbitrary locations on the stack. Specify -152, and we’re able to write to the return address of the current function:


From here, this is a reasonably straightforward exercise in multi-stage ROP chains. Our ultimate goal is to make a call to system(“/bin/sh”). To do this, we construct multiple ROP chains which return to main:

  • ROP Chain 1: Infoleak GOT (to derive system in libc)
    • printf
    • main (return address)
    • 0x0804A010 (printf in the GOT)
  • ROP Chain 2: Seed /bin/sh into the data section
    • getnline
    • main (return address)
    • 0x0804A030 (data section)
    • 0x41414141 (length. doesn’t really matter)
  • ROP Chain 3: Call system
    • system (derived from initial infoleak in ROP chain 1)
    • main (return address – may as well be exit())
    • 0x0804A030 (data section)

A quick Python script later, and we have a shell:


Note the initial failure: this doesn’t always work cleanly, if an address in the GOT contains a zero (and terminates the infoleak too early), we simply exit and try again. It is possible to continue ROP chaining to leak more bytes of the GOT, but given the possibility of a GOT address containing a zero versus the possibility of it not, it’s faster to just try again.

You can download the Python script here.


This challenge was presented as a binary with libc, you can download this here.

This challenge is presented as an executable which allows operations on a number of “students”. Each “student” is represented in memory like this:

struct student{
  char memo[0x20]
  char *name;

The application allows the user to create students (which malloc’s the structure above as well as the ‘name’ and stores it in a big array), and view or edit the memo or name of any existing student record.

The vulnerability comes in the form of an off-by-one in the “write memo” function: this allows a user to write a single byte past the end of a memo or a name:


It’s possible to abuse this to create a limited read/write-what-where condition, by overflowing the “memo” field for student zero, one can write within a limited space surrounding student zero’s “name” field:



As illustrated above, we are able to exert limited control over the name pointer of a student object. With this limited level of control, we can read and write to an arbitrary location. We can relax this restriction, by creating a second student object, and overflowing student[0].memo to make student[0].name point to the address of student[1].name.

We don’t need to know where it is exactly, but if we know where it is relative to student[0].name, and that’s within a single-byte-overflow range, we’re in business – and this relative distance isn’t changing between execution’s so ASLR isn’t a problem.

We then set student[0].name (pointing to student[1].name’s address) to an arbitrary address (e.g. the GOT), and then read it via reading student[1].name (which is now set to the GOT).

This becomes an arbitrary read-write-where primitive. From here, we can use the setjmp/longjmp functionality to gain code execution:


We can abuse this functionality, as we know that setjmp “saves” the state of execution to a buffer, the address of which is stored locally: between the read-write primitive, the GOT and the setjmp buffer, we should be able to return execution to system pretty easily – unfortunately, it isn’t that simple. Viewing the buffer in gdb shows the following:


Oddly enough, what appears to be RIP and RSP in the jump buffer isn’t, it’s actually what’s stored in the red box. A bit of documentation surfing and traipsing through the disassembly of setjmp, and we can determine that the pointer is mangled through a rather simple function:


Using this, we can de-obfuscate the pointers cleanly and write our own new RIP and RSP. Simply setting RSP to system() won’t work – if RDI isn’t clear, system() on a 64-bit system will attempt to read the first argument out of RDI.

At this point, I looked to an existing writeup for guidance. Credit to Inndy@Github for this idea: https://github.com/Inndy/ctf-writeup/blob/master/2016-seccon/jmper/jmper.py.

From here, we can use a simple static pop rdi; ret ROP gadget to set RDI, as well as prepare the stack for a return to system(). Therefore, our order of operations is as follows, abusing the arbitrary write primitive above:

  • Leak a function from the GOT to locate system()
  • Leak RSP from jmpbuf
  • Write jmpbuf->RSP[0] = a pointer to /bin/sh (an unmodified student[1].name works nicely, see above – we’ll have the address of this anyway as we set up the read-write-anywhere primitive).
  • Write jmpbuf->RSP[1] = system()
  • Write jmpbuf->RIP = POP RDI, RET rop gadget

We then trigger longjmp by adding 29 more students. When longjmp gets triggered, RIP and RSP are set according to the values in jmpbuf, as follows:

  • RDI is now a pointer to /bin/sh
  • RIP is RET
  • RIP is system(), and we get shell:


You can download the Python script for the full exploit here.

Tools – Binary Ninja

During this time, I did the reverse engineering for jmper exclusively in Binary Ninja. This isn’t a tool I use often, and “feels different” for someone used to working in IDA. To me, it was clear that this was designed with a fresh pair of eyes, as opposed to IDA being layer upon layer of useful functionality (the “evolved” feel).

Two things of note, for reference:

  • The option to display opcodes and addresses is hidden in the bottom right, in the “Options” menu next to “ELF” and “Linear”:
  • There appears to be no function to show segment permissions in the tool itself, I had to rely on objdump –headers to see which sections were writeable in the executable.

Despite it’s relative youth, this appears to be a solid tool. I look forward to experimenting more with it’s capabilities.

As always, I’d like to thank the SECCON team for putting together a fantastic and challenging CTF last year. I was (fortunately!) able to save a great many challenges from this CTF for future reference, and look forward to solving them at my own pace, if you’d like to play along, come find me and I’d be happy to share what I have with you.

I’ll see you all in the Insomni’hack teaser CTF in a week’s time.

Posted in Bards, Computers, Jesting | Tagged , | Leave a comment

Writeup – SANS Holiday Hack Challenge (Part 4 of 4 – Conclusion)

In this post, we will continue the writeup of the SANS Holiday Hack Challenge, combining our retrieved audio files to reveal the final answers to this challenge.

Part 5


  • Who is the villain behind the nefarious plot. (Dr. Who)
  • Why had the villain abducted Santa? (“Do I look like I’m in my right mind? I’m a madman with a box”)

With the audio files we had retrieved from the previous challenges, it was clear they were intended to be in some manner of order:


I took a gamble and renamed the “debug-” mp3 file to “discombobulatedaudio4.mp3”, and then joined the files in order. As MP3 files are effectively raw data, I just used the “cat” program.

I then opened this joined file into Audacity. Playing the file, it seemed like this was slowed down audio. By using the “Effect / Change Tempo” function, I was able to speed up the file. At about 8 seconds total length, the message became distinct enough:

"Merry Christmas Santa Claus, or as I've always known him, Jeff"

I then spent a little while trying to “say” this to the Audio Discombobulator in-game, when I realized I needed to try this at the final locked door (in the corridor behind Santa’s office). This successfully opens the door, and leads us to the “Clock Tower” area, and the final villain:


This NPC also provides some entertaining (and surprisingly relevant) monologue, which I’ve screenshotted for posterity:

answer_part1 answer_part2


I’d like to thank the SANS team for the effort they have put into setting up this event. Quite clearly, a lot of care and thought went into this event, both in terms of usability, as well as ensuring the target systems remained mostly up for the (very extended) duration of the event – well done.

If I may offer some feedback:

  • Firstly, the ladder was way too long. I tried to work out some way to make travelling faster.
  • Secondly, the network access on the Train console was a nice easter egg. I tried to poke at the back-end ( server, and in doing so, was able to expand my toolkit of Perl trickery to include a nice one-line netcat substitute. Unfortunately, I was unable to get anything meaningful in the time provided.
  • Thirdly, I’m not sure it was intentional to leak the identity of the final villain and clues to the location of Santa in the web socket traffic sent by the game:I haven’t yet been able to construct something which allows me to directly speak with Santa from anywhere? I assume this is possible? I will experiment further J
Posted in Bards, Computers, Jesting | Tagged , | Leave a comment

Writeup – SANS Holiday Hack Challenge (Part 3 of 4 – Servers)

In this post, we will continue the writeup of the SANS Holiday Hack Challenge, specifically, how we identified the target servers and retrieved the Audio files from each.

Part 4


  • For each of those six items, which vulnerabilities did you discover and exploit?
    • Mobile Analytics Server (via credentialed login access): (none)
    • Dungeon Game: (use the “GDT” function, abuse “DT” to display the win string)
    • Debug Server: (set “verbose”:true in the JSON request)
    • Banner Ad Server: (abuse Meteor’s reliance on the client, HomeQuotes._collection.find().fetch()[4])
    • Uncaught Exception Handler Server: (PHP file inclusion in the “crashdump” parameter in the ReadCrashDump operation)
    • Mobile Analytics Server (post authentication): (forge an admin cookie, modify a saved query to extract data from ‘audio’ table).
  • What are the names of the audio files you discovered from each system above? There are a total of SEVEN audio files (one from the original APK in Question 4, plus one for each of the six items in the bullet list above.)
    • Mobile Analytics Server (via credentialed login access): discombobulatedaudio2.mp3
    • Dungeon Game: discombobulatedaudio3.mp3
    • Debug Server: debug-20161224235959-0.mp3
    • Banner Ad Server: discombobulatedaudio5.mp3
    • Uncaught Exception Handler Server: discombobulated-audio-6-XyzE3N9YqKNH.mp3
    • Mobile Analytics Server (post authentication): discombobulatedaudio7.mp3
    • APK: discombobulatedaudio1.mp3

This is an interesting (and lengthy) challenge. The first step of tackling this is to identify the six servers in question. Fortunately, they are all embedded neatly in the resources of the APK, and “apktool” can unpack these resources neatly.

A quick “grep” for “northpolewonderland” through the unpacked res/values folder quickly reveals the location of the servers we are looking for:


From here, we can begin to compromise each of the servers one by one. I will document how I was able to compromise each below.

Analytics (Credentialed Login Access):

This was a trivial “warmup” challenge. Upon accessing https://analytics.northpolewonderland.com, we are presented with a login interface. Authenticating with “guest/busyreindeer78” works, and we are presented with an option to download an MP3, revealing “discombobulatedaudio2.mp3”:



I went for this server next, as one of the NPC’s had disclosed a link to the “dungeon” binary. Upon disassembly of the binary (which nmap revealed to be running on port 11111 of the dungeon.northpolewonderland.com server), this appeared to be a standard text-based RPG, with several debug commands built in. The most interesting command was the “GDT” command, which appeared to unlock a developer mode:


Of note, the “DT” command appeared to allow us to display NPC dialogue and other strings from the game – it would ask us for an entry (an integer), and it would supply whatever string corresponded to that entry in the game’s data store. This quickly revealed an interesting piece of clearly non-standard text:


Emailing this address provides an automated response, with “discombobulatedaudio3.mp3” attached.


The debug server was a JSON endpoint. Initially, sending it “hello world” JSON messages (e.g. {“1″:”2”}) returned nothing, so I went through the Java source code of the APK to identify the parameters I needed to supply:


From here, we can see that the “date”, “udid”, “debug” and “freemem” parameters would usually be sent by the application to the debug server. A quick few minutes of Google later, and we have ourselves a valid request / reply:


On inspection of the response, we note that the “verbose” field is set to false. Setting this to true in the request produces a much more verbose response:


Fetching this file from the web server provides us “debug-20161224235959-0.mp3”.

Banner Ads:

The Banner Ad server revealed a fairly nondescript web interface:


A quick inspection of the source code revealed the use of the Meteor framework. This took me back to an earlier CTF which I had done during the year (I miss which one), where I learned about Meteor’s reliance on client-side controls for security. Josh Owens has an excellent writeup about this here.

Following a hint provided by one of the NPCs, I installed “Meteor Miner” into Chrome, and loaded the site. A little bit of browsing, and I quickly had a meaningful lead:


Using the Chrome developer console, I could then fetch this record and display the “audio” field:


Downloading this file from the web server gave us the “discombobulatedaudio5.mp3” file.

Unhandled Exception Server:

This server was, similar to the “debug” server, another JSON endpoint. Fortunately, this server provides useful feedback, telling you what fields you need to fill to make a valid JSON request. Very quickly, I was able to construct two requests – one to write a “crash dump”, and one to read out the “crash dump”:


Of this request, the most interesting field is “crashdump”. My first approach was to try to read out the “exception.php” file, by setting it to “../exception.php%00”: unfortunately, this produced an HTTP 500 error.

After a little experimentation, I discovered that this was indeed a file inclusion vulnerability, and the php:// filter was allowed. Could the php:// base64 encoding trick be used to encode the “exception.php” file, and read it out?

Indeed it could:


A quick base64 decode later, and we located a comment within the exception.php file, pointing us to “discombobulated-audio-6-XyzE3N9YqKNH.mp3” in the web root.

Mobile Analytics Server (post authentication):

For this challenge, I had a head start – based on the Reddit thread, I knew there had to be a git repository somewhere. I took a guess that the “.git” folder had been left intact on the web server – and I was correct.

Recursively downloading this folder, together with a bit of git checkout magic, I was quickly able to reconstruct the source code to the entire application:”


On reading some of these files, I had realized that only the “administrator” user could access the “/edit.php” functionality. I started by investigating the cookies – it appeared that they were an encoded, encrypted JSON object, containing the username, with the encryption key provided in crypto.php.

I then built a small PHP harness to generate my own cookie:


Substituting this value into the cookie’s “AUTH” field quickly allowed me to log in as an administrator. From here, I had access to the “edit” page:


Initially, I didn’t have an “ID” to use with this page, but then I recalled that I was able to create my own via the “Query” functionality’s option to save a query, as follows:


From here, I could “edit” this request:


Reviewing the source code some more, I found that it was checking for the GET parameters “id” (present), “name” (present), “description” (present) and “query” (not present. Upon further source code review, I realized that I could save arbitrary SQL queries here.

Reviewing the database schema, I was able to identify an “audio” table, which appeared to hold two entries. I could use the TO_BASE64 MySQL function to successfully exfiltrate the second MP3 file, discombobulatedaudio7.mp3:


With all seven MP3 files, we could now proceed to the final parts of the challenge, documented in the next post.

Posted in Bards, Computers, Jesting | Tagged , | Leave a comment

Writeup – SANS Holiday Hack Challenge (Part 2 of 4 – Terminals)

In this post, we will continue the writeup of the SANS Holiday Hack Challenge, specifically, how each “locked door” was opened.

ELF House 2

Password: santaslittlehelper

We will start our adventure in ELF House 2:


As per the hint, we are provided with access to the “/out.pcap” file, which is only readable by the user “itchy”. We start our adventure with inspecting the sudo -l command, to determine what we are able to run as other users:


From here, we can use the “tcpdump” command to copy the file to somewhere where our user can read it, via “tcpdump -r /out.pcap -w /tmp/lol.pcap”, but this turns out to be unnecessary. The “strings” command quickly reveals the first part of our password:


The second part was admittedly a little more tricky (in the red herring sense). Initial inspection of the pcap file (via tcpdump -X to create a hex dump) showed that this appeared to be a packet capture of a Dropbox Sync transaction.

My first instinct was to somehow exfiltrate the file and look for other tools which might recover the files in the binary, and from there, identify the binary. Worryingly, I couldn’t find an obvious executable header in the PCAP, and this would have been drastically out of line with the “point value” of the challenge.

On going through the Reddit thread about the challenge, I realized that I had been chasing a time-wasting end: a simple strings command with a different encoding would reveal the second part of the flag:


Using this password on the adjacent door reveals a hidden room with a hint NPC, but no sign of Santa:


Workshop – DFER / Reindeer Pen Door


We then proceed up the ladder of destiny, to arrive at Santa’s workshop. We begin with the uppermost terminal:


We are presented with a shell in which we have an executable, “wumpus”, in our home directory. My first approach was to exfiltrate the binary, but with no Internet access from this host, this would be a time-consuming prospect at best.

Following a hint from a fellow contestant, I used the objdump tool to identify interesting functions within the executable: given the objective of the game was to kill the Wumpus, the “kill_wump” function immediately stood out:


We can then use the “sed” command to simply replace the first occurrence of the offset of the “main” function (likely in the libc_start_main “loader function”) to make the game start with killing the wumpus (instead of playing the actual game):


Using this password on the adjacent door leads us into the “DFER”, or reindeer pen. Unfortunately, no sign of Santa. Back to the workshop we go…


Workshop – Santa’s Office

Password: open_sesame


This was a refreshingly simple challenge, that if I recall correctly, was one of the challenges in the Exploit Exercises Nebula ISO. A key file had been buried within a large number of directories, and we needed to find the file. A simple “find” was enough to identify the file:


The directory names have obviously been designed to be annoying to type out, so we can simply use backtick characters to pass a single file to “cat”, as follows:


Using this on the adjacent door leads us into Santa’s office, with another terminal. The plot thickens!

Workshop – Santa’s Office



A quick Google search for the phrase reveals it as a reference to the Wargames movie. Some more searching quickly reveals an emulator for the WOPR system that this challenge references.

Note that this isn’t exact: the response to “WOULDN’T YOU PREFER A GOOD GAME OF CHESS?” is “Later. Let’s play Global Thermonuclear War.”.

Playing through the game (i.e. supplying the expected responses, select USSR and target Las Vegas) reveals the flag:


Using this key on the adjacent bookshelf (!) reveals a secret passage, with a locked door at the end:



  • Password: N/A (or 24fb3e89ce2aa0ea422c3d511d40dd84, which unlocks the “BRAKEOFF” command)

Proceeding to the exit on the right of the workshop, we are greeted with a snow-covered train, and one final terminal. This presents us with a console “train control” application, as follows:


I first used the “HELP” command to determine what was happening. This brought us to the interface of the “less” program – from here, I could use “!sh” To escape to an actual shell:


On further inspection, the Train_Console program was a shell script, which would execute the ActivateTrain binary if the correct password (embedded in the shell script) were supplied). Running the “ActivateTrain” command displayed a console graphical interface, then proceeded to change the setting of the game to a 1978 version of… wherever this was:


Half an hour of exploration (and climbing the ladder of destiny) and we find Santa in the DFER / Reindeer Pen:


From here, we can proceed to Question 4. Given the length and complexity of Question 4, we will continue this in another post.

Posted in Bards, Computers, Jesting | Tagged , | Leave a comment