LSB steganograafia

Kaua kaugel tagasi kirjutasin ma oma esimese postituse Habr`is. See postitus oli pühendatud väga huvitavale probleemile, nimelt steganograafiale. Loomulikult ei saa seda vana teemat nimetada steganograafiaks sõna tõelisest tähendusest. See on lihtsalt mäng failivormingutega, kuid samas üsna huvitav mäng.

Täna proovime sügavamale kaevuda ja vaatame LSB algoritmi. Kui see huvitab teid, siis olete lahkelt oodatud allapoole. (Allpool on andmeedastus: umbes megabait.)

Esiteks on vajalik teha väike sissejuhatus. Kõigile on teada, et krüptograafia eesmärk on teha salajase teabe lugemine võimatuks. Muidugi on krüptograafial oma rakendusalad, kuid on ka teine lähenemine andmete kaitsmisele. Teavet ei pea krüptima, vaid saab teha nii, nagu meil seda ei oleks. Just selleks on välja mõeldud steganograafia. Vikipeedia kinnitab meile, et "steganograafia (kreeka k. στεγανοσ - peidetud ja kreeka k. γραφω - kirjutanud, sõnasõnaliselt 'salakirjutamine') on teadus peidetud teabe edastamisest, hoides saladuses edastamise fakti.

Loomulikult ei keelata kellelgi kombineerida krüptograafilisi ja steganograafilisi meetodeid. Veelgi enam, praktikas nii ka tehakse, kuid meie ülesanne on mõista aluseid. Kui hoolikalt uurida Vikipeedia artiklit, siis saab teada, et steganograafia algoritmides mängib rolli nn konteiner ja sõnum. Kontainer on iga info, mis aitab peita meie salajast sõnumit.

Meie juhul on konteineriks BMP formaadis pilt. Esiteks vaatame selle faili struktuuri. Faili saab tinglikult jagada neljaks osaks: faili pealkiri, pildi pealkiri, palett ja ise pilt. Meie eesmärk on teada ainult seda, mis on kirjas pealkirjas.

Pealkirja esimesed kaks baiti on signatuur BM, seejärel kahetasas sõnas on faili suurus baitides, järgmised 4 baiti on reserveeritud ja peaksid sisaldama nulli, ja lõpuks, veel ühes kahetasas sõnas on kirjas, kui kaugel failist on pildi baitide algus. 24-bitises bmp-failis kodeeritakse iga piksel kolme baitiga BGR.

Nüüd teame, kuidas jõuda pildini, jääb alles aru saada, kuidas sinna vajalikku teavet salvestada. Selleks tulebki appi meetod LSB. Meetodi sisu on järgmine: asendame värvikoode koodivõimaluste madalaimad bitid. Oletame, et meie salajase sõnumi järgmine bait on 11001011, ja pildis on baitideks …11101100 01001110 01111100 0101100111…, siis kodeerimine näeb välja selline. Jagame salajase sõnumi baidi neljaks kahebitiseks osaks: 11, 00, 10, 11 ja asendame pildi madalaimad bitid: …11101111 01001100 01111110 0101100111…. Selline asendamine ei ole inimsilma jaoks tavaliselt märgatav. Veelgi enam, paljud vanad väljundseadmed ei suuda isegi nii väikseid muutusi kuvada.

On selge, et saame muuta mitte ainult 2 madalaimat bitti, vaid ka igasugustes kogustes. Siin on järgmine seadus: mida rohkem bitti me muutame, seda suurema teabe mahu saame peita ja seda suuremaid häireid see algses pildis tekitab. Näiteks siin on kaks pilti:

LSB steganograafia
LSB steganograafia

Kuidas iganes ma ka ei püüdnud, ei suutnud ma nende vahel mingit erinevust näha, ja ometigi on teises pildis varjatud Lewis Carrolli luuletus „Sarnaku Jaht“. Kui olete siiani jõudnud, siis on teil kindlasti huvitav teada ka rakenduse kohta. See on üsna lihtne, kuid hoiatan kohe, et kõik on tehtud Delphi keeles. Kaks põhjust: 1. Pean Delpit heaks ja sobivaks keeleks; 2. See programm sündis, kui ettevalmistus masinavaatluse kursuseks, ja kutid, kellele seda kursust õpetan, ei oska veel midagi muud peale Delphi. Nendele, kes ei tunne süntaksit, on vaja selgitada ühte asja shl x – bitiviivitus vasakule x võrra, shr x – bitiviivitus paremale x võrra.

Arvestame, et salvestame konteinerisse teksti, mis on salvestatud stringis ja asendame madalaimad kaks bitti:
Salvestamise kood:

for i:=1 to length(str) do
    begin
      l1:=byte(str[i]) shr 6;
      l2:=byte(str[i]) shl 2; l2:=l2 shr 6;
      l3:=byte(str[i]) shl 4; l3:=l3 shr 6;
      l4:=byte(str[i]) shl 6; l4:=l4 shr 6;
 
      f.ReadBuffer(tmp,1);
      f.Position:=f.Position-1;
      tmp:=((tmp shr 2) shl 2)+l1;
      f.WriteBuffer(tmp,1);
 
      f.ReadBuffer(tmp,1);
      f.Position:=f.Position-1;
      tmp:=((tmp shr 2) shl 2)+l2;
      f.WriteBuffer(tmp,1);
 
      f.ReadBuffer(tmp,1);
      f.Position:=f.Position-1;
      tmp:=((tmp shr 2) shl 2)+l3;
      f.WriteBuffer(tmp,1);
 
      f.ReadBuffer(tmp,1);
      f.Position:=f.Position-1;
      tmp:=((tmp shr 2) shl 2)+l4;
      f.WriteBuffer(tmp,1);
 
    end;

lugemise kood:

for i:=1 to MsgSize do
    begin
      f.ReadBuffer(tmp,1);
      l1:=tmp shl 6;
      f.ReadBuffer(tmp,1);
      l2:=tmp shl 6; l2:=l2 shr 2;
      f.ReadBuffer(tmp,1);
      l3:=tmp shl 6; l3:=l3 shr 4;
      f.ReadBuffer(tmp,1);
      l4:=tmp shl 6; l4:=l4 shr 6;
      str:=str+char(l1+l2+l3+l4);
    end;

Ja täiesti laiskade jaoks – link programmile ja selle lähtekoodile.

Aitäh.

Allikas: habr.com

Osta usaldusväärne hostimine veebilehtede jaoks DDoS-i kaitsega, VPS VDS serverid 🔥 Osta usaldusväärne hostimine veebilehtede jaoks DDoS-i kaitsega, VPS VDS serverid | ProHoster