Лаборатория TJCTF 2016 - µ'sic [forensics 200]

delimitry
, 6 июня 2016

µ's Music Start!

I was solving this task for 3-4 days after TJCTF and yesterday finally solved it.

We are given a link to µ'sic.zip file.

Archive is protected with a password. I've brutted the pasword to the archive.
Password is "LL". Inside the archive a Welcome.txt file with the next message is stored:

Welcome to µ'sic!

The purpose of this challenge is to elucidate the applications of forensics and steganography techniques and the manner in which they may be solved. Our intent is that you will learn and develop a multitude of skills as you progress through this challenge.

For each "layer" of this challenge, we have included one of our favorite songs from Love Live! (now you know what LL stands for), along with the cover image that came with the CD for each song. Each layer involves a password protected zip file, and the password can be found hidden in the cover image.

If nothing else, please enjoy the µ'sic!

-µ's

So we have several nested archives with songs, posters and some other files. 
Each level's cover image contains a hidden password to the next level's zip archive.

Level 0

Password is hidden as a plain text in the cover image:
mfrzwc2eqkuj2quc4j3soofav3gmn80r1wtn7l2ajr7z0fkrtp

Level 1

We have two cover images. We can find diff bytes using Python script:

with open('1.jpg', 'rb') as f:
    data1 = f.read()
with open('2.jpg', 'rb') as f:
    data2 = f.read()

out = ''
for i in xrange(len(data1)):
    if data1[i] != data2[i]:
        out += data1[i]
print out

And get a next data:
amJ2NzI4d2hwdXp3ZnF1a3YzMG55NTZ5NnJwbm8wZGl3bnhidmU5Z2ZmanZ0c2NiOXI=
Which is base64 encoded next level's password:
jbv728whpuzwfqukv30ny56y6rpno0diwnxbve9gffjvtscb9r


Level 3

Inside this level's achive we have a PDF file.
Using the next script I've extracted and decompressed all stream data blocks from PDF.

import zlib


with open('1.pdf', 'rb') as f:
    data = f.read()

while True:
    start = data.find('\x0Astream\x0A')
    if start < 0:
        break
    data = data[start + 8:]
    end = data.find('\x0Aendstream')
    try:
        decompressor = zlib.decompressobj()
        dec_data = decompressor.decompress(data[:end]) 
        with open('out.png', 'wb') as f:
            f.write(dec_data)
    except:
        pass



Is is password written with Wingdings font.

Password:
yd9mhgzsdsqyll3w6hn222i1s044bx8i0ho4jqtgcrplbos1zj


Level 4

In this level's archive we have two PNG images. Using the next script I've extracted diff image with a password:

import operator
from PIL import Image


def diff(col1, col2):
    return map(abs, map(lambda x: operator.sub(*x), zip(col1, col2)))


img1 = Image.open('1.png')
pixels1 = img1.load()

img2 = Image.open('2.png')
pixels2 = img2.load()

w, h = img1.size

img3 = Image.new('RGB', (w, h))
pixels3 = img3.load()

for y in xrange(h):
    for x in xrange(w):
        v = tuple(diff(pixels1[x, y], pixels2[x, y]))
        if v == (1, 1, 1):
            pixels3[x, y] = (255, 255, 255)
        else:
            pixels3[x, y] = v

img3.save('out.png')



Password:
yq4s5wsc01otk81j1ami7qahdup6f01equ0gbj7jt5d38wkm1p

Level 5

We have a jpg file. I've noticed that inside of this file, zip achive is hidden. With the next script - I've extracted it.

with open('Cutie Panther.jpg', 'rb') as f:
    data = f.read()

pos = data.find('PK')

with open('out.zip', 'wb') as f:
    f.write(data[pos:])

Inside extracted archive - Cutie Panther.png image with QR codes... Lots of them...
Image size is 13500 x 13500 pixels. 900 QR codes.
So I've cutted the image into subimages with QR codes. And then decoded each of them.

import glob
import os
import re
import subprocess
import zipfile
from PIL import Image


def cut_qr_codes(img_path, out_dir, qr_left, qr_top, qr_w, qr_h, qr_step_x, qr_step_y):
    """ Cut off subimages from image """
    if not os.path.exists(out_dir):
        os.makedirs(out_dir)
    img = Image.open(img_path)
    img_w, img_h = img.size
    index = 0
    for j in xrange(qr_top, img_h - qr_top - qr_step_y, qr_h + qr_step_y):
        for i in xrange(qr_left, img_w - qr_left - qr_step_x, qr_w + qr_step_x):
            print i, j, index
            img.crop((i, j, i + qr_w, j + qr_h)).save(os.path.join(out_dir, '%003d.png' % index))
            index += 1


def decode_qr(path):
    """ Decode QR using zbar """
    res = subprocess.check_output('zbarimg %s -q' % path, shell=True)
    return re.findall('QR\-Code:(.*)\r', res)


def unzip_specific_file(zip_file, name, password):
    """ Unzip file from zip archive """
    try:
        zip_file.extract(name, pwd=password)
        return True
    except:
        pass
    return False



def main():
    # cut image into subimages with QR codes
    out_dir = './qr_codes/'
    cut_qr_codes('Cutie Panther.png', out_dir, 40, 40, 371, 371, 79, 79)

    # decode QR codes
    passwords = []
    for fn in glob.glob(os.path.join(out_dir, '*.png')):
        data = decode_qr(fn)
        passwords.append(data)

    # find the password
    filename = 'zip5.zip'
    zip_file = zipfile.ZipFile(filename)
    
    # get image's name in archive
    name = ''
    for name in zip_file.namelist():
        if name.endswith('.jpg'):
            print name
            break

    for password in passwords:
        if unzip_specific_file(zip_file, name, password):
            print 'password is:', password
            break


if __name__ == '__main__':
    main()

After running this script, I've found appropriate password.

Password: 
4w3d9ewgg1tdc3s8njc73754i01cs9j1jyzb1sbez5d2pkyp8f

Level 6

import itertools
from collections import Counter
from PIL import Image


img = Image.open('Octal.png')
w, h = img.size
pixels = img.load()

colors_data = []
for y in xrange(0, h, 20):
    for x in xrange(0, w, 20):
        col = pixels[x, y]
        colors_data.append(col)

alphabet = set(colors_data)
alphabet_len = len(alphabet)

out_file = open('out.dat', 'wb')

colors = map(str, xrange(8))
for items in itertools.product(colors, repeat=alphabet_len):
    # get only possible variants without repetition
    if len(set(items)) == alphabet_len:
        alpha_to_item = dict(zip(alphabet, items))
        # get image as an octal number
        oct_number = ''.join(alpha_to_item.get(x) for x in colors_data)
        dec_number = int(oct_number, 8)
        # write all possible results
        if len(hex(dec_number)[2:-1]) % 2 != 0:
            out_file.write(('0' + hex(dec_number)[2:-1]).decode('hex') + '\n')

out_file.close()

After running the script I've checked the file with huge number of possible results. And one of them was:
ip34ckxjmesttnw2hh583bixxb0pv44dg71emze2skvjbtroamSusumeTomorrowSusumeTomorrowSusumeTomorrowSusumeTomorrowSusumeTomorrowSusumeTomorrowSusumeTomorrowSusumeTomorrowSusumeTomorrowSusumeTomorrowSusumeTomorrowSusumeTomorrowSusumeTomorrowSusumeTomorrowSusumeTomorrowSusumeTomorrowSusumeTomorrowSusumeTomorrowSusumeTomorro

So a first part of this message is a password:
ip34ckxjmesttnw2hh583bixxb0pv44dg71emze2skvjbtroam

Level 7

On this level - a password was simply hidden in JPG file as plain text.

Password:
amu60gb7wjbh6sngfuqks3yurom7noyxppgdebuz70qrpvxme1
 
Level 8

In this level we have a PNG file. 
I've noticed a hint in PNG file after IEND block: r^g&b

And using the next script I've got a password to the next level:

from PIL import Image


img = Image.open('1.png')
w, h = img.size
pixels = img.load()
bits = ''

img_out = Image.new('RGB', (w, h))
img_out_pixels = img_out.load()

for j in xrange(h):
    for i in xrange(w):
        col = pixels[i, j]
        r, g, b = col
        bits += '1' if (r^g&b) & 0b1 else '0'
        img_out_pixels[i, j] = (255, 255, 255) if ((r ^ g & b) & 0b1) else (0, 0, 0)
    break

bits = '0' + bits  # !!!!
out = ''
for i in xrange(0, len(bits), 8):
    out += chr(int(bits[i:i + 8], 2))
print `out`

Password:
tkf68pm2s5xx49xpsgjw0gt19scp7axwe8yliqohjvwgw8dexl

Level 9

The last archive contained Flag.png file with part of QR code. Only a part :(


I've decoded QR code by hands :)
Here is the structure of QR code, I've filled each data blocks with color:



It is QR code version 4 (33x33). As you can see the mask (x % 3) is used here.
First block = 4 or byte encoding (8 bits per character).
Second block is a encoded message length = 58.
Next four blocks in the first column are t, j, c, t.
In such way all 58 bytes of data was extracted.

Flag is:
tjctf{g91s4p7y0mzf4p0ufkxfvyopdiekgx21a5fcxhv5p9uj8fqu0c2} 

It was a really difficult task by Annabel Faylan. Thank you!
Inception! We need to go deeper! :)

1 комментарий:

  1. Justnix
       #   10:32, 24 мая 2017
    Zithromax Cost Cialis Free Offer Novolog Ltd Antibiotic Keflex And The Liver Buy Cheap Kamagra Pills Cialis Pas Cher Espagne Finax Generic Propecia Hair Loss Cialis Online Buy Levitra Orodispersibile Prezzo In Farmacia Viagra Uk 150mg Buy Cialis Zithromax For Strep Throat Nolvadex Dosage For Epistane ?Tadalafil Viacom Orlistat Diet Pill Genuine Viagra Cheap Low Price Cialis Levitra Viagra O Cialis Baclofene Amm Get Cheap Cialis Online Buy Accutane In Usa Fast Viagra Delivery Mail Order Zoloft isotretinoin order internet no physician approval Taking Anaprox With Amoxicillin Low Cost Cialis Online Amoxicillin 875mg Tablet Silagra 100 Uk For Sale Propranolol Online Cheap Keflex Is Not Very Strong Baclofene Mal De Tete Buy Kamagra Jelly Online Achat Kamagra Oral Jelly Cephalexin Dosage Puppy Cheapest Levitra Tadalafil Generique Viagra En Vente Where To Buy Zoloft Levitra Prix Au Maroc Keflex Manufacturing Cialis Online No Propecia Infertilidad Cialis Kaufen In Hamburg Cialis Online Usa Generic Finasteride Skin Cialis 20 Mg Utilizzo Buy Kamagra Doryx Website Discount On Line Buying Provera Online Viagra Online Stores Where To Get Levitra Can You Take Benadryl With Amoxicillin Ordina Zoloft Online Cialis Kaufen Internet Viagra Foto Pillola Purchase Viagra Buy Amlodipine Without Prescription Cialis Quanto Costa In Farmacia How Much Is Kamagra Cephalexin Information Generic Free Shipping Clobetasol 0.05% Psoriasis Kamagra En Ligne World Pharmacy Store Achat Cialis Us Ordering Cialis Online Lioresal En Ligne 10mg Online Cialis India Purchase Cheap Xenical Amoxil Informations Peut On Acheter Cialis Sans Ordonnance En Pharmacie Where To Order Kamagra Kamagra Fast London Am Luat Propecia Order Zoloft Tablets Order Acticin Permethrinum Scabies Quick Shipping Australia Cheapeast Buy Cipro Online Uk Tadalafil 20mg Viagra 200mg Online Price Canada Viagra Einnahme Cialis Where To Order Cialis Amoxicillin Dosage For Strep Propecia Help Baldness Sildenafil Generic Amoxicillin Dosing Schedule Flex Keflex 250mg Kamagra Jelly Online Priligy Mise A Jour

Авторизуйтесь, что бы оставить комментарий