Another writeup for a challenge imitating game asset reverse engineering as a part of OverTheWire’s Advent Bonanza 2019. Day 14 of the Advent Bonanza challenges was given as follows:
tiny runes Points: 137 Solves: 106 One of Santa’s Little Helpers received an unusual Christmas wish, a copy of the yet to be released Deus Hex game. All they managed to find were fragments from the dialogue system. Can you decode the last one? Download: d4037209017d4730edc598fe62e6b17f5573ee259b6ad7c8723bac962cf0b328-tiny-runes.tar.gz
Downloading and extracting the file gave the following file structure:
1 2 3 4 5 6 7 8 9 10 11
$ tar -xvzf d4037209017d4730edc598fe62e6b17f5573ee259b6ad7c8723bac962cf0b328-tiny-runes.tar.gz x lines1.bin x lines1.png x lines1.txt x lines2.bin x lines2.png x lines2.txt x lines3.bin x lines3.png x lines3.txt x lines4.bin
The general idea with this challenge seems to be that the .bin files are the raw game assets. The .png and the .txt files are the decoded assets, respectively. The flag was contained in the decoding of lines4.bin which has not yet been decoded.
To start, I took a look at each of the accompanying .png and .txt files.
lines1.txt
1 2
JC Denton: "Paul... I... I..." JC Denton: "I thought you were a GEP gun."
lines2.txt
1 2 3 4
Paul Denton: "We want to power down the whole system." Lobster: "That will be your butt." Paul Denton: "Yes sir!" Lobster: "Get PILLS against my orders! Get moving!"
lines3.txt
1 2
Agent Orange: "I do not move out of the way." JC Denton: "Forgive my interruption, my vision is augmented."
Sure enough, the files match up in their text. I then took a look at the .bin files:
It looks like the .bin files have a .png embedded in them. What is interesting is that all four provided .bin files have the exact same .png embedded in them at the same location. This .png looks like:
Given that the image is 64 x 96 pixels and the image shows rows of 8 characters and columns of 12 characters, I could only assume that there was some sort of indexing scheme into this image which would then build the resulting asset. The key would be figuring out how this indexing is done. I ran hexdump -C on each .bin file and output this to individual files lines1.hex, lines2.hex, and lines3.hex and ran sdiff -s to compare them in pairs:
Interestingly, it looks like the files only differ from bytes 0x17-0x1b and then from bytes 0x32c and onwards. Looking more closely, I saw that there are a lot of bytes in the range of 0x00 and 0x0b, inclusive. If I treat the .png file found in all of the .bin files as a grid, the columns can be indexed by 0x00 to 0x07 (8 columns) and the rows can be indexed by 0x00 to 0x0b (12 rows). Starting at byte 0x32d of file lines2.bin, the byte pairs are (0x00, 0x04), (0x03, 0x0b), (0x07, 0x0a). Matching these to characters in the reference .png, I get the letters Pau which matches the first 3 characters of lines2.txt!
When looking at the ASCII of the .bin files, I saw that preceding each line of text were the ASCII characters LiNe, which must have denoted a new line of the text.
With all of that knowledge, I wrote the following script to extract out the bytes after byte 0x325 in the file and perform the decoding:
res = [] lines = open('lines4.bin', 'rb').read()[0x325:]
spl = lines.split('LiNe')
for line in spl: if line: working_set = line[4:] constructed_line = '' for i in range(0, len(working_set), 2): constructed_line += data[ord(working_set[i+1])][ord(working_set[i])] constructed_line += '\n' res += constructed_line
print''.join(res)
Running the above script outputs the flag:
1 2 3
$ python solve.py Jock: "Oh my God! JC! A flag!" JC Denton: "A flag! AOTW{wh4t_4_r0tt3n_fi13_f0rm4t}"
A fun challenge which is a bit of a toy version of what one would find when reversing actual game asset files!