Recently, at the inaugural BSides Edinburgh, Ben Turner and I made the trek up to Edinburgh to see our colleague Neil Lines present his talk “The Hunt for The Red DA”. I can’t say that I am a massive fan of such early starts (we jumped on the first flight out of Birmingham), but thankfully the organisers made the trip absolutely worth it. The talks that I saw were well presented and had good technical content while the venue was absolutely amazing. I even learnt some stuff about the world of IoT that I wished I didn’t know; cheers Ken.
The conference was very well supported by the sponsors, particularly with the solid training on offer. We even recognised the faces of some of the competition from the CTF at DerbyCon. We’re really looking forward to doing battle again later in the year…

The crypto contest

SecureWorks kindly created a challenge for the BSides Edinburgh 2017 audience; they named it the Crypto Contest. Personally, I think one of the core skills as a good penetration tester is being able to quickly deal with data that are you are unfamiliar with and to have a good set of tools that can parse & process in a flexible way. The contest was a good way to practice some of those skills and demonstrate to my colleagues why pure C# in the world’s best programming tool – LINQPad is better than Powershell 😉 Plus, there were some very cool prizes on hand; our eyes quickly zoned in on the Hak5 Bash Bunny.

Challenge number 1 – Square

Navigating to https://www.secureworks.com/~/media/Files/US/Blogs/bsides%20edi%2017/square.ashx, we got the following wall of text

Now credit for this goes to Ben; after trying some advanced military grade cryptographic techniques such as ROT13, he craned his neck and quickly spotted that this was in fact just rotated text. Yep, I was massively over thinking it too! All we had to do was quickly put together some code that would rotate the text 90 degrees around the origin. Firing up LINQPad, the following solution was created (which of course has been tidied up and comments added).

//Create webclient for download
//https://msdn.microsoft.com/en-us/library/system.net.webclient(v=vs.110).aspx
var wc = new System.Net.WebClient();
//Set User-Agent get 403 if not there
wc.Headers.Add(System.Net.HttpRequestHeader.UserAgent,
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36");
//Download the the challenge, split the text into lines and then convert each line into an arracy of chars
var lstChars =
wc.DownloadString("https://www.secureworks.com/~/media/Files/US/Blogs/bsides%20edi%2017/square.ashx")
.Split(new char[]{'\r','\n'},StringSplitOptions.RemoveEmptyEntries)
.Select(x => x.ToCharArray().ToList()).ToList();
//Not all rows are equal, work out the max
Int32 maxY = lstChars.Select(x => x.Count).Max(), maxX = lstChars.Count;
//create the result object use a List of char arrays
//https://msdn.microsoft.com/en-us/library/6sh2ey19(v=vs.110).aspx
var res = new List<char[]>();
//Calculate the maximun length
var max = Math.Max(maxX, maxY);
//Prepopulate the result arrays
Enumerable.Range(0, max).ToList().ForEach(x =>res.Add(new char[max]));
var yctr = maxY - 1;
/* We want to rotate the text clockwise so that essentially
*  x                     +-------x
*  |                     |
*  |         becomes =>  |
*  |                     |
*  +-------y             y
*/
//Loop through each line in the challenge text
lstChars.ForEach(row =>
{
    //Reset the xctr
    var xctr = 0;
    //Not all rows are equal in length so Pad it out if neessary and then loop through
    row.AddRange(Enumerable.Range(0,max - row.Count).Select( p => ' ').ToList());
    //Loop through each character in the row
    row.ForEach(character =>
    {
        //Move the text to its new home
        res[xctr++][yctr] = character;
    });
    //decrement yctr
    yctr--;
});
//Create a new stringbuilder, awesome for building strings
var str = new StringBuilder();
//Each row is returned as a Array of chars, convert it to strings here
res.Select( x => new String(x).Dump()).ToList().ForEach( y => str.Append(y));
str.ToString().Trim().Dump();

The following out is produced and the flag is ours:

Sure, we could have put the monitor on its side, but where’s the fun in that?

Challenge 2 – Royale

Opening the page https://www.secureworks.com/~/media/Files/US/Blogs/bsides%20edi%2017/royale.ashx?la=en, you got the following, which was immediately recognisable as Morse code. The instructions stated you need to “Please decode the following message, adding appropriate spacing as needed so the flag is readable.”
Funnily enough, I had never worked with Morse code before, but the first thing I noticed was that thankfully Secureworks had put in spaces between prosigns, which made the code a little easier. The first step was to obtain a Morse code library, one that would translate the symbols to letters. This was pretty easy to find with Google and allowed me to build up a CSV file which looked something like this:

Once again, using LINQPad, the following code split up all the symbols, translate each one and then coverted it all into a string.

//Create a dictionary to store the prosigns and the alphabet
var dict = new Dictionary<String, String>();
File.ReadAllLines(@"C:\Users\pentest\Documents\BSides\morse-code.csv").ToList().ForEach(x =>
{
    //Split the csv row
    var alph = x.Split(',');
    //if it's alpha key is not there then store it
    if (!dict.ContainsKey(alph[1]))
        dict.Add(alph[1], alph[0]);
});
//Create a stringbuilder to contain the result
var str = new StringBuilder();
//Read the challenge text, split on spaces and then enumerate through each of the prosigns
File.ReadAllText(@"C:\Users\pentest\Documents\BSides\challenge2.txt").Split(' ').ToList().ForEach(x =>
{
    //If the alphabet dictionary contains the prosign append the corrseponding character
    //to the stringbuilder otherwise append a space
    if (dict.ContainsKey(x))
        str.Append(dict[x]);
    else
        str.Append(" ");
});
//Dump out the created string
str.ToString().Dump();

This gave us the following result, which is written in the NATO phonetic alphabet.

So, a slight tweak to the code, changing the last line to:

var sb2 = new StringBuilder();
str.ToString().Split(' ').ToList().ForEach(x =>
{
    sb2.Append(x[0]);
});
sb2.ToString().Dump();

…and the next flag was ours:

Challenge 3 – Royale.txt

For challenge 3, https://www.secureworks.com/~/media/Files/US/Blogs/bsides%20edi%2017/dreams.ashx?la=en, we received the instructions “Decipher the message from this transmission” and then the following:

The first calculation was the size; the 5 lines contained 1200 bits (150 bytes). Assuming bytes was our first mistake; this had us trying to convert to different text forms and every kind of data type that we could think of, without any luck. Being bits, we then tried creating images types, e.g. bitmap and even QR codes (which in fairness didn’t really align to the size). The path then led to 6 bit characters because, well, 1200 divides by that very nicely. In honesty, we should have looked more into that first, but we didn’t as there was a talk we wanted to see (honest :)).
So, we were back inside the vendor area when the following tweet arrived.

