25 марта 2011 г.

Стегоанализ с известным контейнером или попиксельное сравнение изображений в Matlab.


Одним из наиболее простых способов стегоанализа является стегоанализ с известным контейнером. Он возможен при наличии исходного изображения. Заведомо пустая картинка сравнивается с той, которая подозревается в содержании скрытой информации. Однако, разницу в один бит (и даже больше) человеческий глаз увидеть не может. Напишем скрипт в системе математического моделирования Matlab, который произведет попиксельное сравнение цветовых компонент изображений и сделает их разницу более очевидной. 

Рис.1 Мурзик без вложений :)
Загружаем изображения в Matlab. Возможен такой случай, когда мы не знаем какой из файлов является пустым, а какой содержит стегосообщение. Поэтому обозначим изображения переменными IMG_1 и IMG_2 без указания, какое из изображений чистое, а какое со встраиванием.

IMG_1_name='./images/murzik.bmp';
IMG_1 = imread(IMG_1_name);

IMG_2_name='./stego_murzik1.bmp';
% IMG_2_name='./stego_murzik2.bmp';
% IMG_2_name='./stego_murzik3.bmp';
IMG_2 = imread(IMG_2_name);


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

IMG_size_y=size(IMG_1,1);
IMG_size_x=size(IMG_1,2);

IMG_size_y2=size(IMG_2,1);
IMG_size_x2=size(IMG_2,2);

Если размеры изображений не совпадают, выводим сообщение об ошибке и завершаем работу.

if ((IMG_size_y~=IMG_size_y2)||(IMG_size_x~=IMG_size_x2))
 error('Выбранные изображения имеют неодинаковый размер. Попиксельное сравнение невозможно.');
end;

В случае, если все нормально и  изображения одинакового размера, продолжаем:
if ((IMG_size_y==IMG_size_y2)&&(IMG_size_x==IMG_size_x2))

  Разделим трехмерный массив изображения на двумерные массивы цветовых компонент RGB:

  R_1=IMG_1(:,:,1);
  G_1=IMG_1(:,:,2);
  B_1=IMG_1(:,:,3);

  R_2 =IMG_2 (:,:,1);
  G_2 =IMG_2 (:,:,2);
  B_2 =IMG_2 (:,:,3);

  Проиндексируем те пиксели, которые полностью одинаковы, т.е. те, у которых значения для всех цветовых компонент совпадают:

  ind_R=uint32(find((B_1==B_2) & (R_1==R_2) & (G_1==G_2 )));
  ind_G=uint32(find((B_1==B_2) & (R_1==R_2) & (G_1==G_2 )));
  ind_G=ind_G+IMG_size_y*IMG_size_x;
  ind_B=uint32(find((B_1==B_2) & (R_1==R_2) & (G_1==G_2 )));
  ind_B=ind_B+2*IMG_size_y*IMG_size_x;

  Создадим новое изображение, в котором яркими точками будем показывать места неодинаковости пикселей:

  IMG=IMG_2;

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

  IMG(:,:,1)=255;
  IMG(:,:,2)=0;
  IMG(:,:,3)=0;

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

  Запишем одинаковые значения цветовых компонент на свои места.

  IMG(ind_R)=IMG_2(ind_R);
  IMG(ind_G)=IMG_2(ind_G);
  IMG(ind_B)=IMG_2(ind_B);


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

  imshow(IMG);
end;

С помощью нашего скрипта сравним пустую фотографию уже знакомого нам Мурзика. С его же фотографиями, в LSB которых встроены архивы трех литературных произведений: 
  • «Утопия» Томаса Мора
  • «Мертвые души» Николая Гоголя
  • «Война и мир» (1-й том) Льва Толстого 
Скрипты для встраивания и извлечения данных можно посмотреть в предыдущих постах.
Т.к. мы же и были авторами встраивания, то знаем, что встраивание происходило по столбцам, слева направо поочередно в красную, зеленую и  синюю цветовые компоненты. Учтем эту информацию в дальнейшем анализе.



Рис.2 «Утопия»
 Т. Мор
Как видно, после встраивания архива «Утопии» правая  часть изображения осталась совершенно незатронутой. Можно сделать вывод, что данный архив занимает только часть 1-й цветовой компоненты изображения (Рис.2).
Рассмотрим внимательно левую часть рисунка, ту, где есть встраивание. Среди красных точек, где сравниваемые изображения не совпадают, можно увидеть пиксели, которые одинаковы для обоих изображений. Более внимательное изучение показывает, что «загрязнению» подверглось 50% Мурзика. Следовательно, вероятность изменения байта цветовой компоненты встраиванием равна 0.5. 

 Рис.3 «Мертвые души»
 Н. Гоголь
Рассмотрим встраивание большего объема. Архив «Мертвых душ» Николая Гоголя занимает всю 1-ю цветовую компоненту и чуть более половины второй (Рис.3).  В правой части рисунка 3 подобно левой части рисунка 2 изменения коснулись только половины пикселей (изменению подверглась только первая цветовая компонента).


Левая часть рисунка 3 гораздо сильнее «загрязнена» по сравнению с исходным изображением. Это объясняется объединением случайных событий: «изменение пикселя в 1-й цветовой компоненте» и «изменение пикселя во 2-й цветовой компоненте».

P(A+B)=P(A)+P(B)-P(AB)=
=0.5+0.5-0.5*0.5=0.75

Следовательно, в левой части рисунка 3 «загрязнено» уже 3/4 пикселей.
Рис.4 «Война и мир»
 1-й том Л. Толстой
Наибольшее встраивание - 1-й том «Войны и мира» Льва Толстого занимает все три цветовые компоненты. Сквозь пелену измененных пикселей едва проглядываются те, которые остались без изменений. 
Посчитаем вероятность того, что пиксель останется неизменным после рассеянного встраивания во все цветовые компоненты.


P(A+B+С)=P(A)+P(B)+P(С)-P(AB)-P(BС)-
-P(СA)+P(ABC)=
=0.5+0.5+0.5-0.25-0.25-0.25+0.125=0.875

При встраивании во все пиксели всех цветовых компонент без изменения останется лишь 12,5 % пикселей.
Загрузить скрипт сравнения с файлами, которые использовались в публикации можно по ссылке.

3 комментария:

  1. Вот молодец автор! Грамотно во всех отношениях! Редкость. Спасибо.

    ОтветитьУдалить
  2. Ссылка не работает! Обновите пожалуйста, очень интересно посмотреть!

    ОтветитьУдалить
  3. Ладно, ничего страшного, что не работает! Я так собрал, с этой страницы в .m файл. Все работает! Мега-респект!

    ОтветитьУдалить