These funny humans
try to exclude us from the delicious beer of the Oktoberfest! They made up a
passcode for everyone who wants to enter the Festzelt. Sadly, our human
informant friend could not learn the passcode for us. But he heard a
conversation between two drunken humans, that they were using the same passcode
for this intercepted archive file. They claimed that the format is is
absolutely secure and solves any kind of security issue. It’s written by this
funny hacker group named FluxFingers. Real jerks if you ask me. Anyway, it
seems that the capability of drunken humans to remember things is limited. So
they just used a 6 character passcode with only numbers and upper-case letters.
So crack this passcode and get our ticket to their delicious german
beer!
Here is the
challenge:
https://ctf.fluxfingers.net/static/downloads/fluxarchiv/hacklu2013_archiv_challenge1.tar.gz
These sneaky humans!
They do not just use one passcode, but two to enter the Festzelt. We heard that
the passcode is hidden inside the archive file. It seems that the FluxFingers
overrated their programming skill and had a major logical flaw in the archive
file structure. Some of the drunken Oktoberfest humans found it and abused this
flaw in order to transfer hidden messages. Find this passcode so we can finally
drink their beer!
(only solvable when FluxArchiv (Part 1) was solved)
Here is the challenge:
https://ctf.fluxfingers.net/static/downloads/fluxarchiv/hacklu2013_archiv_challenge1.tar.gz
Solution
When trying to solve this challenge, we accidently forgot to read the challenge
description so we ended up solving part2 before part1. For this challenge, we
get a program and an archive created by this program. Starting the program
gives:
1234567891011121314151617
$ ./archiv
################################################################################FluxArchiv - solved security since 2007!
Written by sqall - leading expert in social-kernel-web-reverse-engineering.
################################################################################Unknown or invalid command.
Usage: ./archiv <command> <archiv> <password> <file>
commands:
-l <archiv> <password> - lists all files in the archiv.
-a <archiv> <password> <file> - adds a file to the archiv (when archiv does not exist create a new archiv).
-x <archiv> <password> <filename> - extracts the given filename from the archiv.
-d <archiv> <password> <filename> - delete the given filename from the archiv.
So the programm requires a password for every operation on an archive file.
After some reversing, we found out, that the password is hashed with sha1 and
the result is used as seed for a rc4 prng. Everytime a chunk ob data should be
encrypted, the prng is reset with the sha1sum and the data is xored with the
prng data. So to find out more about the fileformat, we created two archive
files with different password:
$ dd if=/dev/urandom of=1mb bs=1024 count=1024
1024+0 Datensätze ein
1024+0 Datensätze aus
1048576 Bytes (1,0 MB) kopiert, 0,0755623 s, 13,9 MB/s
$ ./archiv -a test1 pw1 1mb
################################################################################FluxArchiv - solved security since 2007!
Written by sqall - leading expert in social-kernel-web-reverse-engineering.
################################################################################Archiv test1 successfully created.
Progress:
0% ... 10% ... 20% ... 30% ... 40% ... 50% ... 60% ... 70% ... 80% ... 90% ... 100%
File 1mb successfully added to the archiv.
$ ./archiv -a test2 pw2 1mb
################################################################################FluxArchiv - solved security since 2007!
Written by sqall - leading expert in social-kernel-web-reverse-engineering.
################################################################################Archiv test2 successfully created.
Progress:
0% ... 10% ... 20% ... 30% ... 40% ... 50% ... 60% ... 70% ... 80% ... 90% ... 100%
File 1mb successfully added to the archiv.
The result should be two files with completely the same content only the
cipherstream is different, so with the following script, we can find the
cipherstream starts and reverse the format:
12byte unencrypted “FluXArChiV13” header (can be seen when looking at the hexdump)
20byte unencrypted sha1 hash of scrambled input pw (found while reversing)
8byte “FluXL1sT” header
8byte of unknown data
8 file entries:
2x 8bytes of unknown data
16bytes md5sum (found while reversing and checked against 1mb file)
96 byte filename, padded with null bytes
many data chunks:
8bytes of unknown data
1032byte file data
What is interesting, is the encrypted “FluXL1sT” header and the zero padded
filenames, because we can reconstruct the keystream from these, lets see what
we can find out about the original archive when using what we already know
about the format:
Looks like we got the whole file listing and it looks consistent, so we can
assume the keystream is correct. But we still need more bytes of the keystream
to decompress the whole data because we only have 96 bytes at the moment, but
while going through what we already have, we found a new file listing at
0x2bef0 with this script:
Small modifications to the directory listing parser spit out another
filelisting with just one file th_oh-noes-everybody-panic.gif and an md5sum
of f1df033f0179fe101d11700fe796b4fd, luckily we could find the original (we
couldn’t find the original of any other file until now) with a matching md5sum
and could reconstruct enough bytes to parse the whole file with this script: