Райтап на задачу «Кости и Баги»

fderious

Автор:

fderious

31 октября 2026

7

31.10.2026
Кости и Баги
Категория:

Reverse

Задача «Кости и Баги»

Автор:

3T0T_FL4G_1MB4

Первая кровь:
broken_reality
Сложность:
medium
Дата публикации:
08.11.2025
Решений:
79
Рейтинг:
5/5
Ссылка:
Решать

Описание

Только элита достойна флага. Попробуй выиграть в кости и получить флаг.

Файл game-python3.9.pyc скомпилирован под версию Python 3.9.

Решение

Попробуем запустить игру через python3 start.py, однако получаем следующее:

RuntimeError: Bad magic number in .pyc file

Посмотрим на сам скомпилированный Python-файл. Необходимо его декомпилировать.

Гуглим. Такую задачу может выполнить утилита pycdc. Устанавливаем её и получаем исходный код через:

pycdc game-python3.9.pyc > game.py

Удалось декомпилировать не весь код, но нужная нам часть получена. Мы видим 3 обфусцированные функции: get_flag(), get_real_flag, k().

По коду узнаём, как проходит обфускация: zlib_compress, base64, reverse. Данное действие повторяется много-много раз, пока не получается итоговая строка.

По сути, нам нужно лишь расшифровать все функции, подобрав количество этапов обфускации.

Для деобфускации напишем простой код:

def deobfucated(data):
	match = re.search(rb"b'([^']+)'", data) # Убираем часть с exec()
	data = match.group(1)
	return zlib.decompress(base64.b64decode(data[::-1]))

Теперь наша задача — подобрать верное количество итераций так, чтобы программа вывела конкретно изначальную строку. Это можно сделать просто циклом:

for i in range(n): # n необходимо перебрать
    obfuscated = deobfucated(obfuscated)

Подобрать n можно бинарным поиском — если полученные данные всё ещё обфусцированные, то увеличиваем n, если получили ошибку — уменьшаем.

По итогу верное количество — 64 итерации.

Далее применяем наш алгоритм к каждой строке из декомпилированного кода.

Получаем следующее:

def _k():
	return bytes([0x68,0x65,0x68,0x65,0x68,0x65,0x5f,0x66,0x61,0x6b,0x65,0x5f,0x66,0x6c,0x61,0x67])
	
	
def _get_real_flag(data: bytes, key: bytes) -> bytes:
	klen = len(key)
	return bytes(d ^ key[i % klen] for i, d in enumerate(data))


def _get_flag():
	ct_hex = "2a100f263c232452140f5631125f12380e551a111d0b6b39501e136b1211"
	ct = bytes.fromhex(ct_hex)
	pt = _get_real_flag(ct, _k())
	print("\\nFlag " + pt.decode("utf-8", "ignore") + "\\n")	

Теперь нам остаётся лишь запустить данный код и получить заслуженный флаг!

Если вы нашли опечатку или ошибку, пожалуйста, выделите фрагмент текста и нажмите Ctrl+Enter

Также по теме:

Райтап на задачу «Прошлогодний флаг»

/Разборы задач

Райтап на задачу «Прошлогодний флаг»

Разбор задачи «Прошлогодний флаг» от fderious: изучаем бинарник в Ghidra и получаем флаг POST-запросом.
Прочитать

11

Райтап на задачу «Почувствуй радугу»

/Разборы задач

Райтап на задачу «Почувствуй радугу»

Разбор задачи «Почувствуй радугу»: изучаем ELF-файл в Ghidra и восстанавливаем флаг по MD5-хешам.
Прочитать

8