Writeup – Pupper (PlaidCTF)

This past weekend, I briefly participated in PlaidCTF. Unfortunately, with other life priorities interfering, I was not able to play the entire weekend, but I was able to solve one challenge in the time available. The writeup is presented below.


This challenge was presented as a package containing source code and a Linux binary, which you can download here.

This was a taint-tracking variant of ML (Meta Language). I had never programmed in ML before, but the syntax appeared relatively simple to work out via the examples. Running the “failing” examples shows the nature of the challenge – we need to reveal a “private” value:

Fortunately, we can leak a single bit of data via an if statement:

From here, it is a simple matter of brute forcing the flag, bit-by-bit. Fortunately, the source code of the challenge lets us know the length of the flag (36 chars):

You can find the Python script used here. The “%d” placeholder. in “fuck.dog” is the value of the variable y.

As always, thankyou to the PlaidCTF organisers for putting together a well-structured and varied CTF. With any luck, see you all in the DEF CON CTF Qualifier, and in FAUST CTF.

Posted in Bards, Computers, Jesting | Leave a comment

Writeups – Babyc, Plastic (ASISCTF 2018 Quals)

Over the past two days, I had the pleasure of briefly playing in the ASIS 2018 CTF Quals with the folks from Monsec. During this time, I solved the “babyc” and “plastic” challenges, both of which I present here for future reference. The “babyc” writeup will be more detailed than usual, outlining methods which did not work.


This challenge was presented as a Linux executable, which you can download here. The challenge text indicated that we only needed the first 14 characters of the input, which gives you a “good” output (that is, ASIS{sha1(input[:14])}). Running the executable lets you enter some user input, after which “Wrong” was printed. Running strings gives us one interesting string (“m0vfu3c4t0r!”) but this isn’t the flag input.

On disassembly, we immediately note that it is movfuscated:

My first attempt involved running strace and ltrace against the executable, to identify at a high level what it actually did. We note that it does a strcmp – a little trial and error shows that the strcmp is against input[3:], and the maximum input is 32 bytes long.

Still, filling this with the magic “m0vfu3c4t0r!” string doesn’t work either, so we’re still missing something.

My first attempt was brute forcing the first 3 characters. I used a simple Python script, shown below:

At this point, I decided to attempt two side channel attacks – firstly, against the return code (from a previous challenge), and then, against the instruction count. Firstly, the return code, as it’s a simpler brute force – I solved a CTF challenge once a long time ago, as it would modify it’s return code for each character of the flag you got right (so you could brute force character by character.

Unfortunately, I wasn’t able to make this produce anything meaningful. My next attempt was to instruction count: that is, using the “perf” program running on a bare-metal box, I could count the number of instructions executed for each given input. Again, a character-by-character brute force attack was attempted:

This produced quite interesting results:

Even on the same box, two different iterations of the script produce different “maximum instruction count paths” for input, indicating that the executable performs the same amount of instructions no matter how many input characters are provided, or how many are correct.

I then resorted to manual analysis, grepping for immediate arguments. Searching on a whim for ‘A’, we get a hit:

A little while later, we can see the same code pattern, repeating with ‘h’:

Scrolling further through the code, we can see a few more characters, totalling “Ah_0y1ng:(“. I wasn’t too sure what to do at this point, and didn’t want to manually spend the time reverse engineering movfuscated logic. I went with my instinct, SHA1’ing “Ah_m0vfu3c4t0r” for the flag and an easy ~100 points.


This challenge was presented as a PNG image, presented below in it’s entirety:

Binwalk showed nothing, and quick pixel analysis showed nothing. I attempted to play around with things like alpha channels, but nothing turned up. Opening the image in a hex editor reveals our first clue:

We can immediately see base64 encoded content. Not knowing what this was, I went to Google “RDF”, which didn’t turn up anything too relevant to this specific challenge. I then went to unbase64 this, providing a blob of binary data: I couldn’t see anything, but binwalk said there was zlib data from offset 4. Zlib.decompress’ing this provides the flag:

Thankyou to the ASIS 2018 CTF Quals creators for putting together this CTF – this was a good set of challenges, and I am learning much from other people’s writeups.

Posted in Bards, Computers, Jesting | 2 Comments

Writeups – Diary, Isoar (Midnight Sun CTF Quals)

This weekend, I attended the BSides Australia 2018 conference. This was another iteration on an already excellent con, with numbers expanding year on year. It is always good to have the opportunity to meet up with people I haven’t seen in a long time: I probably had more productive meetings on the second day of the con than one entire week at my day job.

On Sunday, I participated in the Midnight Sun CTF Quals. This was a well-structured CTF, with a good variety of challenges leaning towards the difficult end. Unfortunately, I was only able to solve a few challenges: here are the writeups for them:


The Diary challenge was presented as an archive, containing a Git repository, which you can download here.

In this archive, there is “diary.txt” and “wishlist.txt”. Opening up “diary.txt” reveals the following:

Unfortunately, the Git repository seems to be corrupted:

A little bit of Google reveals a way around this: we run “git fsck”, revealing an interesting dangling commit:

We can directly check out the dangling commit despite the git log being broken, and then git checkout to the entry pointing to April 11th, revealing the flag:


The Isoar challenge was presented as a web application, allowing users to check the strength of their password against a list of 1001 passwords, one of which is the administrator’s password.

When a password is submitted, the page returns one “fact” about the password, and a score:

The goal was to obtain the administrator’s password. Inspecting the page source, we can see some interesting files:

The “app.js” file shows us how to check for a user’s password and how to log in, while “pwmeter.js” is an obfuscated JavaScript file which shows us how to generate a proof of work for these actions (based off a randomly salted SHA hash of the password you want to test).

A little bit of further exploration reveals 1000 of the passwords, in the file “/public.password.list”.

From here, we have enough to execute the attack: we simply generate “test” requests for a given character, say “a”, until it tells us how many passwords (from the list of 1001) are suffixed with “a”: we then check this against the list of known passwords. We repeat this for each character, until one of the results does not match our own generated results – we instantly know that this is the suffix of the administrator’s password.

Two hours of brute forcing later, and we know the administrator’s password ends with “rHolyP4ssw0rd”. Some guesswork later, and we get the flag by submitting a login request with “H3rHolyP4ssw0rd”:

You can find the Python scripts I used for this solution here and here.

Thankyou to the organisers of this CTF – I enjoyed this experience. That said, I grow weary of competing by myself once more – it is my intention to restart farmingsimulator2015 (in one form or another). More thoughts on this later – the clock ticks on for WPICTF, and my projects won’t complete themselves.

See you in WPICTF.

Posted in Bards, Computers, Jesting | Leave a comment

Writeups – Hastad, Triptych (UIUCTF)

This weekend, I participated in the UIU CTF. This was a challenging but well-crafted CTF with a good range of challenges: disappointingly, I was only able to solve two challenges in the time allocated. Without further ado, writeups.


This challenge was presented as two text files, with a note which mentions that “e=3”. This is a dead give-away that this is some twist on Hastad’s broadcast attack, where you can recover a plaintext if the same message is sent with 3 or more keys, and ‘e’ is small.

I had a look for public implementations of this attack, and many existed – but all of them needed a number of ciphertexts and a number of public key moduli – we had 3 moduli, but a large number of ciphertexts.

A few moments of brute force, courtesy if Python’s excellent itertools, and we have our solution.


This challenge was presented as an ELF executable, which you can download here.

Opening this up in IDA pro, we are greeted with our first sign of the type of trolling to be inflicted in this challenge:

Right, self-modifying code it is. If we follow the code down a bit further, we can see the self-decrypting code in the_first:

Following this a bit further, we can see the mangled original code in the_second:

This looks like it’d be a hassle to decrypt manually, but it doesn’t take any input from the user or the environment – so it’s a safe bet to simply let the program run, breakpoint at this instruction, and decrypt, breaking at 0x400ACD (the call to the_second, instead of the_second: if gdb implements breakpoints by placing 0xCC in the broken function, a decryption loop will erase the breakpoint).

This yields our decrypted version:

We can see that this is likely a repeat of the first function. We can use IDA’s “Load Additional Binary” feature to patch the application and create a new disassembly of the_second:

This repeats an additional time, until we call validate at 0x4006A6. At this time, I thought it would be a good idea to dump a patched executable and solve it with angr: I attempted to patch the call at 0x400B40 (in main) to directly call a decrypted validate at 0x4006A6, and use “Apply patches to input file” (Edit -> Patch Program) to write a new executable which directly called validate with no funny business, but I discovered that the decrypted functions, loaded via “Load Additional Binary”, didn’t count as patches, and therefore, weren’t written to disk.

At this point, I reviewed the validate function in IDA. At a high level, it looked like a three-layer character substitution cipher, something like the following:

The simple solve for this is to create a lookup table. We can do this by breakpointing the character compare function at 0x4007CE: we pass in a string of “a-z”, and we see what it comes out with. We should be able to determine what ciphertext corresponds to each character, and using this, derive the original key the validate function is checking for.

You can find the solution here.

As always, thankyou to the UIU CTF organisers for putting together this event. While it’s disappointing that I was only able to solve so few challenges, it is only through being humbled that we continue to grow.

For those of you attending BSides, see you all at BSides next week. For everyone else, see you in WPI CTF.

Posted in Bards, Computers, Jesting | 5 Comments

Writeups – So_Stealthy, Rescue Shell (Nuit Du Hack Quals)

Yesterday, I participated in the Nuit Du Hack Quals. In hindsight, I should’ve played this all day – this was a good CTF quality-wise, with a good variety of challenges and infrastructure which seemed to remain online.

I will present two writeups below, for posterity.


This challenge was presented as a PCAP file, which you can download here. The objective was to reverse engineer some malware included in the pcap. At a glance in wireshark, most data is HTTP or HTTPS traffic: so we start by extracting all the HTTP/HTTPS objects:

I don’t have an consistent way to attempt these “needle-in-a-haystack” style problems (is there one?), so I went with a manual approach, running “strings” across each of the extracted objects.

Eventually, I identified an odd-looking favicon(1).ico, comprised of obfuscated JS:

I quickly extracted the base64, which turned out to be a binary file, containing a .NET executable at a non-zero offset. We then extract the file and pop it into ILSpy to determine what it does:

It looks like this is a reasonably simple XOR cipher, but I couldn’t find the key initialization anywhere. Going back to the JS, we find our culprit:

We can then match this up with our disassembly, to note that the “Aa6b…” function takes the last 22 characters of it’s argument as the xor key:

Knowing this, a quick python script gives us the flag:

Rescue Shell

This challenge was presented as a Linux binary, which you can download here. This was ostensibly a shell in itself, but was disabled (and infact, did not import any shell-executing functions).

Popping this into IDA pro, I quickly got the sense that this was a classic stack overflow vulnerability, conveniently using read (so null bytes were safe).

A quick test later, and this is confirmed, with the return address from check_passphrase being controlled:

Controlling the stack to this extent makes the rest of the challenge trivial: we then wrangle a rop chain to leak the address of one of the elements in the GOT (using 0x40099a as a “leak” gadget, taking an argument from the stack) and then from there, bounce to a libc magic gadget to give us shell:

You can download the python script I used here.

As always, thanks to the NDH organisers for putting together another quality CTF event. There’s quite a number of CTF events next weeked to participate in, so I’ll likely see you all in UIUCTF next weekend.

Posted in Bards, Computers, Jesting | 7 Comments