Magic Image

Сегодня мы с вами рассмотрим таск на криптографию с недавно прошедших TU CTF 2016.

Magic Image
100

We found this png, but it seems to be encrypted...

Can you decrypt it?

6d5e0b3d406ba8f099f3b363b019127839fe6cac.zip [345,5 Kb] (cкачиваний: 56)

В архиве два файла: encrypt.py и encrypted.png

Вкратце: типичная ситуация - нам дан скрипт, которым было зашифровано изображение, и требуется получить исходное изображение.

Исследуем код

Изучив encrypted.png ничего не нашли, давайте рассмотрим файл encrypt.py:

#!/usr/bin/env python

def xor(s1, s2):
    res = [chr(0)]*12
    for i in range(len(res)):
        q = ord(s1[i])
        d = ord(s2[i])
        k = q ^ d
        res[i] = chr(k)
    res = ''.join(res)
    return res

def add_pad(msg):
    l = 12 - len(msg)%12
    msg += chr(l)*l
    return msg

with open('flag.png') as f:
    data = f.read()

data = add_pad(data)

with open('key') as f:
    key = f.read()

enc_data = ''
for i in range(0, len(data), 12):
    enc = xor(data[i:i+12], key)
    enc_data += enc

with open('encrypted.png', 'wb') as f:
    f.write(enc_data)



Изучим подробнее главную часть скрипта:

with open('flag.png') as f:
    data = f.read()

data = add_pad(data)

with open('key') as f:
    key = f.read()

enc_data = ''
for i in range(0, len(data), 12):
    enc = xor(data[i:i+12], key)
    enc_data += enc

with open('encrypted.png', 'wb') as f:
    f.write(enc_data)


1. Открытие и присваивание data строковое значение файла
with open('flag.png') as f:
    data = f.read()


2. Добавление в конец несколько байтов, чтобы длина строки делилась на 12
data = add_pad(data)


3. Считывание ключа как строку(переменная key)
with open('key') as f:
    key = f.read()


4. Разделение строки data на строки длинной 12 символов и XOR каждой из строк ключем KEY

for i in range(0, len(data), 12):
    enc = xor(data[i:i+12], key)
    enc_data += enc



5. Сохранение обновленного файла

with open('encrypted.png', 'wb') as f:
    f.write(enc_data)



Решение таска

Собираем все пункты в одно целое и получаем следующее: наше изображение шифруется алгоритмом XOR с неизвестным ключом длиной 12 символов.

У алгоритма XOR есть следующая особенность:

A ^ B = C
C ^ B = A  ==>  data ^ key = enc_data  ==> key = enc_data ^ data
C ^ A = B


Откуда следует, что нам нужно про-XOR-ить промежуток длиной 12 символов до шифрования и после. А откуда взять такой промежуток? Ну конечно же заголовок PNG файла!

Magic Image

89 50 4E 47 0D 0A 1A 0A 00 00 00 0D


Теперь делаем XOR данной строки и 12 строк начала файла и получаем ключ!

$ ls
encrypt.py	encrypted.png
$ python
Python 2.7.10 (v2.7.10:15c95b7d81dc, May 23 2015, 09:33:12) 
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> f = open('encrypted.png')
>>> enc_data = f.read()[:12]
>>> data = '89504E470D0A1A0A0000000D'.decode('hex')
>>> data
'\x89PNG\r\n\x1a\n\x00\x00\x00\r'
>>> key = "".join(chr(ord(x) ^ ord(y)) for x, y in zip(data, enc_data))
>>> key.encode("hex")
'033f651576ea25bc2ad3b50d'


Вот мы и получили ключ! Думаю единственная строка, которую нужно разьяснить - это с join: это одна из реализаций XOR'а двух строк (в данном случае data и enc_data) в питоне.


Ну и последний шаг! Делаем замену в исходном скрипте и запускаем его с encrypted.png


with open('key') as f: key = f.read()  ==>  key = '033f651576ea25bc2ad3b50d'.decode('hex')

with open('flag.png') as f:  ==>  with open('encrypted.png') as f:

with open('encrypted.png', 'wb') as f:  ==>  with open('flag.png', 'wb') as f:



Пояснение: теперь наш файл про-XOR-ится с encrypted.png и сохранит файл flag.png. Фактически мы просто подставили ключ и поменяли местами два файла.

Код целиком:

#!/usr/bin/env python

def xor(s1, s2):
    res = [chr(0)]*12
    for i in range(len(res)):
        q = ord(s1[i])
        d = ord(s2[i])
        k = q ^ d
        res[i] = chr(k)
    res = ''.join(res)
    return res

def add_pad(msg):
    l = 12 - len(msg)%12
    msg += chr(l)*l
    return msg

with open('encrypted.png') as f:
    data = f.read()

data = add_pad(data)

key = '033f651576ea25bc2ad3b50d'.decode("hex")

enc_data = ''
for i in range(0, len(data), 12):
    enc = xor(data[i:i+12], key)
    enc_data += enc

with open('flag.png', 'wb') as f:
    f.write(enc_data)



Запускаем наш измененный скрипт и открываем flag.png!

Magic Image


FLAG: TUCTF{st@llowing_xOR_5ince_Apollo}скачать dle 10.5фильмы бесплатно

  • Автор: drakylar
  • Комментарии: 0
  • Просмотры: 3845

Добавить комментарий

Вы не авторизованы и вам запрещено писать комментарии. Для расширенных возможностей зарегистрируйтесь!