Здрасте форумчане.вот пока выдалось свободное время, и перед тем когда мне наступит конец в связи с сессией, решил попробовать поделиться информацией по интересной для меня теме-стеганографии.Материалец не претендует на какую то мега-статью, скорее личные наблюдения или что. тема навеяна этим https://forum.antichat.ru/thread375855-miniduke.html и является продолжением этой http://bydood.blogspot.com/2013/05/hell-yeah.html т.к. доселе я не мог вразуметь как же так в мультимедиа заседают другие файлы.оказалось можно.хотя методика создана не для этого,но очевидно что тут применилась. В общем-то план таков: 1)немного истории,что являет собой стеганография, етц. 2)виды стеганографии( то что применим мы) 3)анализ застенографированных файлов. Писать будем на делфи, более-менее вменяемые куски кода нашел на делфи и С++ ТЕОРИЯ Итак стеганография- некий вид науки о сокрытой передаче информации, т.е. утаивании самого факта присутствия сообщения.Если криптография - это шифрование информации, то стеганография скрывает сам факт.обычно в данное время застеганографированная информация выглядит как нечто иное - к примеру файлы мультимедиа (изображения,звук,видео, даже исполняемые файлы). некоторые примеры стеганографии в допотопном мире можно прочесть на вики (довольно интересно я вам скажу ) современная стеганография подразделяется на несколько таких вот видов: 1)компьютерная стеганография: как правило сокрытие в зарезервированных полях файлов,пустых местах дисков,флешек етц, особенности файловых систем. (как пример- формат jpg имеет т.н. потоки данных (выделяет потоки для информации) т.е. можно создать отдельный поток в который записать сообщение- однако недостатки состоят в том что jpeg использует сжатие, во вторых объем файла увеличивается,в третьих производя манипуляции с изображением-можно угробить информацию) 2)современный наиболее распространенный вариант - внедрение информации в объекты вроде изображений,аудио,видео… Вызывает некоторые искажения в файлах-контейнерах, однако , как правило, не подвластно человеческому взгляду. Существует несколько алгоритмов, но самое простое и распростаненное для изображений - изменение последнего бита. суть методики в замене последнего бита файла-контейнера на биты нашей информации. рассмотрим на примере битмапа - у него там на одну точку приходится 3 байта- red , green, blue. и согласитесь что если будут точки допустим 135,58,44 и точки 136,58,45 то взгляд среднего (да любого) человека не отличит визуально. Попробуем написать разного рода код для сокрытия информации в: секторе, битмапе,тексте. 1)СЕКТОР. заранее определим нужные нам сектора, это могут быть также сектора заполненные подставными файлами, строки могут быть зашифрованы каким то не сложным алгоритмом.Подробно останавливаться не буду, т.к. тут все просто: открываем диск: Code: CreateFile ('\\.\PhysicalDrive0',GENERIC_WRITE,FILE_SHARE_WRITE,0,OPEN_EXISTING,0,0); (для примера системный диск, ну вообще указываем тот что нам нужен). идем на нужную позицию: Code: SetFilePointer(f,10*512,nil,FILE_BEGIN); 11 сектор в примере. И запись в общем то как в обычный файл: Code: WriteFile(f,somedata,sizeof(somedata),nw,nil); 2)И вот самое интересное - сохраняем в битмап. Тут напишем уже полноправную программку) Рассмотрим запись в «лоб» и замену битов. Заголовок битмапа=14 байтам + ширина*высоту - после этого смещения мы можем писать все что угодно,что бы при этом битмап открывался. но нужно создавать некий разброс если сообщение большое,потому что получается вот такой вот прикол: видим что изображение искажается. понятно что писать в ряд нельзя, что бы скрыть придется писать по 1-2 байта с определяющим знаком (для считывания) и через несколько байт\десятков байт, так что здесь описывать я подробно не буду. Заметил,что при дописывании в файле - рисунок не искажается (искажения идут снизу-вверх) что в целом может подойти как один из наипростейших методов. напишем тогда код алгоритм следующий: 1)открыть битмап 2)считать из хидера 2 параметр-размер битмапа (то есть получим нужное смещение) 3)сместиться на полученное смещение 4)записать строку с определенным идентификатором по считыванию назад 1)открыть битмап 2)считать из хидера 2 параметр 3)читать строку от начала конца (простите за тавтологию) до идентификатора 4)выдрать строку. имеем след. код: Code: type bmpheader=packed record bftype:word; bfsize:dword; bfres1:word; bfres2:word; bfoffbits:dword; end; var Form1:Tform1; ………………………………….. var size:bmpheader; f:hfile; tmp:dword; str:pchar; begin str:='fuck you bitch sosi kirpich :D'; F := CreateFile(PChar('C:\input.bmp'), GENERIC_READ or GENERIC_WRITE , FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0); ReadFile(F, size, sizeof(size), tmp, nil); setfilepointer(f,size.bfSize,nil,FILE_BEGIN); WriteFile(f,str^,length(str),tmp,nil); CloseHandle(F); вот такой не большой код. для чтения все точно также. Следующий метод-замена младших бит. алгоритм его работы таков: есть изображение 24 битов. 1 пиксель кодируется 3 каналами (=3 байтам) RGB меняя наименее значащий бит мы инкрементируем значение байта на 1. Сама методика считается простой, т.к. должны использоваться форматы данных без потерь.Как недостаток-любые манипуляции с файлом контейнером не допустимы.Как достоинства-простота, кол-во данных для внедрения. Естественно что обнаружить сокрытое сообщение закодированное таким методом можно только с помощью стегоанализа. если провести небольшие расчеты то можно подсчитать что каждая точка кодируется числом в диапазоне от 0 до 255 т.е. 3 байта на пиксел что составит 256^3 числа цветов. человеческий глаз различает около 4000 цветов\оттенков, так же человеческое зрение воспринимает лучше вариации зеленого цвета , по этому замену лучше проводить в синей или красной компоненте. окей и сейчас я начну писать как в этих симпотных книжках по делфи =^^= бросьте на форму: edit, label, 3 кнопочки, изображение, openpicturedialog, savepicturedialog что бы получилось примерно так: у image cв-ва proportional и stretch ставим в true в диалогах убираем все кроме битмапки. и сразу пишем обработчики событий кнопочег Code: // загружаем картинку procedure TForm1.Button1Click(Sender: TObject); begin if OpenPictureDialog1.Execute then begin Image1.Picture.LoadFromFile(OpenPictureDialog1.FileName); end; end; //застеганографируем сообщение procedure TForm1.Button2Click(Sender: TObject); begin steanographthemall(Image1.Picture.Bitmap, sign+(edit1.Text)); if SavePictureDialog1.Execute then Image1.Picture.SaveToFile(SavePictureDialog1.FileName); end; // извлекаем сообщение procedure TForm1.Button3Click(Sender: TObject); var s: string; begin if openpicturedialog1.Execute then image1.Picture.LoadFromFile(openpicturedialog1.FileName); showmeyourself(Image1.Picture.Bitmap, s); showmessage(s); end; ну и самый замес- процедуры кодировки\раскодировки, но сначала пишем в константах: Code: const sign:string=’dood’; по ней будем идентифицировать информацию в картинке процедура стеганографирования (нужные комментарии непосредственно в коде) Code: procedure steanographthemall (BMP: TBitmap; Message: string); var i,j,psz,fromhead : integer; rowl : pByteArray; PB : pByte; incc: PChar; bcode,Nbcode,intc,bc: byte; begin psz:=3; // разрядность изображения, не проверял сколько может поддерживаться, только делал на 24 битном, попробуйте поиграть if not Assigned(BMP) then exit; Message:=sign+Message; fromhead:=Length(Message)+2; with BMP do begin incc:=@Message[1]; // указатель на начало сообщения BC:=0; for i:=0 to Height-1 do begin rowl:=ScanLine[i]; // указатель на строку пикселей pb:=@rowl[0]; // смещаем 1 бит на пиксель (можно и больше для большей вместимости шифруемой информации, однако это даст заметно сильные искажения видимые не вооруженным глазом for j:=0 to Width-1 do begin intc:=Ord(incc^); asm mov al,0feh // сбрасываем нулевой бит mov bcode,al xor al,al mov al,bcode not al mov nbcode,al //сдвигаем что бы записывался младший бит mov cl,8 ror Intc,cl mov cl,BC // проход по битам символа ror IntC,cl end; PB^:=(PB^ and BCode) or (IntC and NBCode); // 7 бит не изменяем, а изменяем только 0 или 1 в зависимости от того какой бит установлен в данный момент и какой бит в строке if (BC = 7) then begin // прошел весь символ? inc(incC); // след. символ dec(fromhead); // декрементируем число оставшихся BC:=0; // очищаем счетчик битов end else inc(BC); if fromhead = 0 then exit; inc(PB, PSz); // перемещаем указатель буфера битмапа. end; end; end; end; для битовых операций применился встроенный ассемблер, как бы для студенческой поделки оно и не требуется, однако под напором окружающей среды мозг начинает сохнуть и мне захотелось его пое*ать.) процедура извлечения Code: procedure showmeyourself(BMP: TBitmap; var msg: string); var i,j,psz: integer; c: Byte; pb : pByte; rowl : pByteArray; bc,bit,bit2,bitc: byte; begin psz:=3; // 24bit bitmap msg:=''; // сообщение пока пусто if not Assigned(BMP) then exit; with BMP do begin c:=0; BC:=0; for i:=0 to Height-1 do begin rowl:=ScanLine[i]; pb:=@rowl[0]; for j:=0 to Width-1 do begin asm xor al,al // 1 бит сообщения на пиксель inc al mov bit,al end; Bit:=PB^ and Bit; asm mov al,bit shr al,0 mov bit2,al end; // проверяем установленные биты Bit2:=Bit2 shl BC; // операции противополжны процедуре выше [COLOR=Red]BitC:=1; asm mov cl,BC add BitC,cl end;[/COLOR] C:=C or (BitC and Bit2); if BC = 7 then // прошли байт begin if C <> 0 then //- 0? конец данных begin msg:=msg+Chr(C); if (Length(msg) = 4) then // длинна сигнатуры? begin if msg = sign then // да,- сигнатура совпала- да. begin msg:=''; end; end; end else if (i + j) > 0 then // если не первый пиксель exit; C:=0; BC:=0; // сбрасываем счетчик битов end else inc(BC); // читаем след. бит. inc(PB, Psz); end; end; end; end; А ВОТ ТУТ ТО И ПРИКОЛ!!! я решил устроить просто небольшую фишку (если это вообще хоть кому-то интересно) я допустил ошибку в строке расшифровки, а именно вот тут Code: Bit2:=Bit2 shl BC; // операции противополжны процедуре выше BitC:=1; asm mov cl,BC add BitC,cl end; ее найти очень просто (подсказка в коменте). кто сможет найти тот сможет кой чего посмотреть,это я укажу в конце статьи. МЕТОДЫ АНАЛИЗА как правило если это не такая студенческая поделка, как у меня, которую вскроет любая стегоаналитическая софтина, то методы атаки основаны на нехеровых мат. расчетах что мне объяснить не доступно ибо я не математик. если же это что то простое то обычно можно применить: прослушивание-просматривание файла известен пустой контейнер - например добавить шумы к изображению, проанализировать звуковой спектр в аудиофайле етц… я провел свое микроисследование этого же метода НЗБ вот что мы видим: размер одинаков. а теперь засовываем в хекс редактор. как можно наблюдать слева- зашированное, программа меняла последний бит картинки и ставила в соответствие 00 - 0 01 - 1 FF - 1 FE - 0 строчки снизу вверх, а так же в винде по-моему не как у людей RGB , а BGR. даа забыл указать, объемы скрываемых сообщений зависят от применяемых алгоритмов и обычно бывают ~ 1\5 от объема файла контейнера. ================================================================================================ вот и подошел момент истины что называется.Это такой миниквест если кому интересно(не только ж я себе мозги ебу). с помощью программки по НЗБ в этой картинке зашифрован адрес на архив. а с помощью вот этого кода Code: program Project1; {$APPTYPE CONSOLE} uses sysutils; var inn, outt : textfile; i, j, cnt : integer; OneSymbol : byte; sIn, s, sOne : string; inpt:string = 'C:\1.txt'; otp:string= 'C:\2.txt'; procedure encrypt; begin Assign(inn, inpt); Assign(outt, otp); WriteLn('input the encode string: '); Readln(sIn); Reset(inn); cnt:=0; while (Not EOF(inn)) do begin Readln(inn); inc(cnt); end; Close(inn); begin Reset(inn); Rewrite(outt); for i:=1 to Length(sIn) do begin OneSymbol := ord(sIn[i]); for j:=1 to 8 do begin ReadLn(inn, s); while ( Length(s)>0 ) and (s[Length(s)]=' ') do Delete(s,Length(s),1); if (OneSymbol and 1) = 1 then s:= s+' '; WriteLn(outt, s); OneSymbol := OneSymbol shr 1; end; end; ReadLn(inn, s); while ( Length(s)>0 ) and (s[Length(s)]=' ') do Delete(s,Length(s),1); s:= s+' '; WriteLn(outt, s); while Not EOF(inn) do begin ReadLn(inn, s); WriteLn(outt, s); end; Close(outt); Close(inn); end; end; procedure decrypt; begin Assign(inn, inpt); Assign(outt, otp); sIn := ''; Reset(outt); i:= 0; OneSymbol := 0; while Not EOF(outt) do begin Readln(outt, s); if Length(s)>=2 then if copy(s,Length(s)-1,2)=' ' then Break; inc(i); if (Length(s)>0) and (Copy(s, Length(s),1)=' ') then OneSymbol := OneSymbol or $80; if i=8 then begin sIn := sIn + chr(OneSymbol); i:=0; OneSymbol := 0; end else OneSymbol := OneSymbol shr 1; end; WriteLn('detected: ', sIn); WriteLn; Readln; end; begin // uncomment what u need //encrypt; decrypt; end. из архива из текстового файла извлекается пароль к папке вот тяк от. всем спасибо за внимание. баклажанами не бросаться!)
Пожалуй придется оставить сообщение, знаю, напишешь статью, она идет вниз, рейтинга просмотров почти нет, никто ничем не поинтересуется, не спросит, не предложит написать/добавить. Почти не сталкивался с стеганографией поскольку это не было нужно, тема очень интересная, но её приходится использовать, как и искать в очень редких случаях, которые я практически за исключением основных не могу припомнить, - хотелось бы расширить область применения. DooD, эта статья - неплохое введение, но все её содержание больше относится к программированию на Dephi и ASM, что будет безусловно интересно читателем, но вероятно не при изучении стенографии. Так-же можно было-бы рассказать больше о используемых технологиях, структуре файлов, а не комментировать блоки кода подобным типом: Оформление у предложений практически никакое(Вы сломали обе клавиши Shift?), я понимаю, это ваш стиль, но не стиль других людей. Текста вполне достаточно, однако когда я его читал, я не нашел взаимосвязи его большей части с содержанием и темой статьи. Если вы будете писать продолжение, хотелось бы больше узнать о повседневном применении стенографии, ей обнаружении, и о том, как её применять что-бы никто и не думал что она используется, а она используется, и не просто так.
2ХАМЕНА скажу,что я взял что то наиболее простое,потому что тема сложная,хорошие алгоритмы требуют математических знаний на высоком уровне. метод LSB подходит для множества форматов, однако опять же я взял bmp потому что это ОЧЕНЬ простой формат и тут не должно возникнуть больших сложностей с пониманием. согласен что к оформлению отношусь небрежно,ну такой я а общие принципы применения я думаю не сильно важны или интересны,т.к. это может быть все что угодно,как шифрование для себя,так и обмен информацией между террористами.
Как-то абстрактно это все, вот если бы её использовать так активно, как уязвимости Без этого скучно очень и читать, и делать. Сделал бэкап ценных данных, пустил по сети и все, больше и сказать нечего.
D00D , спасибо за статью , очень интересно почитать! \\ до этого юзал так в консоли Code: copy /b 1.jpg + 2.rar 3.jpg. 2.rar конечно под паролем )) было интересно узнать глубже про стенографию в целом!