Category: Misc Challenge
Just unzip the archive … several times …
Challenge Description
Unzipping the contents of this challenge we have two files. Firstly, flag_999.zip and secondly pwd.png. flag_999.zip requires a password to unzip it and pwd.png looks like this:

Straight away I clock this as being Morse code. I load up a Morse code key and do a quick translation, finding this image to represent 9. Entering 9 as the password to flag_999.zip works like a charm and it spits out a folder called flag. Inside the flag folder is flag_998.zip and another pwd.png. I think I see where this is going… The second pwd.png looks like this:

The colours are slightly different but the premise is the same. The numbering of the zip files and the challenge description reading “Just unzip the archive … several times …” means that some automation is going to be required.
imageToMorse()
The first task is going to be writing a python script that can take an image and then scan it for morse code and then translate that code into English. Fortunately Python has a useful and aptly named library known as Python Imaging Library (PIL) that will make this relatively simple.
def imageToMorse():
img = Image.open(path + 'pwd.png', mode='r')
pixels = img.load()
width, height = img.size
borderColour = pixels[0, 0]
With the image loaded, each pixel can be examined via (x, y) coordinates. Examining pixels individually returns a tuple of that pixel’s colour containing the values of red, green and blue. As the pixel at the top left of the image will always be the reference colour for non-Morse code, a borderColour can be defined using the pixel at [0, 0]. Now when looping through our image, anything that is not the same colour as our borderColour can be assumed to be part of the Morse code.
The rules for checking the Morse code are quite simple. If the pixel is not equal to borderColour and neither are it’s neighbours then it’s a ‘–‘. If the pixel is not equal to borderColour but both of it’s neighbours are, it’s a ‘.‘ Just build up a string of dashes and dots as you go and at the end of each line add it to a list. Once that’s done it’s just a case of running through that list and translating everything to English. I grabbed a dictionary online for this bit.
ENGLISH_MORSE_DICT = { 'A':'.-', 'B':'-...',
'C':'-.-.', 'D':'-..', 'E':'.',
'F':'..-.', 'G':'--.', 'H':'....',
'I':'..', 'J':'.---', 'K':'-.-',
'L':'.-..', 'M':'--', 'N':'-.',
'O':'---', 'P':'.--.', 'Q':'--.-',
'R':'.-.', 'S':'...', 'T':'-',
'U':'..-', 'V':'...-', 'W':'.--',
'X':'-..-', 'Y':'-.--', 'Z':'--..',
'1':'.----', '2':'..---', '3':'...--',
'4':'....-', '5':'.....', '6':'-....',
'7':'--...', '8':'---..', '9':'----.',
'0':'-----', ', ':'--..--', '.':'.-.-.-',
'?':'..--..', '/':'-..-.', '-':'-....-',
'(':'-.--.', ')':'-.--.-'}
Recursive unzipping
So at this point we have some python that loops through each pixel of the pwd.png and gives us a password string. Nice. Next we need our script to take that password and unzip the next archive so that it can grab the next image and get the next password and unzip the next archive and …
I built up my unzip command as the following:
cmd = 'unzip -oP ' + currentPass.lower() + ' ' + path + 'flag_' + str(flagNumber) + '.zip'
os.system(cmd)
unzip -o
allows for the extraction to override files without prompting the user whilst unzip -P
allows us to specify a password. It converts the password to lowercase as a few hundred layers in the zip files begin rejecting uppercase passwords. Fortunately this challenge can be completed using only lowercase characters and numbers. As each unzip produces a new flag folder, traversing through hundreds of directories can be quite annoying and so I added the following to drag everything back into the root of the working directory with each loop:
cmd = 'mv flag/* .'
os.system(cmd)
And finally all is needed is to glue the pieces together and have the main function call itself to recursively decode and unzip everything.
def decodeAndUnzip():
global flagNumber
global path
imageToMorse()
cmd = 'unzip -oP ' + currentPass.lower() + ' ' + path + 'flag_' + str(flagNumber) + '.zip'
os.system(cmd)
print(flagNumber)
print(currentPass)
print(cmd)
flagNumber -= 1
os.system('mv flag/* .')
decodeAndUnzip()
def start():
cmd = 'unzip -oP ' + 'hackthebox' + ' ' + path + 'M0rsarchive.zip'
os.system(cmd)
run()
Finally the script can be ran and watching 999 passwords get decoded and 999 archives unzipped was really satisfying to watch whizz past on the terminal. Once it had finished there was a nice little flag.txt waiting for me and the challenge was completed!
After finishing the challenge I did look through some of the images that appear in the later layers and I saw that they change colour a lot, some of them even look like a single block of colour to the human eye which I saw on the HackTheBox forums tripped a few people up, much like the change to lowercase passwords a few hundred recursions deep.
Super fun challenge, I enjoyed this one a lot. This was a welcome opportunity to brush up on my Python skills and take a foray into image processing which is new to me. I’d definitely be up for trying some similar challenges in the future, decoding a password from an image in this way was really interesting. Well that pretty much zips up this blog post…
- .... .- -. -.- ... / ..-. --- .-. / .-. . .- -.. .. -. --. / -- -.-- / .-- .-. .. - . ..- .--. / ..-. --- .-. / .... .- -.-. -.- - .... . -... --- -..- # ... / -- ----- .-. ... .- .-. -.-. .... .. ...- . / -.-. .... .- .-.. .-.. . -. --. . .-.-.- / .-.. . .- ...- . / .- / -.-. --- -- -- . -. - / .. ..-. / -.-- --- ..- / .-- .- -. - / - --- / ... .... .- .-. . / -.-- --- ..- .-. / . -..- .--. . .-. .. . -. -.-. . ... / --- ..-. / - .... .. ... / -.-. .... .- .-.. .-.. . -. --. . / --- .-. / .. ..-. / -.-- --- ..- / .... .- ...- . / .- -. -.-- / .- .-.. - . .-. -. .- - .. ...- . / ... --- .-.. ..- - .. --- -. ... / --- .-. / - .... --- ..- --. .... - ... .-.-.- / .... .- .--. .--. -.-- / .... .- -.-. -.- .. -. --. -.-.-- / -....- -.- -.-- .-.. .. .
Leave a Reply