LSB steganografi

En gång i tiden skrev jag min första inlägget på navet. Och det inlägget ägnades åt ett mycket intressant problem, nämligen steganografi. Naturligtvis kan den lösning som föreslås i det gamla ämnet inte kallas steganografi i ordets rätta bemärkelse. Det är bara ett spel med filformat, men ett ganska intressant spel ändå.

Idag ska vi försöka gräva lite djupare och titta på LSB-algoritmen. Är du intresserad är du välkommen under katt. (Under klippet är trafik: ungefär en megabyte.)

Först och främst är det nödvändigt att göra en kort introduktion. Alla vet att syftet med kryptografi är att göra det omöjligt att läsa hemlig information. Självklart har kryptografi sina applikationer, men det finns ett annat tillvägagångssätt för dataskydd. Vi behöver inte kryptera informationen, utan låtsas att vi inte har den. Det är just därför steganografi uppfanns. Wikipedia försäkrar oss att "steganografi (från grekiskan στεγανοσ - gömd och grekiskan γραφω - jag skriver, bokstavligen "hemlig skrift") är vetenskapen om den dolda överföringen av information genom att hålla själva överföringen hemlig.

Naturligtvis är det ingen som förbjuder att kombinera kryptografiska och steganografiska metoder. Dessutom gör de detta i praktiken, men vår uppgift är att förstå grunderna. Om du noggrant studerar Wikipedia-artikeln kommer du att få reda på att steganografialgoritmer inkluderar den sk. behållare och meddelande. En behållare är all information som hjälper till att dölja vårt hemliga meddelande.

I vårt fall kommer behållaren att vara en bild i BMP-format. Låt oss först titta på strukturen för den här filen. Filen kan delas in i 4 delar: filhuvud, bildhuvud, palett och själva bilden. För våra ändamål behöver vi bara veta vad som står i rubriken.

De första två byten i rubriken är BM-signaturen, sedan skrivs filstorleken i byte i ett dubbelord, de nästa 4 byten är reserverade och måste innehålla nollor, och slutligen innehåller ett annat dubbelord offseten från början av filen till bildens faktiska byte. I en 24-bitars bmp-fil kodas varje pixel med tre BGR-byte.

Nu vet vi hur vi ska komma till bilden, allt som återstår är att förstå hur vi kan skriva den information vi behöver där. För detta kommer vi att behöva LSB-metoden. Kärnan i metoden är följande: vi ersätter de minst signifikanta bitarna i byten som ansvarar för färgkodning. Låt oss säga att om nästa byte i vårt hemliga meddelande är 11001011 och byten i bilden är...11101100 01001110 01111100 0101100111... så kommer kodningen att se ut så här. Vi kommer att dela upp den hemliga meddelandebyten i fyra tvåbitarsdelar: 4, 11, 00, 10, och ersätta de låga bitarna i bilden med de resulterande fragmenten: ...1111 01001100 01111110 0101100111…. En sådan ersättning är i allmänhet inte märkbar för det mänskliga ögat. Dessutom kommer många äldre utgångsenheter inte ens att kunna visa sådana mindre ändringar.

Det är tydligt att du kan ändra inte bara de 2 minst signifikanta bitarna, utan valfritt antal av dem. Det finns följande mönster: ju fler bitar vi ändrar, desto mer information kan vi dölja, och desto mer störningar kommer detta att orsaka i originalbilden. Här är till exempel två bilder:

LSB steganografi
LSB steganografi

Trots mina ansträngningar kunde jag inte se skillnaden mellan dem, men ändå, i den andra bilden, med den beskrivna metoden, döljs Lewis Carrolls dikt "The Hunting of the Snark". Om du har läst så här långt är du förmodligen intresserad av att lära dig mer om implementeringen. Det är ganska enkelt, men jag kommer genast att varna dig om att allt är gjort i Delphi. Det finns två anledningar till detta: 1. Jag tycker att Delphi är ett bra språk; 2. Det här programmet föddes i färd med att förbereda en kurs om grunderna i datorseende, och killarna som jag undervisar i den här kursen vet ännu inte något annat än Delphi. För de som inte är bekanta med syntaxen måste en sak förklaras: shl x är en bitvis förskjutning åt vänster med x, shr x är en bitvis förskjutning åt höger med x.

Vi antar att vi skriver text lagrad i en sträng i behållaren och ersätter de två nedre byten:
Inspelningskod:

för i:=1 till length(str) gör
    börja
      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);
 
    slutet;

kod att läsa:

för i:=1 till MsgSize gör
    börja
      f.ReadBuffer(tmp,1);
      1:=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+2+3+4);
    slutet;

Tja, för de riktigt lata - länk till programmet och dess källkod.

Tack.

Källa: will.com

Lägg en kommentar