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

Reverse
Задача «Кости и Баги»
Только элита достойна флага. Попробуй выиграть в кости и получить флаг.
Файл 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") Теперь нам остаётся лишь запустить данный код и получить заслуженный флаг!