Ruxcon 2017 HHV Badge Flag – Part 1 – The “Easy” Way

As promised, here’s a walkthrough for retrieving the Badge Flag from the Ruxcon 2017 HHV Badge.

The easy way requires that you have the badge hardware up and running (though you could just load the firmware onto some random ESP8266 module for the same effect).

If we connect to the UART port on the badge we see the following at startup;

Boot messages

In this data we see;
flag: cbd3f82962b3b38679fba0250f243c4c7dc5b8aa5ff403383f43de6e9dd2e23a32de120d62776077e2196c36ae0a330d

SWEEET! that was easy!

Err, no… Typically for a CTF flag it’s something like a GUID or it’s something like flag{<GUID>} or just flag{<16 random hex bytes>}, which doesn’t really gel with the above, furthermore, if you boot a different badge you’ll see a different value here, so apparently we need to apply some intelligence.

If we have a look closer at the data we’ll see that there are 96 characters there, since it’s evidently hex, that corresponds to 48 bytes. Looking at the values, there are bytes there above 7F so it can’t be a direct ASCII encoding or any ASCII-based encoding.

Considering that flag{<GUID>} is 42 characters and flag{<16 random bytes>} is 38 characters, and our ciphertext is 48 bytes that indicates that it’s likely using some flavour of block-wise encryption (in this case 16 bytes or 128 bits) because if it was using a stream type encryption or most other (non ASCII based) encoding schemes the output would be the same size as the input.

In case you didn’t notice from the startup messages above, the firmware on the badge is based on NodeMCU (and the crypto module is included). NodeMCU is basically an embedded Lua engine for ESP8266, the documentation can be found at;

Looking at the documentation for the crypto module we find that the NodeMCU crypto module supports AES-CBC-128 and AES-ECB-128 algorithms for encrypt/decrypt, both of which are blockwise and both of which are 128 bit in the NodeMCU implementation.

So we have a couple of candidate algorithms, but we still need a key.

Since they’re 128 bit algorithms we’re looking for a 16 byte string. As I told everyone who asked over the course of the conference, the key is out in the open. So the question is where… Let’s go back to that screen grab from earlier;

Boot messages

Do we see any 16 character, or otherwise 16 byte strings here? Moreover, they need to be a *UNIQUE* 16 character/byte string, because the “flag” field is different on every badge… That rules out the commit ID because that’s the same for every badge (assuming you’re using the NodeMCU build that ships with the firmware) and it’s too long in any case. Let’s see, can’t be the SSID, that’s only 15 characters, wait what’s this?

Badge Boot Messages Anotated

It’s a 16 character string… And it’s being used as a crypto key (FWIW clue on the CTF listing for this one was “Reusing crypto keys is bad mmm’kay” or something like that), so that might just be it…

Conveniently enough we can use the badge to perform the decryption. First things first though, we need to convert our “flag” to a string for processing by crypto.decrypt(), a quick google will get you the following function;

function fromhex(str)
  return (str:gsub('..', function (cc)
    return string.char(tonumber(cc, 16))

Let’s try AES-ECB first because otherwise we need to figure out what was used as an IV for AES-CBC;

Well that’s interesting, looks like we’re on the right track, but we’re not quite there yet. We can still get some useful info here though, we know the flag begins with, flag{6E65B2F051D, so it’s definitely in the form “flag{<something>}” but we can go even further than that. GUIDs are of the form XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX, we have the first 11 chars here, and there’s no hyphen so it must be in the form flag{<16 random hex bytes>} which tells us that the length of the whole flag is 38 bytes long. This will become important later.

So we get a partial decryption with AES-ECB, this suggests that the code is using AES-CBC here, which means we need an IV.

The IV for any algo using one is the same as the block size (in this case 16 bytes), and in order to enable them to decrypt the data one needs to communicate the IV to the other party. Typically this is done by either prepending or appending the value to the ciphertext, so in this case we’d be looking at two blocks being cipher text and one being IV…

Hang on, but know our flag’s 38 bytes, how the hell do we fit that into 32 bytes…

From what we’ve seen previously, there’s clearly no clever encoding going on here, 38 bytes doesn’t fit in the 2 blocks we have “available”. Either we’re not being told the IV, or the IV is all zeros. Now, not telling you the IV would be a bit of a dick move, because without the IV you can’t decrypt the whole flag, so one can only assume that if it’s not an impossible challenge, the IV is all zeros.

This is easy enough to test, referring back to the doco, it specifies that if an IV is not provided it will use all zeros so, let’s try that;

Ta Da! We appear to have a flag.

It’ll take a while longer for me to do the write up of the “hard” way, because it involves a lot of bytecode and some understanding of the guts of Lua but we’ll get there eventually.

Morgan / 2017-10-28 / Uncategorized / 0 Comments

Ruxcon 2017 Hardware Hacking Village Wrap

Only eight hours sleep across the weekend (gotta love insomnia…) but we’re done for another year.

I was pretty happy with the level of engagement we saw at the Hardware Hacking Village this year, catering to a group like that is always a bit tough.

You can find my slide deck, the badge and simple solder build docs and badge firmware at my Ruxcon 2017 HHV page.

We handed out 111 of the “Simple Solder” kits across the course of the weekend, so we were pretty much spot on with the 120 that we ordered for (Gotta say, really wasn’t expecting to go through that many of those kits, last year IIRC we only ran out of the 50 we’d bought in by about 11 on the Sunday.)

The badge was the real surprise, last year we only went through about 10 of the kits on Saturday and we ended up handing them out to anybody after we ran out of Simple Solder kits on Sunday. This year we blew through 30 badge kits in the first 3 hours the village was open, going to have to figure out how to get 50+ into the budget for next year.

A note for those people who spoke to me and asked if the designs were going to be put up online. I have good news and bad news, the bad news is; the gerbers will not be being put up online. The art on the badge this year was commissioned on the understanding that it would be used for a limited run, as such we can’t publish them. However, if you’re quick there is some good news; I do have several spare boards (I actually had them with me at the village but my brain was too fried on Sunday to think of offering them to you.) because at the last minute I panelised them two up which meant we could get 40 for what it would’ve cost us for 20. I’m happy to send one out to anyone in AU gratis, if you’re international and you really want one I can send one out but it may have to be at your cost. Hit me up via email ( if you’re after one.

The only real downer from the weekend was that two of the Bus Pirates that Ruxcon had generously provided for Dr Noise’s workshop walked out with delegates.

Thanks to everyone who attended, without you the conference wouldn’t happen. And a special thanks to Chris Spencer without whose insanely tireless work we wouldn’t have a con 😉

Over the coming weeks I’ll put up some posts around the badge flag and maybe some bits and pieces about the IoT CTF stuff, stay tuned.

Morgan / 2017-10-23 / Uncategorized / 0 Comments