Как найти флаг в картинке

Работа с изображениями

В этой статье мы поговорим о способе определения метода сокрытия информации в изображениях.

Общие проверки для BMP/PNG/JMP и других

Получение exif файлов
Первое что обычно я делаю, если не знаю с чего начать — получаю exif файла. Пример:
Дана картинка: 1

Последовательность действий:

  1. Переходим на сайт http://regex.info/exif.cgi
  2. Отсылаем картинку.
  3. Замечаем текст Youarethebesthackerihaveeverseen!1337 — это и есть флаг к заданию!

2

Получение GEO-тегов

Аналогичное с EXIF решение, но отсылается файлик на сайт http://www.geoimgr.com/
В итоге получаем координаты:
3

Обычно данные действия требуются в заданиях на форенсику, например популярное задание по фотографии с телефона найти город, где находится воришка.

Архив

Изображение может оказаться архивом. Чаще всего это заметно, если картинка весит больше, чем доолжна весить при таких размерах.
Пример:
Дано изображение: 4

Последовательность действий:

  1. Переименовать оканчание в .rar/.zip/.7z или в любой другой тип архивов (перебор).
  2. Попробовать распаковать.
  3. При оканчании .rar данный файл разархивируется. Получаем файл flag.txt
  4. Открываем txt файл и получаем флаг «BESTFLAGIHAVEEVERSEEN!»
  5. Profit!

Все признаки по которым можно это заподозрить/убедиться:

  • Большой вес изображения при данном разрешении
  • В hexedit увидеть заголовки двух склеенных файлов — изображения и архива
  • Перебор оканчаний с последующим разархивированием

PNG/BMP изображения

Нам дано изображение. Попробуем по некоторым факторам определить, как нам решить этот таск.

Монотонное изображение
5

Если вам дали монотонное изображение, то чаще всего в ней находятся водяные знаки.

Водяные знаки
Чтобы узнать, есть ли на ней водяные знаки, есть несколько вариантов

Painter
Самый простой вариант — открыть изображение в Painter (или любом другом редакторе изображений).
6

Далее заливкой тыкнуть каким-нибудь контрастным цветом. В данном случае лучше всего белым.

Информация об изображении
В некоторых программах-просмотрах картинок есть статистика по цветам/пикселям. Таким образом мы можем узнать, что картинка не монотонна и на ней присутствуют пиксели разных цветов.
На этом этапе суть в том, чтобы определить следующий этап:) Тут может быть как морзянка, так и бинарный код (1001010), о чем пойдет в соответствующей последующей главе.

Другое
Есть еще утилиты, помогающие в поиске водяных знаков, такая как StegSolve. Их мы рассмотрим в соответствующей теме.

Обыкновенное изображение

Нам дано обыкновенное ничем не выделяющееся изображение.
7

Попиксельное вычитание из оригинала
Тут нам следует найти оригинал изображения.

Поиск оригинала изображения
Для этого есть несколько способов.
Сретства для поиска изображений:

  • https://images.google.com/
  • https://yandex.ru/images/

Воспользуемся google поиском:
8

Находим в картинках изображение такого же размера и скачиваем его.
Далее нам остается с помощью какой-либо библиотеки написать программу,которая пройдется по двум изображениям и выделит отличающиеся пиксели.
Лично я сделал со StegSolve, речь о котором пойдет в соседнем разделе.

Разноцветные пиксели

Пиксели двух цветов
Если у вас предоставлено изображение с пикселями двух цветов, то первое что попробуем сделать — это перевести пиксели в байты.
Приведу пример с прошедших соревнований Break In CTF 2016 — таск You Can(t) See Me.
Нам дана картинка color.png: 9

Последовательность действий:

  1. Пишем программу на Python+PIL/Pygame, которая проходит по строкам и создает свою строку f, в которой заменяет черный пиксель на 0 и красный пиксель на 1. Стоит заметить что при переходе на новую строку пикселей во время считывания, мы добавляем пробел в нашу строку f. В итоге получаем строку из 7 разных повторяющихся цифр.
  2. Идем на сайт https://www.branah.com/ascii-converter и вбиваем нашу строку в поле «Binary» и тыкаем на «Convert».
  3. Видим в поле «ASCII» текст «3xXKkFstTUpsG2IFDirE6xDrcAF8DSx4iWxd5f9IQ9T205izN8lS2MQUlsF11gT4TFXHHlLHVHprNTtrh6lURfdUW7Lpuzgu1VKzwb1bg1oq6Ae3GnykkLZZsnze3HVLxHlfCYtzyrcV2Oxp0Gb0Z2ELphR4Oxo7TyvHCuWKWlN8t8KIfHysZK7jBNPu6wRVEUPIwVra.»
  4. Флаг найден!

взято с сайта http://itsecwiki.org/

results matching ««

    No results matching ««

    Стеганография — это метод и наука о сокрытии информации. Так называемое сокрытие информации означает предотвращение того, чтобы кто-либо, кроме предполагаемого получателя, узнал о событии передачи или содержании информации. Стеганография на английском языке называется стеганографией, происходит от Steganographia, книги Тритмиуса о криптографии и стеганографии. Название книги происходит от греческого языка и означает «секретное письмо секретаря».

    Среди вопросов CTF вопросы стеганографии изображений являются частью разного, и вопросы относительно простые. В этой статье примерно разобраны стандартные процедуры стеганографии изображений в соревновании CTF. Если вы не видите проблему, вы можете попробовать одну за другой в следующем порядке:

    1. Просмотрите основную информацию об изображении (сложность соответствующей темы: низкая)

    Для этого типа вопросов вы можете напрямую получить ФЛАГ, просмотрев основную информацию о картинке. Основные методы следующие:

    A) Щелкните правой кнопкой мыши, чтобы просмотреть свойства изображения, и проверьте, есть ли ФЛАГ во введении и примечаниях к изображению;

    Б) Откройте изображение с помощью инструмента редактирования, такого как блокнот, блокнот +, winhex, и проверьте, содержит ли он FLAG;

    2. Многослойные файлы (соответствует сложности заголовка: средний)

    Наверное, все игроки CTF слышали об артефакте-стегсольве. Используйте его, чтобы открывать картинки. Программа также имеет две цели:

    A) Продолжайте нажимать стрелку вправо (или стрелку влево), возможно, появится QR-код;

    B) Извлечение низкоуровневой информации, которая включает в себя большую категорию стеганографии изображений, стеганографию lsb, которая обычно скрыта в младших битах 0, 1 и 2. Отметьте Analyze → Data Extract в параметрах программных функций и отлаживайте одну за другой.

    3. Составные документы (по сложности темы: средняя)

    В соревнованиях CTF часто встречается, что файлы png объединяются с другими файлами, например помещается сжатый пакет, файл txt или добавляется другое изображение после изображения. Конкретные методы работы следующие:

    copy /b a.jpg+b.zip c.jpg

    copy /b a.jpg+b.txt c.jpg

    copy /b a.jpg+b.jpg c.jpg

    Идеи решения проблем: обычно такой вид изображения относительно большой, вы можете изменить суффикс изображения на zip или rar и просто разархивировать его. Вы также можете использовать winhex, чтобы найти начальные и конечные знаки изображения и разделить их вручную, или использовать инструменты binwalk или, прежде всего, под kali, чтобы разделить их;

    Примечание. Если вы скроете изображение с более сложным изображением, некоторые из них удалят заголовок второго изображения, а затем объединят два изображения вместе, так что эти инструменты извлечения будут бесполезны. В настоящее время вам нужно быть немного осторожнее и использовать winhex. Найдите конец первого изображения, затем добавьте заголовок второго изображения, а затем выполните операцию разделения.

    4. Измените высоту изображения (в зависимости от сложности названия: средний).

    В соревновании CTF вы можете использовать шестнадцатеричный инструмент редактирования, чтобы изменить высоту изображения, чтобы отображалась только часть изображения, а нижняя часть была скрыта. Что ж, это хороший способ скрыть вещи!

    Если ни один из вышеперечисленных методов не может получить ФЛАГ, а соотношение длины и ширины изображения странное, вы можете попробовать изменить размер изображения. Ниже описано, как найти флаги ширины и высоты изображения:

    A) Для файлов png вторая строка и шестой столбец — это позиция по высоте, просто измените эту позицию;

    B) Для изображений в других форматах вы можете сначала посмотреть атрибуты изображений, получить значения ширины и высоты, преобразовать их в шестнадцатеричные числа и выполнить поиск шестнадцатеричных значений, чтобы найти бит флага;

    В этой статье перечислены только несколько процедур стеганографии изображений CTF, с которыми в настоящее время сталкиваются блоггеры, добро пожаловать!

    Время на прочтение
    5 мин

    Количество просмотров 30K

    На хакерских конкурсах и играх CTF (Capture The Flag) иногда попадаются задачки на стеганографию: вам дают картинку, в которой нужно найти скрытое сообщение. Наверное, самый простой способ спрятать текст в картинке PNG — прописать его в одном из цветовых каналов или в альфа-канале (канал прозрачности). Для выявления подобных «закладок» есть специальные инструменты, такие как stegsolve, pngcheck и stegdetect, иногда конкурсантам приходится вручную повозиться с фильтрами в GIMP или Photoshop.

    Однако прогресс не стоит на месте — и в последнее время всё чаще используются другие способы скрытия данных, например, PNG-наполнение. Посмотрим, как это делается.

    Начнём с небольшого теоретического введения по «невидимым» частям PNG.

    Альфа-канал

    На экране компьютера при отображении картинки цвета создаются сочетанием красного, зелёного и синего компонентов. Эти три цветовые плоскости называются каналами. Обычно они записываются как RGB.

    Кроме этих трёх каналов, в PNG может быть ещё четвёртый канал, называемый альфа (обозначается буквой А) для определения уровня прозрачности. Полученное изображение RGBA определяет видимые цвета и степень прозрачности.

    В большинстве графических форматов альфа-канал является значением от 0% до 100% (или от 0 до 255 в байтах). Значение 0% (чёрный) обозначает место на изображении, где должна быть полная прозрачность — тут значение RGB игнорируется, и полностью виден фон под картинкой. Значение альфа-канала 100% (белый) означает, что каналы RGB полностью непрозрачны. Промежуточные значения определяют, насколько нужно смешать фон со значением RGB-пикселя.


    Альфа-градиент в PNG

    Значения альфа-градиента обычно используются для наложения изображения на другое изображение или на веб-страницу. Альфа-градиенты есть в PNG, WebP, ICO, ICN и других растровых форматах. Формат GIF поддерживает только логическое значение (пиксель либо прозрачен, либо нет).

    Альфа-канал — только один из вариантов для размещения скрытого текста. Переходим к PNG-наполнению (padding) для прямой записи данных в бинарный файл.

    PNG-наполнение по столбцам

    Формат PNG достаточно прост. Каждый файл начинается с восьми стандартных байт подписи, вот её десятичные значения: 137 80 78 71 13 10 26 10. Первый байт выбран за пределами ASCII, чтобы никакой редактор случайно не принял изображение за текстовый файл. Следующие три байта соответствуют буквам P, N, G. Затем разрыв строки DOS (13 10), маркер DOS окончания файла (26), чтобы программа type не выдавала весь бинарный мусор, и маркер Unix новой строки.

    После заголовка начинаются блоки данных (chunks) со стандартной структурой. Сначала идёт блок IHDR с указанием ширины и высоты изображения, цветового пространства, количества бит на пиксель, методом сжатия, методом фильтрации и указанием наличия/отсутствия чересстрочного кодирования. Для ширины и высоты выделено по четыре байта, для остальных параметров — по одному байту.

    Затем следует опциональный блок tEXt с текстовыми метаданными, например, с названием программы, которая сгенерировала данный файл PNG. В текстовые блоки можно записывать текстовую информацию в открытом виде.

    За IHDR и tEXt следуют блоки IDAT со сжатыми значениями RGB или RGBA для растровых пикселей. При рендеринге PNG обрабатывается IHDR, выделяется буфер в памяти для изображения, данные извлекаются из сжатого формата и попиксельно записываются в буфер. Файл PNG завершается блоком IEND.

    В конце каждого блока записана контрольная сумма CRC для этого блока, которая вычисляется по стандартному алгоритму.

    Обычно изображения PNG содержат 8 или 16 бит информации на каждый канал RGB или RGBA, то есть выходит от трёх до восьми байт на пиксель. В таком формате все байты заняты полезной информацией о цвете и прозрачности, так что в конце каждой строки графического изображения у нас нет места для записи произвольных данных.

    Но для задач стеганографии нужно знать, что PNG поддерживает и меньшую глубину цвета: 1 бит (2 цвета), 2 бита (4 цвета) и 4 бита (16 цветов). В такой ситуации получается, что в одном байте хранится информация о нескольких пикселях. Вот здесь и появляется теоретическая возможность для «горизонтального» наполнения PNG посторонними данными. Если ширина картинки в пикселях не кратна восьми, то в последнем байте строки остаётся неиспользуемые биты, которые все вместе формируют целый неиспользуемый «столбец пикселей».

    В случае 1-битного изображения в конце каждой строки может остаться до 7 свободных бит, которые не будут обработаны парсером. В случае 2-битного изображения в последнем байте остаётся до 3 свободных бит. Онлайновый инструмент FotoForensics находит такие неиспользуемые «столбцы пикселей» в изображениях PNG.

    Впрочем, PNG-картинки с малой глубиной цвета встречаются очень редко, поэтому и данный метод стеганографии можно считать экзотикой. Если вам попалось PNG-изображение с 2, 4 или 16 цветами, один этот факт уже вызывает подозрение и может инициировать проверку PNG-наполнения по столбцам.

    Совсем другое дело — PNG-наполнение за границами картинки. Это более простой метод стеганографии, который позволяет спрятать в изображении гораздо больше информации.

    PNG-наполнение за границами картинки

    PNG-наполнение за границами картинки (post-pixel padding) часто используется в различных играх, головоломках и конкурсах, не только хакерских. Вот как работает этот метод:

    1. Берём изображение PNG (с любой глубиной цвета).

    2. Вставляем секретную информацию в нижнюю часть картинки.

    3. Сохраняем PNG, не используя чересстрочное кодирование.
    4. Открываем файл в hex-редакторе.
    5. Находим блок IHDR. Он располагается в начале файла после восьми обязательных байт подписи и помечен как IHDR.

    6. Первые четыре байта после метки IHDR — это ширина файла, следующие четыре байта — высота. Уменьшаем это значение c 00 00 01 9D (413 пикселей), например, до 00 00 01 7E (382 пикселя).

    7. Не забудьте пересчитать четыре байта CRC (в формате PNG вычисляется значение CRC для каждого блока данных, в том числе для IHDR), которые записаны в конце блока. Если вы не можете посчитать CRC самостоятельно, посмотрите это значение в любом PNG-файле с аналогичными значениями блока IHDR.

      Получаем результат.

    Обратите внимание, что секретные данные остались в нижней части изображения. Размер файла не изменился: 335 906 байт. Просто парсер теперь не обрабатывает эти пиксели — и нижняя часть картинки не демонстрируется на экране.

    Несложно догадаться, что в «секретной» части картинки можно спрятать не только текстовую надпись, но и произвольные данные. Например, мы можем записать туда запароленный архив RAR. Картинка с секретным посланием может быть опубликована на Habrastorage или любом другом общедоступном хостинге. Послание получит только тот человек, с которым вы заранее договорились о способе передачи информации и согласовали пароль. Таким способом вредоносные программы могут передавать полезную нагрузку через Хабр и другие общедоступные хостинги.


    На правах рекламы

    VDS для размещения сайтов — это про наши эпичные! Все серверы «из коробки» защищены от DDoS-атак, автоматическая установка удобной панели управления VestaCP. Лучше один раз попробовать ;)

    My approach generalizes the problem and in fact looks for a red and white strips pattern (horizontal or vertical) near to a blue region. Therefore it works for scenes that only the American flag has this pattern.

    My approach is developed in Java and uses Marvin Framework.

    Algorithm:

    1. Color filter for keeping only pixels with the same color of American flag.
    2. Find horizontal red and white strips pattern
    3. Find vertical red and white strips pattern
    4. Remove patterns with small area (noise)
    5. Check whether this pattern is surrounded by a blue region
    6. Segment the area.

    Input:

    enter image description here

    Color Filter:

    enter image description here

    Flag:

    enter image description here

    More interesting is the performance in the case there are many flags.

    Input:

    enter image description here

    Color Filter:

    enter image description here

    Pattern Matching:

    enter image description here

    Flag:

    enter image description here

    Source Code:

    import static marvin.MarvinPluginCollection.*;
    
    public class AmericanFlag {
    
        public AmericanFlag(){
            process("./res/flags/", "flag_0", Color.yellow);
            process("./res/flags/", "flag_1", Color.yellow);
            process("./res/flags/", "flag_2", Color.yellow);
            process("./res/flags/", "flag_3", Color.yellow);
            process("./res/flags/", "flag_4", Color.blue);
        }
    
        private void process(String dir, String fileName, Color color){
            MarvinImage originalImage = MarvinImageIO.loadImage(dir+fileName+".jpg");
            MarvinImage image = originalImage.clone();
            colorFilter(image);
            MarvinImageIO.saveImage(image, dir+fileName+"_color.png");
    
            MarvinImage output = new MarvinImage(image.getWidth(), image.getHeight());
            output.clear(0xFFFFFFFF);
            findStripsH(image, output);
            findStripsV(image, output);
            MarvinImageIO.saveImage(output, dir+fileName+"_1.png");
    
            MarvinImage bin = MarvinColorModelConverter.rgbToBinary(output, 127);
            morphologicalErosion(bin.clone(), bin, MarvinMath.getTrueMatrix(5, 5));
            morphologicalDilation(bin.clone(), bin, MarvinMath.getTrueMatrix(15, 15));
            MarvinImageIO.saveImage(bin, dir+fileName+"_2.png");
    
            int[] centroid = getCentroid(bin);
            image.fillRect(centroid[0], centroid[1], 30, 30, Color.yellow);
    
            int area = getMass(bin);
            boolean blueNeighbors = hasBlueNeighbors(image, bin, centroid[0], centroid[1], area);
    
            if(blueNeighbors){
                int[] seg = getSegment(bin);
                for(int i=0; i<4; i++){
                    originalImage.drawRect(seg[0]+i, seg[1]+i, seg[2]-seg[0], seg[3]-seg[1], color);
                }
                MarvinImageIO.saveImage(originalImage, dir+fileName+"_final.png");
            }
        }
    
        private boolean hasBlueNeighbors(MarvinImage image, MarvinImage bin, int centerX, int centerY, int area){
            int totalBlue=0;
            int r,g,b;
            int maxDistance =  (int)(Math.sqrt(area)*1.2);
            for(int y=0; y<image.getHeight(); y++){
                for(int x=0; x<image.getWidth(); x++){
                    r = image.getIntComponent0(x, y);
                    g = image.getIntComponent1(x, y);
                    b = image.getIntComponent2(x, y);
    
                    if(
                        (b == 255 && r == 0 && g == 0) &&
                        (MarvinMath.euclideanDistance(x, y, centerX, centerY) < maxDistance)
                    ){
                        totalBlue++;
                        bin.setBinaryColor(x, y, true);
                    }
                }
            }
    
            if(totalBlue > area/5){
                return true;
            }
            return false;
        }
    
        private int[] getCentroid(MarvinImage bin){
            long totalX=0, totalY=0, totalPixels=0;
            for(int y=0; y<bin.getHeight(); y++){
                for(int x=0; x<bin.getWidth(); x++){
    
                    if(bin.getBinaryColor(x, y)){
                        totalX += x;
                        totalY += y;
                        totalPixels++;
                    }
                }
            }
    
            totalPixels = Math.max(1, totalPixels);
            return new int[]{(int)(totalX/totalPixels), (int)(totalY/totalPixels)};
        }
    
        private int getMass(MarvinImage bin){
            int totalPixels=0;
            for(int y=0; y<bin.getHeight(); y++){
                for(int x=0; x<bin.getWidth(); x++){
                    if(bin.getBinaryColor(x, y)){
                        totalPixels++;
                    }
                }
            }
    
            return totalPixels;
        }
    
        private int[] getSegment(MarvinImage bin){
            int x1=-1, x2=-1, y1=-1, y2=-1;
            for(int y=0; y<bin.getHeight(); y++){
                for(int x=0; x<bin.getWidth(); x++){
                    if(bin.getBinaryColor(x, y)){
    
                        if(x1 == -1 || x < x1){ x1 = x; }
                        if(x2 == -1 || x > x2){ x2 = x; }
                        if(y1 == -1 || y < y1){ y1 = y; }
                        if(y2 == -1 || y > y2){ y2 = y; }
                    }
                }
            }
            return new int[]{x1,y1,x2,y2};
        }
    
        private void findStripsH(MarvinImage imageIn, MarvinImage imageOut){
    
            int strips=0;
            int totalPixels=0;
            int r,g,b;
            int patternStart;
            boolean cR=true;
            int patternLength = -1;
            for(int y=0; y<imageIn.getHeight(); y++){
                patternStart = -1;
                strips = 0;
                patternLength=-1;
                for(int x=0; x<imageIn.getWidth(); x++){
                    r = imageIn.getIntComponent0(x, y);
                    g = imageIn.getIntComponent1(x, y);
                    b = imageIn.getIntComponent2(x, y);
    
                    if(cR){
                        if(r == 255 && g == 0 && b == 0){
                            if(patternStart == -1){ patternStart = x;}
                            totalPixels++;
                        } else{
                            if(patternLength == -1){
                                if(totalPixels >=3 && totalPixels <= 100){
                                    patternLength = (int)(totalPixels);
                                } else{
                                    totalPixels=0; patternStart=-1; strips=0; patternLength=-1;
                                }
                            } else{
                                if(totalPixels >= Math.max(patternLength*0.5,3) && totalPixels <= patternLength * 2){
                                    strips++;
                                    totalPixels=1;
                                    cR = false;
                                } else{
                                    totalPixels=0; patternStart=-1; strips=0; patternLength=-1;
                                }
                            }
                        }
                    }
                    else{
                        if(r == 255 && g == 255 && b == 255){
                            totalPixels++;
                        } else{
                            if(totalPixels >= Math.max(patternLength*0.5,3) && totalPixels <= patternLength * 2){
                                strips++;
                                totalPixels=1;
                                cR = true;
                            } else{
                                totalPixels=0; patternStart=-1; strips=0; patternLength=-1; cR=true;
                            }
                        }
                    }
    
    
                    if(strips >= 4){
                        imageOut.fillRect(patternStart, y, x-patternStart, 2, Color.black);
                        totalPixels=0; patternStart=-1; strips=0; patternLength=-1; cR=true;
                    }
                }
            }
        }
    
        private void findStripsV(MarvinImage imageIn, MarvinImage imageOut){
    
            int strips=0;
            int totalPixels=0;
            int r,g,b;
            int patternStart;
            boolean cR=true;
            int patternLength = -1;
            for(int x=0; x<imageIn.getWidth(); x++){
                patternStart = -1;
                strips = 0;
                patternLength=-1;
                for(int y=0; y<imageIn.getHeight(); y++){
                    r = imageIn.getIntComponent0(x, y);
                    g = imageIn.getIntComponent1(x, y);
                    b = imageIn.getIntComponent2(x, y);
    
                    if(cR){
                        if(r == 255 && g == 0 && b == 0){
                            if(patternStart == -1){ patternStart = y;}
                            totalPixels++;
                        } else{
                            if(patternLength == -1){
                                if(totalPixels >=3 && totalPixels <= 100){
                                    patternLength = (int)(totalPixels);
                                } else{
                                    totalPixels=0; patternStart=-1; strips=0; patternLength=-1;
                                }
                            } else{
                                if(totalPixels >= Math.max(patternLength*0.5,3) && totalPixels <= patternLength * 2){
                                    strips++;
                                    totalPixels=1;
                                    cR = false;
                                } else{
                                    totalPixels=0; patternStart=-1; strips=0; patternLength=-1;
                                }
                            }
                        }
    
    //                  if(maxL != -1 && totalPixels > maxL){
    //                      totalPixels=0; patternStart=-1; strips=0; maxL=-1;
    //                  }
                    }
                    else{
                        if(r == 255 && g == 255 && b == 255){
                            totalPixels++;
                        } else{
                            if(totalPixels >= Math.max(patternLength*0.5,3) && totalPixels <= patternLength * 2){
                                strips++;
                                totalPixels=1;
                                cR = true;
                            } else{
                                totalPixels=0; patternStart=-1; strips=0; patternLength=-1; cR=true;
                            }
                        }
    
    //                  if(maxL != -1 &&  totalPixels > maxL){
    //                      totalPixels=0; patternStart=-1; strips=0; maxL=-1;
    //                      cR=true;
    //                  }
                    }
    
    
                    if(strips >= 4){
                        imageOut.fillRect(x, patternStart, 2, y-patternStart, Color.black);
                        totalPixels=0; patternStart=-1; strips=0; patternLength=-1; cR=true;
                    }
                }
            }
        }
    
        private void colorFilter(MarvinImage image){
    
            int r,g,b;
            boolean isR, isB;
            for(int y=0; y<image.getHeight(); y++){
                for(int x=0; x<image.getWidth(); x++){
                    r = image.getIntComponent0(x, y);
                    g = image.getIntComponent1(x, y);
                    b = image.getIntComponent2(x, y);
    
                    isR = (r > 120 && r > g * 1.3 && r > b * 1.3);
                    isB = (b > 30 && b < 150 && b > r * 1.3 && b > g * 1.3);
    
                    if(isR){
                        image.setIntColor(x, y, 255,0,0);
                    } else if(isB){
                        image.setIntColor(x, y, 0,0,255);
                    } else{
                        image.setIntColor(x, y, 255,255,255);
                    }
                }
            }
        }
    
        public static void main(String[] args) {
            new AmericanFlag();
        }
    }
    

    Other Results:

    enter image description here

    enter image description here

    enter image description here

    В этой статье мы поговорим о способе определения метода сокрытия информации в изображениях.

    Содержание

    • 1 Общие проверки для BMP/PNG/JMP и других
      • 1.1 Получение exif файлов
      • 1.2 Получение GEO-тегов
      • 1.3 Приписанный в конец файла текст
      • 1.4 Архив
    • 2 PNG/BMP изображения
      • 2.1 Монотонное изображение
        • 2.1.1 Водяные знаки
          • 2.1.1.1 Painter
          • 2.1.1.2 Информация об изображении
          • 2.1.1.3 Другое
      • 2.2 Обыкновенное изображение
        • 2.2.1 Попиксельное вычитание из оригинала
          • 2.2.1.1 Поиск оригинала изображения
          • 2.2.1.2 Равномерно распределенные пиксели
          • 2.2.1.3 Hallucinate
          • 2.2.1.4 JHide
          • 2.2.1.5 OpenPuff
        • 2.2.2 Чередующиеся пиксели двух изображений
        • 2.2.3 Anubis
        • 2.2.4 DeEgger Embedder
        • 2.2.5 Вдобавок присутствует файл .sig
      • 2.3 Разноцветные пиксели
        • 2.3.1 Пиксели двух цветов
        • 2.3.2 Пиксели восьми разных цветов
        • 2.3.3 Множество разных цветов
          • 2.3.3.1 ASCII->RGB
          • 2.3.3.2 PIET
      • 2.4 Обрезанное изображение
    • 3 Утилиты
      • 3.1 tweakpng
      • 3.2 StegSolver
      • 3.3 CheckPNG
    • 4 Райтапы

    Общие проверки для BMP/PNG/JMP и других

    Получение exif файлов

    Первое что обычно я делаю, если не знаю с чего начать — получаю exif файла.
    Пример:

    Дана картинка:
    EXIF.jpg

    Последовательность действий:

        1. Переходим на сайт http://regex.info/exif.cgi
        2. Отсылаем картинку.
        3. Замечаем текст Youarethebesthackerihaveeverseen!1337 - это и есть флаг к заданию!
    

    Getexif.png

    Получение GEO-тегов

    Аналогичное с EXIF решение, но отсылается файлик на сайт http://www.geoimgr.com/

    В итоге получаем координаты:

    Geotags.png

    Обычно данные действия требуются в заданиях на форенсику, например популярное задание по фотографии с телефона найти город, где находится воришка.

    Приписанный в конец файла текст

    Для определения воспользуемся текстовым редактором или hex редактором.

    Пример строки в конце файла:

    TEXT IN THE END

    Архив

    Изображение может оказаться архивом. Чаще всего это заметно, если картинка весит больше, чем доолжна весить при таких размерах.

    Пример:

    Дано изображение: RARImage.jpg

    Последовательность действий:

        1. Переименовать оканчание в .rar/.zip/.7z или в любой другой тип архивов (перебор).
        2. Попробовать распаковать. 
        3. При оканчании .rar данный файл разархивируется. Получаем файл flag.txt
        4. Открываем txt файл и получаем флаг "BESTFLAGIHAVEEVERSEEN!"
        5. Profit!
    

    Все признаки по которым можно это заподозрить/убедиться:

    • Большой вес изображения при данном разрешении
    • В hexedit увидеть заголовки двух склеенных файлов — изображения и архива
    • Перебор оканчаний с последующим разархивированием

    PNG/BMP изображения

    Нам дано изображение. Попробуем по некоторым факторам определить, как нам решить этот таск.

    Монотонное изображение

    WaterStego.png

    Если вам дали монотонное изображение, то чаще всего в ней находятся водяные знаки.

    Водяные знаки

    Чтобы узнать, есть ли на ней водяные знаки, есть несколько вариантов

    Painter

    Самый простой вариант — открыть изображение в Painter (или любом другом редакторе изображений).

    Решение с Painter

    Далее заливкой тыкнуть каким-нибудь контрастным цветом. В данном случае лучше всего белым.

    WaterSolved.png

    Информация об изображении

    В некоторых программах-просмотрах картинок есть статистика по цветам/пикселям.

    Таким образом мы можем узнать, что картинка не монотонна и на ней присутствуют пиксели разных цветов.

    (Картинка)

    На этом этапе суть в том, чтобы определить следующий этап:) Тут может быть как морзянка, так и бинарный код (1001010), о чем пойдет в соответствующей последующей главе.

    Другое

    Есть еще утилиты, помогающие в поиске водяных знаков, такая как StegSolve. Их мы рассмотрим в соответствующей теме.

    Обыкновенное изображение

    Нам дано обыкновенное ничем не выделяющееся изображение.
    StegoXORimage.png

    Попиксельное вычитание из оригинала

    Тут нам следует найти оригинал изображения.

    Поиск оригинала изображения

    Для этого есть несколько способов.

    Сретства для поиска изображений:

        https://images.google.com/
        https://yandex.ru/images/
    

    Воспользуемся google поиском:

    SearchStegoOriginal.png

    Находим в картинках изображение такого же размера и скачиваем его.

    Далее нам остается с помощью какой-либо библиотеки написать программу,которая пройдется по двум изображениям и выделит отличающиеся пиксели.

    Лично я сделал со StegSolve, речь о котором пойдет в конце страницы.

    Рассмотрим случаи исхода попиксельного вычитания.

    Равномерно распределенные пиксели
    Hallucinate

    Если при XOR оригинала и исходного изображений вы видите ярко выражены равномерно распределенные измененные пиксели, значит используется утилита Hallucinate.

    http://sourceforge.net/projects/hallucinate/

    JHide

    Если при XOR оригинала и исходного изображений вы видите еле виднеющиеся пиксели синего цвета, то используется утилита JHide.

    https://sourceforge.net/projects/jhideapp/

    OpenPuff

    Отличается от JHide только тем, что задействует большее количество байт.

    http://download.cnet.com/windows/openpuff-team/3260-20_4-10146585-1.html

    Чередующиеся пиксели двух изображений

    Чтобы это определить, нам требуется воспользоваться программой StegSolve, о которой будет сказано в отдельном пункте.

    Если перед вами обыкновенное изображение (например пейзаж) и у него у какого то из цветных фильтров шум, то это означает,
    что перед вами изображение в которое встроено еще одно изображение путем замены каждого n-ого пикселя пикселем изображения-флага.

    Anubis

    Если в файле присутствуют строки limiter1, limiter2, inserted length begins, то используется стеганографическая утилита Anubis

    https://sourceforge.net/projects/anubisstegano/files/

    DeEgger Embedder

    Если в файле используется hex-строка

        24 23 26 29 2A 40 26 28 23 5E 2A 00 D1 8B 87 8B FF
    

    то используется утилита DeEgger Embedder

    http://www.softpedia.com/get/Security/Encrypting/DeEgger-Embedder.shtml#download

    Вдобавок присутствует файл .sig

    Если у вас есть файл .sig, то используется утилита OpenStego.

    http://www.openstego.com/

    Разноцветные пиксели

    Пиксели двух цветов

    Если у вас предоставлено изображение с пикселями двух цветов, то первое что попробуем сделать — это перевести пиксели в байты.

    Приведу пример с прошедших соревнований Break In CTF 2016 — таск You Can(t) See Me.

    Нам дана картинка color.png:
    Color.png

    Последовательность действий:
         1. Пишем программу на Python+PIL/Pygame, которая проходит по строкам и создает свою строку f, в которой заменяет черный пиксель
         на 0 и красный пиксель на 1. Стоит заметить что при переходе на новую строку пикселей во время считывания, мы добавляем пробел в
         нашу строку f. В итоге получаем строку из 7 разных повторяющихся цифр.
         2. Идем на сайт https://www.branah.com/ascii-converter и вбиваем нашу строку в поле "Binary" и тыкаем на "Convert".
         Видим в поле "ASCII" текст 
         "3xXKkFstTUpsG2IFDirE6xDrcAF8DSx4iWxd5f9IQ9T205izN8lS2MQUlsF11gT4TFXHHlLHVHprNTtrh6lURfdUW7Lpuzgu1VKzwb1bg1oq6Ae3GnykkLZZsnze3HVLxHlfCYtzyrcV2Oxp0Gb0Z2ELphR4Oxo7TyvHCuWKWlN8t8KIfHysZK7jBNPu6wRVEUPIwVra."
         4. Флаг найден!
    
    

    Пиксели восьми разных цветов

    В случае с 8 пикселями разных цветов сразу же вспоминается Brainloller (http://esolangs.org/wiki/Brainloller).

    Может быть не только brainloller в чистом виде — например сделать замену пикселям.

    Пример изображения brainloller:

    Brainloller.png

    Последовательность действий:

        1. Скачиваем интерпретатор по ссылке - https://github.com/hhhonzik/python-brainfuck
        2. Запускаем: python3 brainx.py -l Brainloller.png
        3. Видим HelloWorld. Profit!
    

    Множество разных цветов

    ASCII->RGB

    Если у вас параметры цветов колеблются между 50 и 150 (включая 32) — вероятнее всего каждый из параметров цвета (red, green и blue) был заменен ASCII-кодами символов.

    Пример изображения:

    Many colors.png

    Последовательность действий:

        1. Пишем программу, которая проходится по всем пикселям
        2. Переводим все параметры пикселей Red, Green и Blue в ASCII символы с такими же номерами.
        3. Обьединяем все символы в строку
    

    Важно! В некоторых CTF символы пикселей обьединяются не по строкам, а по столбцам!

    PIET

    Так же эта картинка может являться программой на языке PIET.

    Пример изображения (NeoQuest 2015):

    Piet.jpg

    Обрезанное изображение

    Если перед вами изображение, которое вероятнее всего было обрезано, как например это
    (таск с training.hackerdom.ru):

    Keepcalm.png

    То значит кто то принудительно изменил размер изображения.

    Единственный способ, которым можно восстановить изображение, это подбирать изначальные размеры.

    Чаще всего изменяется именно высота (иначе могут быть повреждения изображения).

    Поэтому начнем подбирать высоту изображения.

    Для этого откроем его в программе SynalyzeIt (или в hexinator) и включим парсинг содержимого:

    SynalyzeIt PNG.png

    И меняем значение высоты (height) в правой колонке.

    Не забываем, что нам требуется восстанавливать чексумму для корректного открытия.

    Поэтому после каждого изменения запускаем программу pngcsum (http://schaik.com/png/pngcsum.html):

    Pngcsum.png

    Лично я подбираю бинарным поиском — если у меня слишком много захвачено по высоте, то изображение не будет показано.

    В итоге был найден точный размер изображения 600×728:

    И непосредственно ответ:

    Keepcalm1.png

    Утилиты

    tweakpng

    позже

    StegSolver

    CheckPNG

    Райтапы

    http://countersite.org/articles/steganography/71-qrcode-qctf-2016.html — QRcode QCTF 2016

    https://0x90r00t.com/2015/09/07/mma-2015-stegano-nagoya-castle-write-up/ — MMA 2015 Nagoya Castle

    http://blog.w3challs.com/index.php?post/2012/10/13/HackYou-CTF-Stego100%2C-Stego200%2C-Stego300-Writeups — go through the tunnel

    http://blog.squareroots.de/en/2012/11/polictf-write-up-forensics-200/ — PoliCTF Write-Up Forensics 200

    http://countersite.org/articles/steganography/98-curses-and-hexes-stego-tjctf-2016.html — Curses and Hexes TJCTF 2016

    http://countersite.org/articles/steganography/97-grey-shades-tjctf2016.html — Basic Images TJCTF2016

    Понравилась статья? Поделить с друзьями:
  • Кошка поцарапала сапоги как исправить
  • Как найти расстояние между глазами
  • Как найти работу ракам
  • Как через тотал командер найти дубликаты файлов
  • Как найти чудо кнопку