42 lines
2.0 KiB
Markdown
42 lines
2.0 KiB
Markdown
<h1 align="center">PYZ Sidecar</h1>
|
|
|
|
<p align="center">
|
|
<img src="https://img.shields.io/badge/category-Reverse-blueviolet" alt="Reverse"/>
|
|
<img src="https://img.shields.io/badge/difficulty-easy-brightgreen" alt="easy"/>
|
|
</p>
|
|
|
|
В раздатке есть файл `LineSigner.bin` с Python-утилитой для подписи отчётов. Файл начинается со строк `#!/bin/sh` и `exit 1`. Ищем данные утилиты после этой shell-обёртки.
|
|
|
|
## Решение
|
|
|
|
Находим маркер `PYZSIDECARv1\x00`. После него записаны длина блока в формате `u32 LE` и zlib-поток. Распаковываем блок и получаем сериализованный через `marshal` объект Python-кода.
|
|
|
|
Артефакт собран под **Python 3.13**, эту же версию используем для разбора. У `marshal` нет совместимости байткода между произвольными версиями интерпретатора.
|
|
|
|
```python
|
|
from pathlib import Path
|
|
import dis
|
|
import marshal
|
|
import zlib
|
|
|
|
data = Path("public/LineSigner.bin").read_bytes()
|
|
pos = data.index(b"PYZSIDECARv1\x00") + len(b"PYZSIDECARv1\x00")
|
|
size = int.from_bytes(data[pos:pos + 4], "little")
|
|
code = marshal.loads(zlib.decompress(data[pos + 4:pos + 4 + size]))
|
|
dis.dis(code)
|
|
```
|
|
|
|
Внутри видна функция `verify(report_id)`. Она собирает результат из трёх строковых констант:
|
|
|
|
```python
|
|
"caplag{pyz_o" + "ffset_showed_" + "the_signing_secret}"
|
|
```
|
|
|
|
Соль `line-signer-2025` к этим кускам не относится. Можно восстановить строку по константам и дизассемблированию. Приложенный солвер выполняет извлечённый код и вызывает `verify("report-17")`.
|
|
|
|
[Солвер](solve/solve.py).
|
|
|
|
## Флаг
|
|
|
|
`caplag{pyz_offset_showed_the_signing_secret}`
|