Magic Image
Сегодня мы с вами рассмотрим таск на криптографию с недавно прошедших TU CTF 2016.
Magic Image
100
We found this png, but it seems to be encrypted...
Can you decrypt it?
100
We found this png, but it seems to be encrypted...
Can you decrypt it?
В архиве два файла: 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 файла!
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!
FLAG: TUCTF{st@llowing_xOR_5ince_Apollo}
- Автор: drakylar
- Комментарии: 0
- Просмотры: 3845