Автор: @FaLLenSkiLL
Ссылка на таск Codeby
https://codeby.games/categories/misc/4ed82185-29dc-4508-a863-eb1d81da9fb3
Описание задания
Архивы имеют случайные названия. Паролем к каждому архиву является строка, которая выводится при попытке его разархививации. Она закодирована в ROT13→Base64. Раскодируйте её и укажите в качестве пароля
Решение
Итак, нам дали зипку
Из описания мы знаем, что в зипках есть комменты, посмотрим на них с помощью exiftool
apt install exiftool
Каждый коммент зипки - пароль для следующей зипке. Стандартная матрешка. Но комменты зашифрованы ROT13→Base64. Значит для расшифровки нам нужно проделать обратную операцию.
Судя по размеру файла, матрешка довольно большая
По этому целесообразней будет автоматизировать весь процесс. Я буду использовать python. (кодик конечно костыльненький, но главное - работает)
Описание кода
Импортируем необходимые модули Python для работы с файловой системой, выполнения внешних команд, декодирования строк, и работы с zip-архивами.
import os
import subprocess
import base64
import codecs
import zipfile
Напишем функцию, которая принимает закодированную строку в формате base64, декодирует её, а затем применяет ROT13 шифрование к результату. После чего, возвращает декодированную строку.
def decode_rot13_base64(encoded_str):
decoded_bytes = base64.b64decode(encoded_str)
decoded_str = decoded_bytes.decode('utf-8')
return codecs.decode(decoded_str, 'rot_13')
Теперь используем утилиту exiftool
, которую скачали ранее, для извлечения комментария из метаданных zip-архива. После запуска exiftool
, вывод разбивается на строки, ищется строка, начинающаяся с Comment
, и извлекается сам комментарий.
def extract_comment_from_zip(zip_file):
try:
exiftool_output = subprocess.check_output(['exiftool', zip_file])
lines = exiftool_output.decode('utf-8').split('\n')
for line in lines:
if line.startswith('Comment'):
comment = line.split(': ')[1]
return comment
except subprocess.CalledProcessError:
print("Error: exiftool command failed.")
return None
Извлекаем содержимое zip-архива, с использованием заданного пароля. Функция открывает zip-архив, итерируется по всем файлам внутри, и извлекает их с помощью заданного пароля. После успешной распаковки архива, он удаляется (чтобы не заполнить папку кучей зипок).
def extract_zip_with_password(zip_file, password):
try:
with zipfile.ZipFile(zip_file, 'r') as zip_ref:
for info in zip_ref.infolist():
zip_ref.extract(info, pwd=password.encode())
os.remove(zip_file) # Удаление архива после распаковки
except zipfile.BadZipFile:
print("Error: Invalid zip file.")
except RuntimeError:
print("Error: Password incorrect.")
except Exception as e:
print(f"An error occurred: {e}")
И последняя функция. Она ищет zip-файл в текущем рабочем каталоге, извлекает комментарий из метаданных этого архива, декодирует комментарий, а затем использует полученный пароль для извлечения содержимого архива. После этого она запускается 1001 раз (именно столько нужно для решения таска).
def main():
current_dir = os.getcwd()
zip_files = [f for f in os.listdir(current_dir) if f.endswith('.zip')]
if len(zip_files) != 1:
print("Error: There should be exactly one zip file in the directory.")
return
zip_file = zip_files[0]
comment = extract_comment_from_zip(zip_file)
if comment:
zip_password = decode_rot13_base64(comment)
print(f"Archive {zip_file}: Password - {zip_password}")
extract_zip_with_password(zip_file, zip_password)
if __name__ == "__main__":
for _ in range(1001):
main()
В итоге получаем что-то такое:
import os
import subprocess
import base64
import codecs
import zipfile
def decode_rot13_base64(encoded_str):
decoded_bytes = base64.b64decode(encoded_str)
decoded_str = decoded_bytes.decode('utf-8')
return codecs.decode(decoded_str, 'rot_13')
def extract_comment_from_zip(zip_file):
try:
exiftool_output = subprocess.check_output(['exiftool', zip_file])
lines = exiftool_output.decode('utf-8').split('\n')
for line in lines:
if line.startswith('Comment'):
comment = line.split(': ')[1]
return comment
except subprocess.CalledProcessError:
print("Error: exiftool command failed.")
return None
def extract_zip_with_password(zip_file, password):
try:
with zipfile.ZipFile(zip_file, 'r') as zip_ref:
for info in zip_ref.infolist():
zip_ref.extract(info, pwd=password.encode())
os.remove(zip_file) # Удаление архива после распаковки
except zipfile.BadZipFile:
print("Error: Invalid zip file.")
except RuntimeError:
print("Error: Password incorrect.")
except Exception as e:
print(f"An error occurred: {e}")
def main():
current_dir = os.getcwd()
zip_files = [f for f in os.listdir(current_dir) if f.endswith('.zip')]
if len(zip_files) != 1:
print("Error: There should be exactly one zip file in the directory.")
return
zip_file = zip_files[0]
comment = extract_comment_from_zip(zip_file)
if comment:
zip_password = decode_rot13_base64(comment)
print(f"Archive {zip_file}: Password - {zip_password}")
extract_zip_with_password(zip_file, zip_password)
if __name__ == "__main__":
for _ in range(1001):
main()
Запускаем код
Последнюю зипку также смотрим с помощью exiftool и получаем флаг
Флаг
Tags: