This post outlines the solution to NorthSec 2020’s Essay challenge, it presents the side-channel that I used to retrieve the flag without actually reversing the code
You are given a rather large text file called
essay.txt which looks like the beginning of a Shakespeare play. A bit of googling around reveals that it’s actually some esoteric language that some genius (or mad?) students procrastinating their assignments came up with.
Nice, now I have to learn this for virtual points in a virtual competition? challenge accepted.
The thing to understand about Shakespeare is that it’s old. Like 2004 old. And because of its verbose nature, it understandingly does not have as large a cult following as say, Golang or Rust.
Another member of my team had attempted the challenge before me, and it turns out that the challenge designer had also (purposefully?) made typographical mistakes and syntax errors that caused the existing tools to crash. Thankfully, my teammate had figured those out and sent me the C-translated source code along with a pre-compiled version.
The translating compiler he used was Kyle Cartmell’s Marlowe which has actual decent error reporting, unlike all the other projects that we tried.
Initially I was going to instrument the entire code base to try and understand what was going on, but while doing that and reading through
libspl.c from the transpiler, I noticed that a lot of debugging code already existed and was simply gated behind an
#ifdef DEBUG check. I enabled that and ran the program again, dumping
stderr to a log file, which resulted in a massive quantity of log.
-DDEBUG and then compiling
essay.c into an executable (mind you, this required a lot of fiddling in the visual studio projects, too), I was able to get the following output (snippet) leading up to the password prompt:
and this keeps going… for roughly 300KB of text.
From parsing those logs and sending pre-determined inputs of data, I was able to identify the meaning of each “variable”. The important ones being:
- Juliet The user input
- Romeo The expected password
I also determined that at some point Romeo’s stack would need to be popped to perform character comparison. I used a very advanced technique known as
Ctrl+F to look for stack pops from Romeo, but only found one hit. A theory began to brew inside of my brain. I decided to try to submit
FLAG- as my input, and promptly found 6 hits.
By changing the number of “valid” password characters, I noticed that the number of pop operations on Romeo would change accordingly. What this means is that the crackme is most likely breaking out of its password validation loop early when it encounters a character that doesn’t match the expected password.
Taking this one step further, what this means is that it’s possible to count the number of pops on Romeo to determine if we have found the right password letter at a given position.
Time to turn this into a script!
I hacked together this script quickly to bruteforce the password. It has a bug for the last character as there will not be an extra comparison once all flag characters are found, but thankfully the flag turned out to be a sentence which made it easy to guess the last character.
Running this script is fairly slow as it requires to launch a new instance of the essay.exe binary, input all known values of the password and then receive the debug output, counting the number of occurences of
Once it has successfuly run, though, we are left with the flag: