Breaking down the CodeMash Capture the Flag

Last year at Codemash they had the first Capture the Flag (CTF) and it was very successful. They decided to bring it back for 2018 and the format was changed a bit. The official site has all of the rules and information, but the basics of it were that a single puzzle was released at midnight in the 2 weeks leading up to the conference. This allowed people to solve them at a more leisurely pace and not have to cram them in during the confernece. Also the puzzles this year are a bit easier (but still challenging), which makes them more accessible to the entire audience of codemash.

Now that the CTF is over and the winner has been crowned, I thought I would share my solutions, so others can learn and share how they solved the problems.

I created a GitHub repo for any of the custom code I wrote for the CTF.

  1. Do you like my Style?
  2. Hobo Robo
  3. 1337 Riddler
  4. Super Eyesight
  5. Bools for Fools
  6. Withcraft
  7. Happy Eyes
  8. Lock
  9. Meow
  10. Chest
  11. Bacon
  12. On-site Challenge
  13. Alice
  14. Security Regulations
  15. P.A.L.M. Login

Codemash CTF - 15 - P.A.L.M. Login

Hint

15 - P.A.L.M. Login ™
Folks at HOBO Authentication Systems implemented a new authentication system named P.A.L.M. Login

Prove that you can break it and find a pair of username and passcode to log on.

Login

Approach

The login page contains a button and two inputs. When you put in text and hit the login button you get the text of nope.

Looking at the javascript for the button click takes us to a function that does the following:

function checkEntries() {
    var u = document.getElementById('puser').value;
    var p = document.getElementById('ppass').value;
    var used = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
    var ok = false;
    if (u === 'cavs') {
        if (p > 0 && p.length == 10) {
            ok = true;
            for (i = 1; i <= 10; i++) {
                var digit = p.charAt(i - 1);
                var part = p.substring(0, i);
                if (used[digit] != 0 || part % i != 0) {
                    ok = false
                }
                if (used[digit] == 0) {
                    used[digit] = 1
                }
            }
        }
    }
    if (ok) {
        document.location.href = 'palm_' + u + '_' + p + '.html'
    } else {
        alert('nope')
    }
}

Looking at the code, the username needs to be cavs and the password is a 10 digit number.

I started writing a brute force algorithm and trying to figure out the number that way, but I decided to see what I could find about the properties of the number.

It is a 10 digit number, where every digit is only used once and the first N digits must be divisible by N.

Plugging those requirements into google yield lots of results.

Our number is 3816547290. Put that in the form and it takes you a page named

palm_cavs_3816547290.html

With the text of:

Congrats!
cm18-zbIc-O4Zh-gmxl-r5J6

Return to the full breakdown of the Codemash CTF

Codemash CTF - 14 - Security Regulations

Hint

14 - Security Regulations
Due to some new privacy regulations this flag had to be shred. The classification will be secret or topsecret depending on the content.

____-____-____-____-____

Left over shred inside the paper shredder

Approach

Following the link gives you shred text:

Shred 1: 
Note: the other shreds are classified as «topsecret»!

cm18

Since the URL has a number in it, maybe we could change the 1 to a 2. Doing that results in shred text of:

Shred 2: 
Note: the contents on this shred were sanitized!

XXXX-XXXX

The URL also contains the word secret and there was mention in the clue of secret and topsecret, so if we change the URL to topsecret_challenge_shred2.html, we get the following text:

Shred 2

bWh0-VIkC

Uupdate the URL for #3 and we get the text:

Shred 3

cMf4-72jY

Combine them together for the flag of

cm18-bWh0-VIkC-cMf4-72jY

Return to the full breakdown of the Codemash CTF

Codemash CTF - 13 - Alice

Hint

13 - Alice
Follow the white rabbit.

With a hint image of:

white rabbit

Approach

Looking at the image, it is really big for a jpg. Also looking at the file in a text editor, you see mentions of other files:

Looking more deeply at the file, there appears to be a zip file after all of the bytes in the JPG. I extracted the bytes for the zip file using BE.HexEditor and copied them to a new file.

After extracting the zip you are given three files.

Opening each of those files in a text editor finds that there is exif data giving you hints:

In forest:

This image has a protected secret.

In meadow:

This meadow is all dried out. Check the water first.

In water:

steghide was here. With an empty passwor

I used an online steghide tool to extract the data.

Water yields the result:

You search the whole place but you can't find anything.


...


Now get out before you get flushed down.

Not much helpful in there, but Meadow yields the result:

So you think a mole can speak?!


...


Lucky you, this one can!

He's name is Fred and he tells you the passphrase:

The-Mad-Hatter

Forest appears to be password protected, so we take the password from meadow and apply it.

This yields the flag

Congratulations here is the flag!

cm18-xZl2-eHC5-axW3-ZkZG

Return to the full breakdown of the Codemash CTF

Codemash CTF - 12 - On-site Challenge

Hint

12 - On-site Challenge
The flag for this challenge can only be found onsite at the conference, in the location seen on top of the backside of the elephant, in this picture.

When you arrive at CodeMash, find the code. Only attendees of CodeMash are eligible to win this competition, so don't share the code with anyone!

Approach

I have to admit, I spent more time on this one than I should have. I looked all around the elephant. If you look more closely at the picture, there is a reflection. Turning around I saw the flag (albeit with some clues from others):

Return to the full breakdown of the Codemash CTF

Codemash CTF - 11 - Bacon!

Hint

11 - Bacon!
Get the bacon!

1000.zip

Approach

This is a zip file that contains a git repository. Which contains a zip file, which contains a git repository, and so on and so forth. Looking at the git repository, it looks like there is a deleted file, so if we reset the repository, the file is restored.

Since there is a pattern to the names, it should be pretty easy to script.

Param([int]$startId)

Add-Type -assembly "system.io.compression.filesystem"
$currId = $startId;

do 
{
    $next = ($currId-1).ToString().PadLeft(4,"0")  
    $currStr = $currId.ToString().PadLeft(4,"0")
    [io.compression.zipfile]::ExtractToDirectory("D:\temp\cmgit\$currStr\$next.zip", "D:\temp\cmgit")
    cd "D:\temp\cmgit\$next"
    git reset --hard
    $currId = $currId -1;
    
} While( $currId -gt 0)

Then I can invoke the script using

.\1000.ps1 1000

This worked for the first 100 entries and then the format changed. For number 901, it skipped 900 and went to 0899.zip. I renamed folder 0901 to 0900 and continued on.

.\1000.ps1 900

This worked until 0613 where the zip file simply contained an image named trunk.jpg:

After a bit of playing and seeing that there were multiple commits on the branch, I reset to 2 commits back (git checkout HEAD~2) and the zip file followed our pattern again.

.\1000.ps1 0613

This worked until 278 which had an image named scooter.jpg and a zip file:

Checking the branches, there is a new branch called blaster:

λ  git branch -l
  blaster
* master

Switch to that branch and continue on: .\1000.ps1 278

That worked until 0044, which wasn’t a valid git repository. I went back to the 0045 directory and tried to extract the zip file and was prompted for a passowrd. The original file name offered a hint on where to look:

Doing a git log on the 0045 folder yields: commit b364135b78a640c2889dc1fc44e5e1c3326b8cd2 (HEAD -> master) Author: Gorilla [email protected] Date: Thu Dec 7 09:42:54 2017 -0500

Commit committed. Pass is fluffy99

Reset the git repo again and continue on.

.\1000.ps1 0044

This leads us to folder 0001, which has a flag image inside it:

Return to the full breakdown of the Codemash CTF

Codemash CTF - 10 - Chest

Hint

10 - Chest
Can you find the flag inside of the chest?


chest Approach —

Looking at the chest, it appears to be an ELF executable. However, opening the executalbe in a text editoring, I was able to get the entire string table and just copy and paste that out. I replaced the spaces with newlines and opened in excel. Sorting the file made it really easy to search.

Looking at the flags, there are plenty of red herrings in there, but they are pretty obvious. They have pirate themed text in them:

cm18-mQmX-bUoC-rust-ykey // rusty key
cm18-lYmV-bUoC-vXpa-rrot // parrot
cm18-bFaL-bUgo-lden-coin // golden coin
cm18-cHbG-bUfa-ncyb-oots // fancy boots
cm18-dIiI-bUsi-lver-coin // silver coin
cm18-eOdP-bUoC-orna-ment // ornament
cm18-fLkP-bUoC-vXXb-ones // bones
cm18-gMhS-bUoC-seas-hell // sea shell
cm18-hPnR-bUoC-vXje-wels // jewels
cm18-iPnV-fanc-yban-dana // fancy bandana
cm18-jWqS-bUon-ylon-flag // nylon flag
cm18-kOlV-bbot-tleo-frum // bottle of rum
cm18-Ml2l-bUoC-vXXE-Fc8c //??? This is our flag

Return to the full breakdown of the Codemash CTF

Codemash CTF - 9 - Meow

Hint

09 - Meow!
Can you lure the cat out of the hiding place?


meow.pdf

Approach

Opening the PDF in a hex editor and searching for the string image you see that there appears to be multiple images in the PDF.

There are plenty of online tools to extract the images from the PDF: http://www.pdfaid.com/ExtractImages.aspx

One of the images from the PDF is our flag.

Return to the full breakdown of the Codemash CTF

Codemash CTF - 8 - Happy Eyes

Hint

08 - Lock
The key for that lock got lost.

If you are good at lock picking you will find the flag.

Lock.class

Approach

A .class file is a java compiled file, so I simply uploaded the file to an online decompiler and got the following code:

package com.hackinglab.ctf;
import java.io.PrintStream;

public class Lock { public Lock() {} private static String key = "lockpickingisfun";
  private static String cipher = "?8hiyKT5fw*W^J~art3t.47i";
  
  public static void main(String[] args) {
    if (args.length != 1) {
      System.out.println("Provide codeword to open the lock!");
      System.exit(-1);
    }
    String input = args[0];
    StringBuffer codeword = new StringBuffer();
    for (int i = 0; i < cipher.length(); i++) {
      codeword.append((char)(key.charAt(i % key.length()) - cipher.charAt(i) + 54));
    }
    if (codeword.toString().equals(input)) {
      System.out.println("Correct codeword! The Lock is open!");
    } else {
      System.out.println("Wrong codeword!");
    }
  }
}

I took the guts of the code and re-worked it into a small C# app to give me the correct output.

private static String key = "lockpickingisfun";
private static String cipher = "?8hiyKT5fw*W^J~art3t.47i";

public static void Main(String[] args)
{
    String input = key; ;
    StringBuilder codeword = new StringBuilder();
    for (int i = 0; i < cipher.Length; i++)
    {
        codeword.Append((char)(key[(i % key.Length)] - cipher[i] + 54));
    }
    Console.WriteLine(codeword.ToString());
    Console.ReadLine();
}

Return to the full breakdown of the Codemash CTF

Codemash CTF - 7 - Happy Eyes

Hint

07 - Happy Eyes
Barbara really loves to chat with all friends.

To express joy they use the characters ^^ which represent eyes of a smiling face.

Can you find this happy flag?

Hint: Offset by 2

1xT-Gcm8FV-5cYN-iBc-syHW

Approach

This one is tricky. The offset 2 indicates that there is a tool out there that takes an input. Looking at the text, it contains c, m, 1, and 8, so it may just be a scramble of the text. After playing with a lot of tools online, I found a super-tool that has all sorts of cipher varieties:

After that, another hint came along from the @codemashctf twitter account:

The hint was subtle, but the On the fence portion just didn’t fit. A quick search of the ciphers that contain fence, and you find the Rail Fence cipher. I found a tool that included the offset option.

