Hack The Vote write-up
I wanted to practice my computer security and reverse engineering skills for quite some time, so I was happy to see that Hack The Vote CTF event was about to take place soon. The contemporary US presidental election theme sounded like fun, which was proven to be true. I participated under the nick pwny so that I wouldn’t be publicly ashamed if something went wrong, but 121st place out of 1000 (or 500 if you count only those who completed at least one challenge) doesn’t sound that bad. I really enjoyed the competition and I’m looking forward to participate in similar events.
Let’s skip the Sanity check. Yes, you could’ve got two points subtracted.
- Sanders Fan Club (Web)
- Consul (Reversing)
- Warp Speed (Forensics)
- TOPKEK (Crypto)
- Trump Trump (Crypto)
- Vermatrix Supreme (Crypto)
Sanders Fan Club
It seemed pretty easy. I started off by looking at the incomming traffic.
Some weird things are going on. Why is the
flag2.jpg being sent as a stylesheet? A quick examination of the file reveals this.
So the comment is probably a hint. I was messing with the image in many different ways (
diffing with Wikimedia source etc.) which lead me nowhere. I only realized the second day that I should do something with the
Accept HTTP header since the image-sent-as-a-stylesheet event was caused by this header as well.
Bingo. (I’m glad I’m using Firefox by default.)
Nothing interesting at the first glance. Let’s have a look at the assembly. I was using
radare2 for the first time so it took me a while to get this view.
There are some functions, hidden unused right above the main one. We can run them from
gdb by setting a breakpoint and jumping to the desired address, but only the
real_help() function worked “out of the box”, the other ones were segfaulting.
When I jumped to address
0x400aeb right before subroutine calls in the other functions, I could get different outputs.
My observation was that it just adds number stored in
ESI register to ASCII codes of all chars in the string. So now the only task was to find the flag itself. It was hidden at address
0x601280 and it could’ve been decoded by increasing the chars by 64.
We can see some text, but it’s pretty hard to read. Let’s have a look inside.
Hmmm, another hidden message. Okay, let’s try to make it a square. The original image has a size of 1000×250 px, so the square image should be 500 px wide and high. I resized it by changing the corresponding bytes when I finally found usable JPEG documentation. Here’s the result, rotated for easier reading.
Do we even know, who is this 4 CHAN???
Pretty funny quote to remember. Anyway, the input file looked like this:
KEK! TOP!! KEK!! TOP!! KEK!! TOP!! KEK! TOP!! KEK!!! TOP!! KEK!!!! TOP! KEK! TOP!! KEK!! TOP!!! KEK! TOP!!!! KEK! TOP!! KEK! TOP! KEK!
…and so on. The
KEK are evenly alternating, but the number of exclamation marks changes. I assumed that it’s some representation of binary, by trial and error I found that the exclamation marks in even words were zeroes and those in odd words were ones. All we have to do now is to convert this binary to string.
Can we get a signature from you Mr. Trump?
Since we are in the crypto category, this pun refers to cryptographic signature, which can be created with possession of a private key. We have only the public key, but we can communicate with someone who can help us (yes, I’m looking at you Mr. T). Of course he never signs pictures of himself.
The server accepts numbers and it’s using plain RSA without padding (something you should never do) which can be tested by sending number 1 to sign. We can make use of some math under the RSA principles. Here’s how we would usually get signature of a message (picture) :
If we can’t get this message signed directly, let’s pick a constant , such as that , multiply the message by it and send both and to the unsuspecting recipient. Then the signature of our message can be recovered like this:
How do you like your signature Mr. T?
I recognized the
ff d8 JPEG header thanks to the Warp Speed challenge.
We’re given a random seed and matrix. We also have a source code of what’s happening on the server. The matrix is generated such as:
where are the initialisation vector (IV) digits and seed characters – seed is always padded so that is a multiple of 9. If we can guess the IV, server gives us the flag. Since XOR is reversible, we can extract the IV by running this procedure backwards. Here’s the script that takes care of everything.