Archive
MMA CTF 2015 Splitted writeup Forensics
Download the challenge file from here
The challenge involved, a little bit of thinking to solve in a simple way, if you are unsure about the zip file structure. A zip file was split into 8 different parts and it was sent to the host 192.168.3.10. The task is, reconstruct the fragments of the zip file, arrange it in order adhering to the zip file structure. Once you do it you will get a valid Adobe Photoshop file ( .psd). Then extract the image to view the flag. This works only if you reconstruct the zip file in the order mentioned in the zip file structure. Since it is just a 30 points challenge, I didn’t spend much time in thinking about solving in a proper way. Here is the idea (#lame 😀 :P) I came up with,
- Reconstruct the fragments from the Wireshark. If you are doing it by hand make sure to strip the HTTP headers in the beginning. The best way is to Export the HTTP objects. Find my reconstructed fragments from here
- Identify the header and footer of a zip file. Zip file header always starts with the magic number 50 4B 03 04 14 00… (HEX), PK…….(ASCII). Now the footer, it looks something like this,
- You have identified the header and footer. So the number of remaining fragments from the pcap file is 6 (excluding the header and footer) out of 8. So there are 6! (spelled as six factorial) ways to arrange these fragments to get a valid zip file. We just wrote a script using Python to do complete this task (I owe my sincere thanks 😛 to b3h3m0th for helping me with this script).
#!/usr/bin/env python import itertools import zipfile import os body_n = [1, 3, 4, 6, 7, 8] header = "2_header.raw" footer = "5_footer.raw" def generate_file(sequence, i):    final_file = "final_" + str(i) + ".zip"    open(final_file, "w").close()    final = open(final_file, "a")    header_data = open(header, "r").read()    footer_data = open(footer, "r").read()    final.write(header_data)    for item in sequence:        d = open(item, "r").read()        final.write(d)    final.write(footer_data)    final.close()    try:        content = zipfile.ZipFile(final_file)        content.extractall()        print "\n\n\n\n [*] permutation", i, "SUCCESS !!! "        print "\n [i] Successful Sequence:\n\n"        print header        for item in sequence:            print item        print footer    except:        os.remove(final_file) def main():    perms = []    body_list = [str(i) + ".raw" for i in body_n]    permsobj = itertools.permutations(body_list)    while True:        try:            perms += [permsobj.next()]        except StopIteration:            break    i=1    for item in perms:        generate_file(item, i)        i = i+1 if __name__ == "__main__":    main()
When you run this script you will get the sequence (2_header.raw, 6.raw, 7.raw, 3.raw.. etc) as well as the valid zip file.
Unzip the valid zip file which is reconstructed using this script. The file name would be final_443.zip. When you unzip you will get a psd file. We used a psd file parser to get the layered images. After running the parser on the psd file we got the flag.
One of the image had our flag,
[EDIT] Another way to reconstruct the ZIP file
Here is a elegant way to solve the challenge. I came to know about this method from the comments.
Filter the http packets. When you click on a GET request packet you can see the “Range” field( in the HTTP section). Now carefully look the range of values(Range field) in all the packets, you will notice a sequence, With that we can reconstruct the zip file.
Packet No: 14Â Range : 2345-2813
Packet No: 24Â Range : 0 – 468
Packet No: 34Â Range : 1407 – 1875
Packet No: 44Â Range : 2814 – 3282
Packet No: 54Â Range : 3283 – 3744
Packet No: 64Â Range : 469 – 937
Packet No: 74Â Range : 938 – 1406
Packet No: 84Â Range : 1876 – 2344
Now order these packets in increasing order and then write it to a file. So the order should be: Packet number : 24, 64, 74, 34, 84, 14, 44, 54. Or export the data streams in these order, rearrange it to get the valid zip file.