66 lines
2.9 KiB
Python
66 lines
2.9 KiB
Python
#!/usr/bin/env python3
|
||
"""
|
||
Правильный флаг спрятан в младшем бите (LSB) альфа-канала пикселей,
|
||
где (R*G*B) % 7 == 3.
|
||
Ложный флаг находится в LSB красного канала.
|
||
Шаги:
|
||
1. Открыть изображение в режиме RGBA
|
||
2. Обойти пиксели в растровом порядке (слева направо, сверху вниз)
|
||
3. Для каждого пикселя проверить условие (R*G*B) % 7 == 3
|
||
4. Если условие выполнено — извлечь младший бит альфа-канала
|
||
5. Декодировать каждые 8 бит в один ASCII-символ
|
||
"""
|
||
import sys, os
|
||
from PIL import Image
|
||
|
||
def solve(filepath: str) -> str:
|
||
# Открываем изображение и принудительно переводим в режим RGBA
|
||
# (чтобы гарантированно получить альфа-канал)
|
||
img = Image.open(filepath).convert('RGBA')
|
||
pixels = img.load()
|
||
|
||
# Извлекаем младшие биты альфа-канала из подходящих пикселей
|
||
bits = []
|
||
for y in range(img.height):
|
||
for x in range(img.width):
|
||
r, g, b, a = pixels[x, y]
|
||
|
||
# Условие фильтрации: произведение RGB по модулю 7 равно 3
|
||
# Это нестандартный критерий, чтобы скрыть данные от обычных стего-сканеров
|
||
if (r * g * b) % 7 == 3:
|
||
# Берём только последний (младший) бит альфа-канала
|
||
bits.append(a & 1)
|
||
|
||
print(f"[*] Найдено {len(bits)} подходящих пикселей (бит)")
|
||
|
||
# Декодируем последовательность бит в строку флага
|
||
flag = ''
|
||
for i in range(0, len(bits) - 7, 8):
|
||
# Собираем байт из 8 последовательных бит (старший бит — первый)
|
||
byte_val = 0
|
||
for j in range(8):
|
||
byte_val = (byte_val << 1) | bits[i + j]
|
||
|
||
# Нулевой байт означает конец данных (аналог нуль-терминатора в C)
|
||
if byte_val == 0:
|
||
break
|
||
|
||
# Принимаем только печатаемые ASCII-символы (коды 32–126)
|
||
# Всё остальное — признак конца флага или мусорных данных
|
||
if 32 <= byte_val <= 126:
|
||
flag += chr(byte_val)
|
||
else:
|
||
break
|
||
|
||
return flag
|
||
|
||
|
||
if __name__ == '__main__':
|
||
img_path = os.path.join(os.path.dirname(os.path.abspath(__file__)),
|
||
'..', 'public', 'vacation.png')
|
||
|
||
if len(sys.argv) > 1:
|
||
img_path = sys.argv[1]
|
||
|
||
flag = solve(img_path)
|
||
print(f"[+] Флаг: {flag}") |