Well, I came home yesterday quite late, so I only had time to “play” for about ~4 hours. Meanwhile, my team solved some other challenges, but I solved the Asia 400 challenge.

In this challenge you got a zipped file called “images.rar”. Inside were lots of .gifs, either black or white. It was immediately obvious that this was a QR code, since there were 626 pictures [25*25 QR Version 2 code, ??+1 seeming random image??].

Stitching them together wasn’t hard, I just used the standard PIL library to handle straightforward image manipulation.

The only real “tricky” part here was figuring out the name-convention used to name the gifs. They were named like this

  • 11.gif

  • 12.gif

  • 2512.gif

  • 111.gif

  • 11(1).gif

{see for yourself in the .rar  - LINKHERE}

At first I tried sorting them alphabetically, but no cigar. I also tried using a natural sorting script for python (sorting them the same way explorer.exe does, e.g. Team 1  [Team 101 Team 12 Team 21] -> [Team 1 Team 12 Team 21 Team 101] instead of the alphabetically [Team 1 Team 101 Team 12 Team 21]http://www.codinghorror.com/blog/2007/12/sorting-for-humans-natural-sort-order.html), but nothing seemed to work.

After some thinking I figured out that they just concanted the “x” and “y” coordinates of each “pixel” in the QR code without any concantetor - e.g. x=2, y=12 would become 212. Obviously this would introduce collisions at x=5, y=12 and x=21, y=2, so they solved this by putting the “y” into brackets if a collision arose. This explained the strange numbering scheme. Instead of wasting hours on regex and complicated scripts to parse the existing names, I just went for a script that “recreated” this numbering scheme in the right order from scratch, which worked out pretty well - “if you can’t bring mohammed to the mountain bring the mountain to mohammed” and all that…

Any, without further ado, here is the final script used to generate the QR codes - http://pastebin.com/J8MFZTUW or:

import Image, os, math

#Start by scanning the directory and getting results

fakelist = []
for x in range(1, 26):
    for y in range(1, 26):
        if((20<x<25 and 0<y<10) or (10<x<13 and 0<y<10)): #Since the existing file names seem to regard the entire series 20-25 as collisions, we'll do that to :|
            fakelist.append(str(x) + "(" + str(y) + ")" + ".gif")
        elif((str(x) + str(y) + ".gif") in fakelist):
            print "we fd up!!!!"
            os.exit()
        else:
            fakelist.append(str(x) + str(y) + ".gif")
print fakelist

finalimage = Image.new('RGB', (300, 300))

for imageno, imagename in enumerate(fakelist):
    print str(imageno) + " and name: " + imagename + "\n"
    tempimage = Image.open('images/' + imagename)
    pixel = tempimage.crop((0, 0, 12, 12))
    row = int((math.floor(imageno/25)))
    column = int(((imageno) % 25))
    print str(row) + ":" + str(column)
    finalimage.paste(pixel, (column*12, row*12, (column+1)*12, (row+1)*12))
    del tempimage

finalimage.save("output.jpg")

See you at defcon CTF! :D