Feel it out… hang on… Braille uses 6 bit characters, right? Bingo! Straight to https://en.wikipedia.org/wiki/Six-bit_character_code#Example_of_six-bit_Braille_codes to look at the Braille glyphs:

The 2×3 column structure lined up very nicely with the text in the transmission. Cool, so time to bash some code out. By this stage, you can probably guess what tool was opened up 🙂
The first step was to once again create a dictionary file that would translate the glyphs to ASCII. For this, we borrowed the text from the wiki page and built a csv file translating the positions into a letter. It looked like this:

Next was to write some code that translated those positions into characters. We bashed out the following quickly (it’s not perfect but did the job):

var dict = new Dictionary<Int32, char>();
File.ReadAllLines(@"C:\Users\pentest\Documents\BSides\braille.csv").ToList().ForEach(x =>
{
    var splt = x.Split('§');
    Int32 res =0;
    splt[0].Split('-').ToList().ForEach(y =>
    {
        res = res | (1 << 0x6 - (Int32.Parse(y)));
    });
    dict.Add(res, splt[1][0]);
});
//Need to add a special case for the space
dict.Add(0, ' ' );
var lines = File.ReadAllLines(@"C:\Users\pentest\Documents\BSides\challenge3.txt");
Int16 ictr = 0, xctr = 0;
var sb = new StringBuilder();
Enumerable.Range(0, 5).ToList().ForEach(x =>
{
    var lines3 = lines.Skip(ictr++ * 3).Take(3);
    Int32 res =0;
    for (var i = 0; i < (lines.First().Length -1) ; i+=2)
    {
        var row1 = lines3.ToList()[0];
        res = res | (((row1[i+0] == '1') ? 1 : 0) << 5 );
        res = res | (((row1[i+1] == '1') ? 1 : 0) << 2 );
        var row2 = lines3.ToList()[1];
        res = res | (((row2[i+0] == '1') ? 1 : 0) << 4 );
        res = res | (((row2[i+1] == '1') ? 1 : 0) << 1 );
        var row3 = lines3.ToList()[2];
        res = res | (((row3[i+0] == '1') ? 1 : 0) << 3 );
        res = res | (((row3[i+1] == '1') ? 1 : 0) << 0 );
        sb.Append(dict[res]);
        res = 0;
    }
});
sb.ToString().Dump();

We get the following output; there were a couple of manual corrections that we needed to make to get the flag, but it looked like the Bash Bunny might be ours.

Yeah, it was!

Conclusion

While not a Crypto contest in the strictest sense of the word, it was still a lot of fun and we got some practice with data formats that we don’t normally come across. As I said at the start, this is an important skill. A big thank you to SecureWorks for putting the time in to create this contest – we really enjoyed it and we hope you all enjoyed our write up!
– Rob, Ben & Neil