Setting the offset to 2 results in:

cm18-FxVs-T5yc-YHNG-WicB

Return to the full breakdown of the Codemash CTF

Codemash CTF - 6 - Witchcraft

Hint

06 - Witchcraft
I was just messing around with my magic wand trying out some new spells and all of a sudden the flag was gone.

All I was left with is the following:

    363336643331333832643438363537373432326436383530
    333137323264346337393738333932643635373035343465

Can you undo my spell and get the flag?

Approach

The first thing that jumped out to me on this one is the number of 3s in the text. Obviously this is some sort of encoded string. Taking the first few bytes 36 33 as hex numbers and convert them to a string 63. 63 is the ascii code for c and since I knew all of the flags started with cm, I definitely had a lead.

I wrote a small script to process through the entire string:

static void Main(string[] args)
{
    var input = "363336643331333832643438363537373432326436383530333137323264346337393738333932643635373035343465";
    Console.WriteLine(HexToString(input));
    Console.WriteLine(HexToString(HexToString(input)));
    Console.ReadLine();
}

static string HexToString(string source)
{
    StringBuilder sb = new StringBuilder();
    for(int i=0; i<source.Length; i+=2)
    {
            sb.Append(Convert.ToChar(int.Parse( source.Substring(i, 2), System.Globalization.NumberStyles.HexNumber)));
    }           return sb.ToString();
}

This yields the output:

636d31382d486577422d685031722d4c7978392d6570544e
cm18-HewB-hP1r-Lyx9-epTN

Return to the full breakdown of the Codemash CTF

Codemash CTF - 5 - Bools for Fools

Hint

05 - Bools for fools
Calculate this!

((not(a) and b) or c) xor d

boolsforfools_fixed.zip

Approach

The hint is pretty obvious that you need to do some boolean operations on the attached files. To start, I load the text and get rid of all of the whitespace, so I am just dealing with the 1s and 0s. I then wrote functions for each of the operatoins (not, and, or, and xor)

Here is the not implementation as an example. See the full source on GitHub

public static string Not(string input)
{
    var result = new StringBuilder();
    foreach (var s in input)
    {
        Validate(s);
        if (s == '1')
        {
            result.Append("0");
        }
        else if (s == '0')
        {
            result.Append("1");
        }
        else
        {
            throw new Exception();
        }
    }

    return result.ToString();
}

Once I had all of that wired up, I ended up with the result of:

1111111000100110001111111
1000001011100011001000001
1011101010000010101011101
1011101001001010001011101
1011101011101100101011101
1000001010101101001000001
1111111010101010101111111
0000000010110011100000000
1101001100011100001110110
0111110011011000111101001
0000101010011100110101001
0011010111111101110111010
1101011000110101111101010
0100100101010100111001011
1001001010010110100010101
0100010011010110000101001
1111111100101101111110101
0000000010001010100010101
1111111011111111101011111
1000001001001010100010110
1011101001001110111110010
1011101010110101000110000
1011101000101111000011001
1000001011011100010100000
1111111010100001100000111

I tried various encodings and translations on this data, until we got a hint from CodeMashCTF:

Now it is obvious that this represents a QR code. I wrote a little code to write data to an image:

public static string Format(string input)
{
    var bmp = new System.Drawing.Bitmap(25, 25);
    var g = System.Drawing.Graphics.FromImage(bmp);
    var whitepen = new Pen(Brushes.White);
    var blackpen = new Pen(Brushes.Black);
    var row = 0;
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < input.Length; i++)
    {
        if (i % 25 == 0 && i != 0)
        {
            row++;
            sb.Append("\r\n");
        }
        sb.Append(input[i] == '1' ? "1" : "0");
        var pen = input[i] == '1' ? blackpen : whitepen;
        g.DrawRectangle(pen, i % 25, row, 1, 1);
    }
    bmp.Save("D:\\temp\\cm\\qr.bmp");
    g.Dispose();
    bmp.Dispose();
    return sb.ToString();
}

The output image looks like this:

Return to the full breakdown of the Codemash CTF

Codemash CTF - 4 - Super Eyesight

Hint

Can you see what others cannot?

Here is an image to prove your super eyesight.

image.jpg

Approach

I took the image and started playing with various settings in paint.net. After playing for a bit, I adjusted the levels and found that the flag was hidden below the squirrel (that’s a sentence I never thought I would write).

Return to the full breakdown of the Codemash CTF

Codemash CTF - 3 - The Riddler

Hint

03 - 1337 Riddler
1337 r1ddler h4s a puzzl3 f0r u 2 solve!

H3 1s l1st3n1ng 0n th3 <i>BEST</i> p0r7 on this s3rv3r!

Approach

The clue in this puzzle to get your started is that you need to connect to an open port on the server.

Using telnet, I connected to the server on port 8357 (BEST in l33t 5p34k):

telnet> o codemash.hacking-lab.com 8357
Trying 80.74.140.117...
Connected to codemash.hacking-lab.com.
Escape character is '^]'.
Make an educated guess, dude:
1
I need 20 digits, dude!
Connection closed by foreign host.

20 digits??!? This is going to take a while to do by hand. Let’s put in 20 digits and see what happens:

Make an educated guess, dude:
11111111111111111111
0<

As I was working this out, the @codemashctf account sent out a hint.

So, I tried a 7 followed by all 1s:

Make an educated guess, dude:
71111111111111111111
1<

And then a 9 followed by all 1s:

Make an educated guess, dude:
91111111111111111111
0>

Based on the few things I have tried, it appears that the number is the number of characters that are correct and the < and > indicate if the next number is larger or smaller than the number you input.

We could manually walk through the logic and eventually solve this, but, it could also be scripted. Here is a quick C# console app I put together to do this:

static void Main(string[] args)
{
    int knownCount = 1;
    string known = "7";
    while (true)
    {
        bool found = false;
        foreach (var guess in GetGuesses(known))
        {
            TcpClient client = new TcpClient("codemash.hacking-lab.com", 8357);
            var s = client.GetStream();

            ReadHeader(s);
            Console.Write(guess + " - ");

            s.Write(Encoding.ASCII.GetBytes(guess + "\r\n"), 0, 22);
            byte[] result = new byte[3];
            while (true)
            {
                var cnt = s.Read(result, 0, 3);
                Console.WriteLine(Encoding.ASCII.GetString(result).Trim());
                string number = Encoding.ASCII.GetString(result).Trim().TrimEnd(new[] {'>','<'});
                
                if (int.Parse(number) > knownCount)
                {
                    known += guess[knownCount];
                    knownCount++;
                    found = true;
                }
                if (cnt <= 0) break;
            }
            if (found) break;
        }
    }
}

static string[] GetGuesses(string known)
{
    var result = new List<string>();
    for (int i=0; i<10; i++)
    {
        var x = known + i.ToString();
        x=x.PadRight(20, '5');
        result.Add(x);
    }
    return result.ToArray();
}

static void ReadHeader(Stream s)
{
    byte[] result = new byte[1];
    while (s.Read(result, 0, 1) >0)                
        if (result[0] == Encoding.ASCII.GetBytes("\n")[0])  break;
}

Running this code eventually gives us the value 78025928232920712967. Popping that into a telnet session gives you:

Make an educated guess, dude:
78025928232920712967

Congrats! Here's your flag:
cm18-Glz3-yM2k-h9i9-wntS

Return to the full breakdown of the Codemash CTF

Codemash CTF - 2 - Hobo Robo

Hint

Hobo Robo prepared a paper chase for you.

Start

Approach

The link takes you to the C3P0 wikipedia page (or so it seems). Upon further inspection, you notice that the link actually takes you to https://codemash.hacking-lab.com/codemash/bots/bots.html, which immediately redirects you to the C3P0 wikipedia page.

