Based off the descriptions, these four challenges looked like fun little incrementally more difficult crypto challenges.
Since this was a cloud CTF and I was doing my utmost to avoid any cloud content, I thought that was an excellent option and downloaded the first (or 0th, I suppose) one to take a peek.
Azure’s Goblins 0 Intro Card
The intro card for this (and subsequent) Azure’s Goblins challenges seems to contain hints about the type of keys and encryption you’re supposed to crack, which would have come in handy had I any intention whatsoever of actually doing that.
The downloaded zip file contains the dockerfile and dependencies for each of the Azure’s Goblins challenges, and so I opened up the first one and took a look.
Screenshot of Directory
Note: try.py
is my script, not a part of the challenge.
Clearly, you’re meant to build and run each dockerfile and then interact with the service to crack something and do something to get the flag (or something).
However, I didn’t have docker installed and didn’t particularly want to go through the process of doing so, so I went to look at __init__.py
Screenshot of __init__.py
Normally I’d include the text rather than a screenshot, but there’s always a chance the CTF folks don’t want that posted, so a screenshot of my terminal you get.
You’ll notice that, while ugly, this looks very familiar to anyone with any incident response or SOC experience. That’s because it’s obfuscated in the same way a lot of malicious payload is: By base64-encoding, reversing, and compressing about a jillion times, with an added eval() and uncompress/unreverse/unbase64 at each level.
I’m well-familiar with that special brand of annoyance, so I wrote an ugly script that took that base64 string, decoded it, and then pulled the base64 string out of that decoded string (using hard-coded boundaries, of course), and repeated that until it failed gracefully detected there was no longer any base64 to decode, at which point you can reasonably assume you’ve reached the code, or some fresh hell of obfuscation.
try.py
import zlib
import base64
def do_thing(one):
print("ONE\n", one)
print("ONE STRIPPED\n", one[11:-3][::-1])
two = zlib.decompress(base64.b64decode(one[11:-3][::-1]));
print("TWO\n", two)
do_thing(two)
print()
thing= b'==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'
one =zlib.decompress(base64.b64decode(thing[::-1]));
do_thing(one)
You’ll notice that I am consistent between filenames, variable names, and function names, in that I use only the least-descriptive possible names. In my defence, the name of the game in a CTF is speed, and I promise I document better professionally or when I’m not racing.
Anyways, you pop the initial base64 in that one variable and run the script, and Bob’s your uncle. Here’s (some of) the output from that script:
Screenshot of Output
If you squint, you’ll see that the command finishes after gracefully detecting that it has reached non-base64 content, and in the second-last printed variable (not including the mess of errors), you’ll see the source code, and the flag stored in a variable as
FLAGGob1insAndKMSIsn0tRe4l21e68b
Wrap that up into the flag format and there you have it.
Note: I think this is actually the flag for the 4th (or 3rd, depending on where you start counting) challenge in this set, because I didn’t bother re-entering the base64 from the 0th (1st) – You’ll see why in a sec
Now I moved on to the next three goblin challenges. Lo and behold, they all wanted me to do something silly like run a docker container. Thankfully, the exact same script worked for each (after replacing the base64), and I was spared from having to install docker for another day. This also got us a ton of points for very little effort, though one of the organizers assured me the next day that this was a foreseen and legitimate way of solving the challenge. Pah!
Here’s a quick capture of the intro cards for each, and the output of my script: