вторник, 19 ноября 2013 г.

Проверка корректности формата

За неделю набор инструментов для выявления стеганографии значительно расширился. Пока я решил сконцентрироваться на стеганографии JPEG, а потом перейти к другим форматам изображений.
Первое что я понял - старый SDI - интерфейс не годится для эффективной работы стегоаналитика. Вдохновившись фотошопом перерисовал интерфейс - там появилось два новых окна: окно, где находится сама анализируемая картинка, и окно с информацией об изображении.
Информации пока не очень много: ширина, высота, да формат файла (пока поддерживается только jpeg), но как говорится, лиха беда начало! Помимо этого в рамках аттракциона неслыханной щедрости добавлено: поканальная визуальная атака на стеганографию и анализ формата файла jpeg, исключающий скрытное дописывание стеганографии в конец файла. А теперь обо всем поподробнее...

Новый интерфейс программы stect в MDI


Размышлял я тут о повышении эффективности визуальной атаки.
Известно, что человеческий глаз очень чувствителен к даже незначительным изменениям яркости пиксела и гораздо более терпим к изменениям цвета - это лежит в основе преобразования изображения в формат JPEG -  цвет загрубляется, и из каналов цветности удаляется лишняя информация. Этот же эффект можно использовать при модификации бит - изменения  в цветовых канала менее заметны, чем в яркостном!
Чтобы работать с отдельными каналами изображения нужно воспользоваться закладкой "Каналы". Можно выбрать один из трех каналов (в случае 24-х битной глубины цвета) и просмотреть его. Если выбрать элемент "все" - покажется исходное изображение.
По-канальный анализ изображения на стеганографии. Пока подключены все каналы в RGB

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

Как известно, существует много различных цветовых пространств, которые используются для кодировки цвета пиксела. Я пока поддерживаю два из них: RGB - стандарт для bitmap изображений и YCbCr родное цветовое пространство для JPEG.
Выделение отдельных каналов цветности в пространстве RGB реализуется на Qt очень просто. При помощи метода QImage::pixel () получаем цвет пиксела в виде класса QRgb который задан в интересующем цветовом пространстве. Выделяем из общей цветности интересующий нас канал: для этого используются методы qRed (), qGreen () и qBlue (). Теперь осталось только модифицировать цвет пиксела, оставив там составляющую цвета только для одного канала. Делается это при помощи метода  QImage::setPixel ().Если нужно, чтобы изображение красного канала были красноватыми, синего - синим, а зеленого - зеленым можно воспользоваться моим примером приведенным ниже.
В этом примере сначала открывается графический файл, далее в цикле идет обход каждого пиксела, после чего его цвет модифицируется. В нашем случае у него обнуляются значения цветности синего и красного каналов.
Если нужно, чтобы канал был черно-белой (как в фотошопе) нужно написать:
 attr1->setPixel(i,j,  qRgb(qRed(p), qRed(p)qRed(p)));

После выполнения кода примера в классе QImage attr1 будет только красный канал изображения.
    QImage *attr1 = new QImage("image_stego.jpg");

    for(int j=0;jheight();j++)
        for(int i=0;iwidth();i++){
            QRgb p = attr1->pixel(i,j);
            attr1->setPixel(i,j,  qRgb(qRed(p), 0, 0));
        }
При построении каналов цветового пространства  YCbCr я использую известные формулы перевода из  пространства RGB в YCbCr. К сожалению библиотеки  Qt при открытии jpeg файла декодируют его в bitmap изображение и переводит его в пространство RGB, так что говорить о полной идентичности каналов в открываемом JPEG файле и полученной в результате преобразований нельзя.
Тем не менее сегодня я поработаю с тем что есть, а потом подумаю о более точных преобразованиях. А пока пойдем по тому же пути, что и кодек jpeg перед началом сжатия изображения. Методика преобразования RGB -> YCbCr известна и отражена в той же википедии. Засучим рукава и модифицируем предыдущий пример таким образом, чтобы на выходе в QImage attr1 лежал канал яркости.
Возьмем формулу преобразования между различными цветовыми пространствами  и честно посчитаем значение яркости каждого пиксела.

