Художественная галерея

Stego 979 pts

Изучаем выданный `gallery.psd` — PSD-файл с пятью слоями: | # | Имя | Состояние | |---|---|---| | 0 | `Background` | видимый | | 1 | `Title` | видимый | | 2 | `Pattern A` | скрытый | | 3 | `Pattern B` | скрытый | | 4 | `Encrypted` | скрытый | Два из трёх скрытых слоёв — ложный след, а настоящий QR-код лежит в третьем и дополнительно зашифрован AES'ом. ## Решение PSD разбираем руками по [официальной спецификации Adobe](https://www.adobe.com/devnet-apps/photoshop/fileformatashtml/). Структура файла такая: ```mermaid block-beta columns 1 H["8BPS header"] CM["Color Mode Data"] IR["Image Resources
XMP ID 0x0424 ← ключ к расшифровке"] LMI["Layer and Mask Info
слои, флаги, каналы"] ID["Image Data"] classDef base fill:#f3f4f6,stroke:#6b7280,color:#111827 classDef hit fill:#fef3c7,stroke:#f59e0b,color:#78350f class H,CM,LMI,ID base class IR hit ``` В секции `Image Resources` ищем XMP-метаданные (блок с ID `0x0424`) — там и запрятан ключ ко всей задаче. Внутри XMP смотрим на тег ``: ISO 8601 timestamp создания файла. В секции `Layer and Mask Information` для каждого слоя лежит имя, флаги видимости (бит `0x02` в flags = «скрытый»), `opacity` и сырые данные каналов. Пиксельные данные хранятся несжатыми — можно напрямую залить в `numpy`-массив `h × w`. Первое, что теперь приходит в голову при виде двух скрытых «паттернов» — это XOR'нуть их между собой. Берём `Pattern A` и `Pattern B`, XOR — получается картинка с вполне читаемым QR-кодом. Сканируем, внутри флаг, таск решён… *кроме того, что флаг внутри фейковый*. Настоящий QR живёт в третьем скрытом слое — `Encrypted`, и это шифротекст исходного QR в режиме AES-ECB. Ключ для AES собирается из той самой timestamp-метки: ```python aes_key = sha256(timestamp.encode()).digest()[:16] ``` Расшифровываем R-канал в `AES.MODE_ECB`, снимаем PKCS#7-паддинг по последнему байту, интерпретируем результат как `h × w` grayscale-картинку. Внутри — настоящий QR, внутри QR — флаг. Если `pyzbar` с первого раза не узнал код, помогает `NEAREST`-апскейл в 2–3 раза. Готовый солвер — [`solve/solver.py`](solve/solver.py). ## Флаг `caplag{l4y3rs_0f_d3c3pt10n_unv31l3d}`