tiny runes
The objective is to decode
the message in the lines4.bin
by reverse engineering the file format.
By opening the lines4.bin
in hex editor, we can see
that it contains the magic header \x89PNG
at offset 0x24
,
thus it contains a PNG image.
The image can be carved by removing the preceeding bytes:
This image seems to be a character set.
The charset is the same in every bin
file.
After removing the image data, we are left with the following bytes (lines1.bin
):
The following decoded lines were provided by the author for lines1.bin
:
The LiNe
seems to be the line data structure header.
The four next bytes is the line size: 00 00 00 3C
.
By looking at the decoded data and
similarly repeating bytes in the encoded
data, one can see that bytes 05 09
correspond to dot
.
By looking at the charset image, 05
seems to be the column
and 09
is the row.
Now the lines4.bin
can be decoded
by converting
the image to
a 2D list and by using the LiNe
header to locate the line data:
import struct
filename = "lines4.bin"
data = None
with open(filename, 'rb') as f:
data = f.read()
LINE_HDR = "LiNe".encode("utf-8")
# For each row
CHARSET = [
['Q', '?', '0', '\\', 'H', '$', 'Y', ','],
['R', '-', 'L', '^', 'K', 'J', '', 'k'],
['s', '#', '_', '/', 'm', '=', 'f', '9'],
['7', 'd', '-', 'N', 'E', '4', 'q', 'r'],
['P', 'i', '', 'V', '`', '&', 'X', 'A'],
['n', '3', 'I', '', 'O', '*', ';', 'Z'],
['w', 'G', 'p', 'B', '8', 'c', 'S', 'j'],
['F', 'g', ':', 'e', 'b', 'y', '"', 'v'],
['%', '+', '', '1', ' ', '!', 'M', '©'],
['h', '{', '2', 'x', 'W', '.', 'D', '}'],
['t', 'U', '|', 'C', 'T', 'z', '6', 'u'],
['|', 'o', '>', 'a', '5', 'l', '<', '\'']
]
def parse_line(line_bytes):
line_len = struct.unpack(">I", line_bytes[:4])[0]
# print("Line len: %d" % line_len)
idx = 4
line = ""
while idx <= (line_len + 2):
col = line_bytes[idx]
row = line_bytes[idx+1]
# print("%d, %d" % (col, row))
char = CHARSET[row][col]
line += char
idx += 2
return line
def find_lines(data):
line_offsets = []
for i in range(len(data)):
current_hdr = data[i:i+4]
if current_hdr == LINE_HDR:
line_offsets.append(i + 4)
return line_offsets
lines = find_lines(data)
for line in lines:
print(parse_line(data[line:]))
The flag is:
Jock: "0h my God! JC! A flag!"
JC Denton: "A flag! AOTW{wh4t_4_r0tt3n_fi13_f0rm4t}"