Читаем текст задания:
logo-1.png [443 КБ]
Первое, что приходит в голову — попробовать закрасить черный и белый цвет. Сразу же находим пасхалку разработчиков таска, злимся и ищем дальше. Черный фон закрасить не получилось, при внимательном изучении понимаем, что он составлен из нескольких градаций черного цвета.
Исследуем изображение дальше, загружаем его в программу StegSolve и в режиме Blue plane 2 находим вторую пасхалку, злимся еще больше.
Обращаем внимание на главный фон, начинаем исследовать его. Замечаем, что он содержит не весь RGB-диапазон, а цвета повторяются. Отсюда предполагаем, что флаг скрыт через близкие по значению цвета.
После нескольких часов раздумий и отработки различных вариантов в голову приходит посчитать количество пикселей у которых одинаковый Red, Green или Blue цвет. Для этого пишем небольшой python скрипт:
from PIL import Image
image = Image.open('logo-1.png')
pixels = image.load()
counter = []
for i in range(0,256):
counter.append(0)
for i in range(image.size[0]):
for j in range(image.size[1]):
counter[pixels[i,j][0]] += 1
print counter
Где — counter[pixels[i,j][0]] — ноль соответствует Red цвету. Т.е. мы выводим все пиксели, у которых одинаковое значение красного цвета (Red=const;Green;Blue);
Запускаем скрипт и получаем результат:
[7501, 7602, 6979, 7090, 6882, 6976, 6747, 6869, 27, 23, 29, 22, 17, 25, 16, 40, 29, 25, 21, 27, 3, 2, 3, 2, 2, 3, 1, 0, 5, 3, 2, 4, 2, 4, 1, 2, 3, 4, 1, 1, 1, 2, 1, 0, 3, 3, 1, 2, 15, 15, 44, 17, 22, 20, 19, 0, 21, 13, 29, 17, 24, 37, 0, 5, 2, 2, 0, 1, 4, 1, 4, 1, 5, 3, 2, 1, 1, 1, 2, 4, 1, 2, 1, 0, 1, 3, 1, 2, 1, 2, 2, 2, 1, 4, 5, 5, 8, 1, 1, 0, 1, 2, 0, 1, 2, 1, 1, 0, 2, 2, 1, 4, 0, 4, 2, 3, 0, 1, 3, 2, 15499, 15391, 15603, 15602, 15407, 15452, 15348, 15376, 15277, 15456, 15609, 1, 3, 2, 1, 0, 2, 1, 2, 0, 4, 2, 0, 1, 134, 145, 126, 138, 41, 42, 33, 27, 3, 1, 2, 2, 0, 3, 1, 2, 2, 1, 1, 2, 0, 0, 3, 5, 3, 3, 2, 4, 0, 3, 2, 1, 32, 51, 67, 1, 66, 144, 80, 1, 3, 0, 1, 3, 2, 4, 2, 2, 1, 0, 2, 1, 2, 0, 3, 2, 1, 3, 1, 2, 0, 5, 3, 5, 0, 2, 1, 2, 56, 80, 4, 5, 134, 150, 1, 0, 0, 0, 3, 1, 3, 1, 1, 2, 11, 9, 3, 2, 4, 3, 1, 1, 3, 3, 2, 4, 4, 5, 4, 1, 4, 7, 3, 3, 6, 4, 4, 3, 19, 12, 255, 20498]
Так, уже интереснее. Первые 8 значений — 7501, 7602, 6979, 7090, 6882, 6976, 6747, 6869 — градации черного цвета по центру. Значение в конце — 20498 — белый цвет надписи. Ну и значения по центру — 15499, 15391, 15603, 15602, 15407, 15452, 15348, 15376, 15277, 15456, 15609 — используются для основного фона. Пока ничего необычного.
Пробуем повторить процедуру для Green цвета (меняем в скрипте выше ноль на единицу: counter[pixels[i,j][1]]) и получаем следующий результат:
[7700, 7328, 7139, 6982, 6998, 6855, 6872, 6786, 26, 19, 19, 23, 32, 17, 23, 20, 30, 25, 27, 22, 4, 2, 4, 4, 3, 0, 3, 2, 1, 5, 4, 2, 3, 3, 1, 2, 4, 1, 4, 0, 0, 1, 2, 4, 0, 4, 1, 1, 15, 19, 47, 17, 12, 17, 23, 1, 27, 24, 29, 15, 17, 31, 1, 2, 2, 5, 1, 1, 2, 2, 3, 2, 3, 1, 3, 2, 1, 1, 1, 2, 3, 3, 0, 2, 0, 1, 1, 4, 1, 0, 2434, 2427, 2484, 2425, 2446, 2544, 2465, 2412, 2487, 2486, 2381, 2454, 2376, 2482, 2503, 2478, 2496, 2489, 2420, 2449, 2504, 2478, 2415, 2452, 2505, 2484, 2535, 2444, 2468, 2489, 2425, 2473, 2442, 105, 2456, 2497, 2437, 2538, 2457, 2440, 2501, 2463, 2459, 2479, 2521, 2532, 2528, 2387, 2584, 2434, 2425, 2396, 2428, 2461, 2502, 2577, 2594, 2630, 2467, 2488, 2540, 2492, 2465, 2464, 2426, 2514, 2541, 2456, 2483, 2383, 1, 4, 0, 1, 1, 1, 3, 2, 5, 3, 0, 3, 1, 3, 3, 1, 33, 59, 56, 3, 69, 158, 63, 1, 2, 1, 3, 2, 3, 2, 1, 2, 2, 0, 3, 1, 1, 1, 2, 2, 1, 2, 2, 2, 1, 5, 4, 2, 2, 2, 1, 2, 56, 79, 5, 5, 143, 140, 1, 0, 0, 1, 2, 1, 1, 3, 1, 3, 10, 10, 1, 2, 4, 3, 2, 1, 3, 3, 2, 4, 4, 5, 4, 1, 4, 7, 3, 3, 6, 4, 4, 3, 19, 12, 395, 20358]
Тут точно так же, как и для Red цвета: первые восемь значений — это градации черного цвета по центру, последнее значение — белый цвет надписи, а значения в середине используются для основного фона. Но замечаем одну странность. Среднее количество использования значений в середине — приблизительно 2400, и число 105 практически по центру явно выбивается из общей картины. Значит какой-то цвет из используемого диапазона использовался очень редко.
Выведем номер этого значения Green цвета:
for i in range(0,256):
if counter[i] == 105:
print 'res = ' + str(i)
Получаем, что значение Green-цвета равное 123 использовалось 105 раз. Попробуем перекрасить все пиксели у которых Green цвет равен 123 в черный цвет. Весь скрипт выглядит так:
from PIL import Image
image = Image.open('logo-1.png')
pixels = image.load()
counter = []
for i in range(0,256):
counter.append(0)
for i in range(image.size[0]):
for j in range(image.size[1]):
counter[pixels[i,j][1]] += 1
print counter
for i in range(0,256):
if counter[i] == 105:
print 'res = ' + str(i)
for i in range(image.size[0]):
for j in range(image.size[1]):
if pixels[i,j][1] == 123:
pixels[i,j] = (0,0,0)
img.save('result.png')
img.close()
Запускаем скрипт и в левом верхнем углу видим азбуку Морзе.
Открываем любой online-декодер азбуки Морзе и получаем флаг: 7hetw3lfth0fm4rch, который успешно сдаем после нескольких попыток. Флаг — h4ck1t{7HETW3LFTH0FM4RCH}