Чтобы построить канал яркости можно воспользоваться ниже:

    QImage *attr1 =  new QImage(image->toImage());

    for(int j=0;jheight();j++)
        for(int i=0;iwidth();i++){
            QRgb p = attr1->pixel(i,j);
            uint pixel = 0.299*qRed(p) + 0.578 *qGreen(p) +0.114 * qBlue(p);
            attr1->setPixel(i,j, qRgb(pixel, pixel, pixel));
        }

Построение двух других каналов осуществляется аналогично, различаются лишь формулы. Приведу их:
Канал  Cb
uint pixel = 128 - 0.168736*qRed(p) - 0.331264 *qGreen(p) +0.5 * qBlue(p);

Канал Cr
uint pixel = 128 + 0.5*qRed(p) - 0.418688 *qGreen(p) - 0.081312 * qBlue(p);

Все это добавлено в программу stect. Можно выбрать соответствующее цветовое пространство, канал и он будет отображен в рабочей области.
Один из каналов в цветовом пространстве YCbCr

Выбрали соответствующий канал - нажмите на значок глаза, тогда визуальную атаку на стеганографию, о которой я уже писал можно провести поканально!
например, если ее провести на файле image_stego.jpg, пораженный программой jsteg (тестовый файл можно скачать вместе с исходниками), то становится заметно что отдельные каналы пострадали сильно, другие не пострадали совсем.
Визуальная атака на стеганографию осуществляется по каналу яркости

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

Однако перейдем от методики замены наименее значащего бита к более приземленным скучным и простым вещам. К сожалению разработчики программ для стеганографии, валяющихся в интернете не радуют нас разнообразием, и в основе 90% такого софта лежит тупое и наглое дописывание скрываемого сообщения в конец файла. Любой из вас может написать свой СуперНадежныйСтегоСофт пририсовав копирайтов, окошечек, свистелок и перделок к простейшей консольной команде:

echo "Проверка обнаружение дописывания в конец файла JPEG" >>mages_stego.jpg

Принцип работы алгоритма прост и непритязателен: практически все форматы документов, фото и видео содержат маркеры конца файла, после которого все данные, даже если они и содержатся, отбрасываются. Никаких искажений в фото не будет, а скрытое сообщение появится!
Для борьбы с такими хитрецами я добавил к себе анализ формата файла jpeg.

Анализируем формат файла. Тут что то не так! 


Метод обнаружения стеганографии так же прост, как и метод сокрытия. Чтобы доказать факт сокрытия информации надо найти маркеры конца файла и убедиться, что на них файл не оканчивается. Для формата jpeg этими маркерами является FFD8 и FFD9.
Чтобы организовать текста в файле воспользуемся простейшим из возможных алгоритмов, приведенному ниже:
QFile fl(this->windowTitle());
int step = 50;
if(fl.open(QFile::ReadOnly)){
//Читаем файл с конца
   QByteArray templ;
   int ended = 0xffd8ffd9;
   templ.append(ended);

   int position =-1;

   for(int i = fl.size()-step*2; i>0; i-=step){
      fl.seek(i);
      QByteArray arr = fl.read(step*2);
      if(arr.contains(templ)){
          position = arr.indexOf(templ) +i;
          break;
      }
    }

   if(position == -1 ){
      fl.close();
      return NULL;
   }
   fl.seek(position);
   QString Appended = QString(fl.readAll());


Добавленное в конец файла сообщение

После выполнения кода в переменной Appended будет содержаться добавленная в конец файла информация.  В программе Stect для анализа достаточно загрузить файл и нажать кнопку "анализ формата"

Напоминаю что скачать исходные коды программы пока еще можно по адресу http://code.google.com/p/stect/

Комментариев нет:

Отправить комментарий