I decied to curl the web page (to prevent the redirect) and saw the following:

<html>
<head>
        <title>Bots</title>
        <script type="text/javascript">
        eval(String.fromCharCode(105, 102, 32, 40, 33, 40, 110, 97, 118, 105, 103, 97, 116, 111, 114, 46, 117, 115, 101, 114, 65, 103, 101, 110, 116, 32, 61, 61, 61, 32, 39, 72, 111, 98, 111, 82, 111, 98, 111, 39, 41, 41, 32, 123, 32, 108, 111, 99, 97, 116, 105, 111, 110, 46, 114, 101, 112, 108, 97, 99, 101, 40, 39, 104, 116, 116, 112, 58, 47, 47, 101, 110, 46, 119, 105, 107, 105, 112, 101, 100, 105, 97, 46, 111, 114, 103, 47, 119, 105, 107, 105, 47, 67, 45, 51, 80, 79, 39, 41, 59, 125))
    </script>
</head>
<body style="background: white; border: 20px solid white;">
    <div style="widht: 100%; height: 100%; background: url('./robotbg.jpg') no-repeat center center fixed; -webkit-background-size: contain; -moz-background-size: contain; -o-background-size: contain; background-size: contain;">&#160;</div>
</body>
</html>

The obfuscated javascript is what handles the redirection, so that is not important, but the image that on the page is interesting.

A quick google search for some of the words in the image lead you to Robot Interaction Language. Using that page to translate the image leads to the text:

You must make word of addition two and two - This be name of page.

This takes us to https://codemash.hacking-lab.com/codemash/bots/four.html

Curling this page results in

<html>
<head>
        <title>Bots</title>
        <meta name="description" content="Robots talk in ROILA language: eman egap eht esrever tsum">
    <meta name="keywords" content="secret, page, robots, fun, hacky easter, blrt, five, beep">
        <script type="text/javascript">
        eval(String.fromCharCode(105, 102, 32, 40, 33, 40, 110, 97, 118, 105, 103, 97, 116, 111, 114, 46, 117, 115, 101, 114, 65, 103, 101, 110, 116, 32, 61, 61, 61, 32, 39, 72, 111, 98, 111, 82, 111, 98, 111, 39, 41, 41, 32, 123, 32, 108, 111, 99, 97, 116, 105, 111, 110, 46, 114, 101, 112, 108, 97, 99, 101, 40, 39, 104, 116, 116, 112, 58, 47, 47, 101, 110, 46, 119, 105, 107, 105, 112, 101, 100, 105, 97, 46, 111, 114, 103, 47, 119, 105, 107, 105, 47, 67, 45, 51, 80, 79, 39, 41, 59, 125))
    </script>
</head>
<body style="background: white; border: 20px solid white;">
    <div style="widht: 100%; height: 100%; background: url('./robotbg2.jpg') no-repeat center center fixed; -webkit-background-size: contain; -moz-background-size: contain; -o-background-size: contain; background-size: contain;">&#160;</div>
</body>
</html>

The image on this page is

The image didn’t provie any clues this time, but looking at the meta tag on that page content="Robots talk in ROILA language: eman egap eht esrever tsum. Looking at the text it says must reverse the page name.

Going to https://codemash.hacking-lab.com/codemash/bots/ruof.html results in the following image, which is our flag:

Return to the full breakdown of the Codemash CTF

Codemash CTF - 1 - Do you like my Style?

Hint

01 - Do you like my Style?
Every one is talking about styles. Sometimes its about what you wear and sometimes its about what you do.

All I know is that the flag you want definitely has Style.

It also included the following image:

Approach

This CTF is a very obvious hint that wants us to look in the stylesheet for the site to find the flag. I opened up the developer tools in my web browser and browsed through the style.css file. At the bottom, I found the flag.

solution-image

Return to the full breakdown of the Codemash CTF

View Archive (89 posts)