Hallo zusammen,
bei der Steganographie geht es darum, eine geheime Nachricht in einem anderen, offensichtlich harmlosen Objekt zu "verstecken" im Sinne von überdecken.
Dabei werden Daten oft in Bildern versteckt, man kann aber auch in MP3´s oder in anderen Dateiformaten Informationen unterbringen, ohne dass man den "geheimen" Inhalt erkennt.
Der folgende fast 1 kb große Text
ZitatHallo, diese Nachricht ist im AutoIt-Icon versteckt!
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo.
ist im rechten Icon enthalten, das linke ist das Orginal-Icon!
-
Sieht man den Unterschied der Icons? Nein, genau DAS ist die Absicht! Ein offensichtlich harmloses Objekt enthält weitere Daten...
Wie funktioniert das?
Beispiel 32- oder 24-Bit Grafiken:
Ein Pixel besteht aus 3 Farbanteilen, Blau, Grün, Rot, welche jeweils einen Wert von 0 bis 255 (8 Bit=1 Byte) annehmen können. Man stellt die Farbe hexadezimal als 0xBBGGRR dar. Nun ist es so, daß kleine Änderungen in der Farbe von Menschen nicht wahrgenommen werden können, ein Mensch kann keinen Unterschied zwischen der Farbe 0xA3B3C3 und 0xA0B0C0 erkennen. Die "niederwertigen" Bits sind also für den optischen Eindruck völlig irrelevant. Mit Geräuschen verhält sich das ebenso. Kompressionsverfahren wie z.B. MP3 nutzen das aus, indem "unhörbare" (bei Bildern "unsichtbare") Anteile einfach weggelassen werden.
Bei der Steganografie wird hingegen dieser "unwichtige" Anteil an den Farben durch z.B. eine geheime Nachricht ersetzt!
Dabei wird die Nachricht in (in meinem Beispiel) 2 Bit lange Teilstücke aufgeteilt, und diese Teilstücke anstatt der "unwichtigen" niederwertigen Bits in den Farben eingesetzt.
Aufgabe: Der Buchstabe M soll in einem knallgrünen Bild versteckt werden.
Der Buchstabe M (Ascii 77, Ascii-Tabelle in der AutoIt-Hilfe im Anhang) sieht Binär also folgendermassen aus 01001101. Dieser Binärstring wird nun in 2 Bit große Teilstücke aufgeteilt:
M => 77 => 01001101 =>01 00 11 01
Als Farbe nehmen wir der Einfachheit halber an, die ersten Pixel des Bildes seien knallgrün Farbe 0x00FF00. Dabei besteht der Blau-Anteil der Farbe aus 0x00, Grün aus 0xFF und Rot aus 0x00. Binärdarstellung von grünen Pixeln:
00000000 11111111 00000000 (Erstes Pixel) 00000000 11111111 00000000 (zweites Pixel) usw.
Nun löschen wir die untersten beiden Bits in jedem Farbanteil, und ersetzen sie mit den Teilstücken unseres Buchstabens:
00000001 11111100 00000011 (Erstes Pixel) 00000001 11111111 00000000 (zweites Pixel) usw.
Bild speichern, fertig...Das Bild ist immer noch knallgrün, aber hat nun "Inhalt". Unser Buchstabe M sitzt "unsichtbar" in diesem Bild. Wie kann man den wieder herausholen?
Umgekehrter Weg, bei jedem Farbanteil die letzten beiden Bits extrahieren, aus 4 dieser 2er-Blöcke wird ein 8-Bit Ascii-Buchstabe...isn´t that easy?
Im folgenden Script habe ich als Bilddatei das AutoIt-Icon 3-fach vergrößert dargestellt.
Spoiler anzeigen
;eine Text-Nachricht mit bis zu 819 Zeichen wird "unsichtbar" im AutoIt-Icon versteckt und wieder extrahiert
;Beispiel für Steganographie von Andy @ autoit.de
#include <WinAPI.au3>
#include <WinAPIGdi.au3>
#include <EditConstants.au3>
#include <WindowsConstants.au3>
#include <StructureConstants.au3>
Local $hGUI, $hEdit, $hicon
Local $pointer_icon, $hbmp_icon ;pointer und handle icon
Local $pointer_stegano, $hbmp_stegano ;pointer und handle stegano
Local $pointer_diff, $hbmp_diff ;pointer und handle differenzbild
$hGUI = GUICreate("Beispiel für Steganographie", 560, 300) ;GUI
$label1 = GUICtrlCreateLabel("Orginal Icon Icon mit integriertem Text Differenzbild 64-fach verstärktes Differenzbild", 10, 10)
$label2 = GUICtrlCreateLabel("Der im Icon versteckte Text:", 10, 170)
$label3 = GUICtrlCreateEdit("", 10, 195, 530, 100, $ES_READONLY, 0)
$hdc_gui = _WinAPI_GetDC($hGUI) ;DeviceContext der Gui
GUISetState()
$hDC_icon = _CreateNewBmp32(32, 32, $pointer_icon, $hbmp_icon) ;neue 32-Bit-Bitmap erstellen, Rückgabe: DC, Pointer und Handle
Local $hicon = DllStructCreate("ptr") ;platz für Pointer des/der Icon(s)
_WinAPI_ExtractIconEx(@AutoItExe, 0, DllStructGetPtr($hicon), 0, 1) ;AutoIt-Icon holen (Zeiger auf die Liste der Handles)
$hicon = DllStructGetData($hicon, 1) ;Handle des Icons holen
$anz = _WinAPI_DrawIconEx($hDC_icon, 0, 0, $hicon, 32, 32, 0, _WinAPI_GetSysColorBrush(2), 3) ;Icon in den Buffer zeichnen mit Windows-"Hintergrundfarbe"
_WinAPI_StretchBlt($hdc_gui, 10, 50, 100, 100, $hDC_icon, 0, 0, 32, 32, $SRCCOPY) ;Icon mit 3-facher Größe in die GUI kopieren
;In diesem Icon wird eine "Nachricht" versteckt, indem ein Text (maximal 819 Zeichen) in die beiden untersten Bits jeder "Pixel"-farbe
;kodiert wird. 819 = 32 Pixel * 32 Pixel * 4 Byte pro Pixel (Anzahl Bytes des Icons) / 5 (in 5 Bytes wird ein "Buchstabe" versteckt)
;32 Bit pro Pixel= 4 Byte = BBGGRRAA Alphakanal wird nicht verwendet bzw verändert, so kann man auch transparente Icons/Bilder benutzen
;Es wird eine neue Bitmap erstellt (_stegano) und diese aus den obersten 6 Bit der Farbe des Orginal-Icons mit den Bits der
;Nachricht, welche die untersten beiden Bits der Farb-Bytes enthalten, zusammenkopiert
;32 Bit pro Pixel BBBBBBTTGGGGGGTTRRRRRRTTAAAAAAAA TT= Bits eines Buchstabens aus dem Text
;das nachfolgende Script kann immens gekürzt werden, allerdings auf kosten der Übersichtlichkeit und des Verständnisses^^
$Text = "Hallo, diese Nachricht ist im AutoIt-Icon versteckt!" & @CRLF ;versteckte Nachricht
$Text &= "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo."
;den Text in 2-Bit lange Teilstücke auftrennen
Dim $bitarray[32 * 32 * 4] ;Platz für die 2-Bit-Stücke 8 Bit = 4 * 2 Bit
For $i = 1 To StringLen($Text) ;jeden Buchstaben im Text holen
$byte = Asc(StringMid($Text, $i, 1)) ;ascii-code der einzelnen Buchstaben holen
$bitarray[($i - 1) * 4 + 0] = BitShift($byte, 6) ;oberste 2 bit
$bitarray[($i - 1) * 4 + 1] = BitShift(BitAND($byte, 48), 4) ;nächste 2 bit AND 00110000, bitshift 4
$bitarray[($i - 1) * 4 + 2] = BitShift(BitAND($byte, 12), 2) ;nächste 2 bit AND 00001100 bitshift 2
$bitarray[($i - 1) * 4 + 3] = BitAND($byte, 3) ;unterste 2 bit AND 00000011
Next
;unterste 2 Bit aus jedem Byte des Icons mit den 2 Byte des Textes ersetzen
$hDC_stegano = _CreateNewBmp32(32, 32, $pointer_stegano, $hbmp_stegano) ;neue 32-Bit-Bitmap erstellen, Rückgabe: DC, Pointer und Handle
$struct_stegano = DllStructCreate("byte [" & 32 * 32 * 4 & "]", $pointer_stegano) ;struct mit der größe der Bitmap an der Position der "Kopie"
$struct_icon = DllStructCreate("byte [" & 32 * 32 * 4 & "]", $pointer_icon) ;struct mit der größe der Bitmap an der Position des Icons
$bitarray_count = 0 ;zähler für den Index des Bitarray
For $y = 0 To 31 ;spaltenweise Pixel ändern
For $x = 0 To 31 ;zeilenweise Pixel ändern
;Pixel-farbanteile aus dem Icon holen
$B = DllStructGetData($struct_icon, 1, $y * 128 + ($x * 4) + 1) ;blau-anteil des Pixels
$G = DllStructGetData($struct_icon, 1, $y * 128 + ($x * 4) + 2) ;gruen-anteil des Pixels
$R = DllStructGetData($struct_icon, 1, $y * 128 + ($x * 4) + 3) ;rot-anteil des Pixels
$A = DllStructGetData($struct_icon, 1, $y * 128 + ($x * 4) + 4) ;Alpha-anteil des Pixels (wird nicht verändert)
;die untersten 2 Byte der farbanteile "löschen"
$B = BitAND($B, 252) ;AND 11111100 setzt die unteren beiden bit auf 0, alle anderen bleiben erhalten
$G = BitAND($G, 252)
$R = BitAND($R, 252)
;Bits aus dem Bitarray dazuaddieren
$B = $B + $bitarray[$bitarray_count * 3 + 0] ;2 bits aus dem Bitarray in das Byte an unterster position einfügen
$G = $G + $bitarray[$bitarray_count * 3 + 1]
$R = $R + $bitarray[$bitarray_count * 3 + 2]
$bitarray_count += 1 ;zähler erhöhen, nächste 3 2er Bits
;mit dem Text modifizierte Farbbytes in Zielbitmap einfügen
DllStructSetData($struct_stegano, 1, $B, $y * 128 + ($x * 4) + 1) ;blau-anteil in _stegano-bitmap eintragen
DllStructSetData($struct_stegano, 1, $G, $y * 128 + ($x * 4) + 2) ;grün-anteil in bitmap eintragen
DllStructSetData($struct_stegano, 1, $R, $y * 128 + ($x * 4) + 3) ;rot-anteil in bitmap eintragen
DllStructSetData($struct_stegano, 1, $A, $y * 128 + ($x * 4) + 4) ;alpha-anteil in bitmap eintragen
Next
Next
;_stegano-Icon in GUI darstellen
_WinAPI_StretchBlt($hdc_gui, 140, 50, 100, 100, $hDC_stegano, 0, 0, 32, 32, $SRCCOPY) ;Icon mit 3-facher Größe in die GUI kopieren
;Text aus dem _stegano-Icon extrahieren
Dim $char_array[32 * 32 * 4] ;platz für die 2-Bit-stücke machen
$char_array_count = 0
For $y = 0 To 31 ;spaltenweise Pixel auslesen
For $x = 0 To 31 ;zeilenweise Pixel auslesen
;Pixel-farbanteile aus dem Icon holen
$B = DllStructGetData($struct_stegano, 1, $y * 128 + ($x * 4) + 1) ;blau-anteil des Pixels
$G = DllStructGetData($struct_stegano, 1, $y * 128 + ($x * 4) + 2) ;gruen-anteil des Pixels
$R = DllStructGetData($struct_stegano, 1, $y * 128 + ($x * 4) + 3) ;rot-anteil des Pixels
;die untersten 2 Byte der farbanteile "herauslösen"
$char_array[$char_array_count * 3 + 0] = BitAND($B, 3) ;AND 00000011 löscht die oberen 6 bit, die beiden unteren bleiben erhalten
$char_array[$char_array_count * 3 + 1] = BitAND($G, 3)
$char_array[$char_array_count * 3 + 2] = BitAND($R, 3)
;Bits aus dem Bitarray dazuaddieren
$char_array_count += 1 ;zähler erhöhen, nächste 3 2er Bits
Next
Next
$string = "" ;extrahierter text
For $i = 0 To UBound($char_array) - 1 Step 4
$char = $char_array[$i] * 64 ;oberste 2bit
$char += $char_array[$i + 1] * 16 ;nächste 2 bit
$char += $char_array[$i + 2] * 4 ;nächste 2 bit
$char += $char_array[$i + 3] ;unterste 2 bit
$string &= Chr($char) ;8 Bit = 1 Byte = 1 char
Next
GUICtrlSetData($label3, $string) ;text in GUI anzeigen
;differenzbild in der GUI anzeigen
_WinAPI_StretchBlt($hdc_gui, 280, 50, 100, 100, $hDC_icon, 0, 0, 32, 32, $SRCCOPY) ;Orginal Icon mit 3-facher Größe in die GUI kopieren
_WinAPI_StretchBlt($hdc_gui, 280, 50, 100, 100, $hDC_stegano, 0, 0, 32, 32, $MERGEPAINT) ;stegano-Icon mit 3-facher Größe in die GUI kopieren und mit dem Orginal XOR-Verknüpfen
;da nur sehr kleine Änderungen vorhanden sind, muss das Differenzbild für die Anzeige verstärkt werden...
;dazu werden die einzelnen Farbanteile des Differenzbildes mit 64 multipliziert!
;Differenzbild erstellen
$hDC_diff = _CreateNewBmp32(32, 32, $pointer_diff, $hbmp_diff) ;neue 32-Bit-Bitmap erstellen, Rückgabe: DC, Pointer und Handle
$struct_diff = DllStructCreate("byte [" & 32 * 32 * 4 & "]", $pointer_diff) ;struct an position des Differenz-Bildes
_WinAPI_BitBlt($hdc_diff, 0, 0, 32, 32, $hDC_icon, 0, 0, $SRCCOPY) ;Orginal Icon ins DIFF kopieren
_WinAPI_BitBlt($hdc_diff, 0, 0, 32, 32, $hDC_stegano, 0, 0, $mergepaint) ;stegano-Icon DIFF kopieren und mit dem Orginal XOR-Verknüpfen
For $y = 0 To 31 ;spaltenweise Pixel ändern
For $x = 0 To 31 ;zeilenweise Pixel ändern
;Pixel-farbanteile aus dem Icon holen
$B = DllStructGetData($struct_diff, 1, $y * 128 + ($x * 4) + 1) ;blau-anteil des Pixels
$G = DllStructGetData($struct_diff, 1, $y * 128 + ($x * 4) + 2) ;gruen-anteil des Pixels
$R = DllStructGetData($struct_diff, 1, $y * 128 + ($x * 4) + 3) ;rot-anteil des Pixels
$A = DllStructGetData($struct_diff, 1, $y * 128 + ($x * 4) + 4) ;Alpha-anteil des Pixels (wird nicht verändert)
;die untersten 2 Byte der farbanteile mit 64 multiplizieren
;geänderte bytes zurückschreiben
DllStructSetData($struct_diff, 1, $B * 64, $y * 128 + ($x * 4) + 1) ;blau-anteil in _diff-bitmap eintragen
DllStructSetData($struct_diff, 1, $G * 64, $y * 128 + ($x * 4) + 2) ;grün-anteil in bitmap eintragen
DllStructSetData($struct_diff, 1, $R * 64, $y * 128 + ($x * 4) + 3) ;rot-anteil in bitmap eintragen
DllStructSetData($struct_diff, 1, $A, $y * 128 + ($x * 4) + 4) ;alpha-anteil in bitmap eintragen
Next
Next
_WinAPI_StretchBlt($hdc_gui, 400, 50, 100, 100, $hDC_diff, 0, 0, 32, 32, $SRCCOPY) ;verstärktes Differenzbild mit 3-facher Größe in die GUI kopieren
; Die Schleife wiederholt sich, bis der Benutzer die Beenden-Aktion der GUI auslöst
Do ;falls GUI minimiert oder übermalt wird, Bilder zeichnen
_WinAPI_StretchBlt($hdc_gui, 10, 50, 100, 100, $hDC_icon, 0, 0, 32, 32, $SRCCOPY) ;Orginal-Icon mit 3-facher Größe in die GUI kopieren
_WinAPI_StretchBlt($hdc_gui, 140, 50, 100, 100, $hDC_stegano, 0, 0, 32, 32, $SRCCOPY) ;stegano-Icon mit 3-facher Größe in die GUI kopieren
_WinAPI_StretchBlt($hdc_gui, 400, 50, 100, 100, $hDC_diff, 0, 0, 32, 32, $SRCCOPY) ;verstärktes Differenzbild mit 3-facher Größe in die GUI kopieren
Until GUIGetMsg() = -3 * Sleep(50)
;stegano-Icon speichern, man kann natürlich andere Dateiformate als BMP verwenden, sollte dann aber die Kompression ausschalten...sonst wird die Nachricht "wegkompriimiert"
#include <gdiplus.au3>
_GDIPlus_Startup()
_GDIPlus_ImageSaveToFile(_GDIPlus_BitmapCreateFromHBITMAP($hbmp_icon), @ScriptDir & "\Orginal-Icon.bmp") ;oder png oder unkomprimiertes JPG...
_GDIPlus_ImageSaveToFile(_GDIPlus_BitmapCreateFromHBITMAP($hbmp_stegano), @ScriptDir & "\Stegano-Icon.bmp") ;oder png oder unkomprimiertes JPG...
_GDIPlus_Shutdown()
shellexecute("Orginal-Icon.bmp") ;auf Bildschirmgröße vergrößern und vergleichen!
shellexecute("Stegano-Icon.bmp")
;DC´s und Handles entladen
_Delete_Bitmap32($hDC_icon, $hbmp_icon)
_Delete_Bitmap32($hDC_stegano, $hbmp_stegano)
_Delete_Bitmap32($hDC_diff, $hbmp_diff)
Exit
Func _Delete_Bitmap32($hDC, $hBmp)
_WinAPI_DeleteObject($hBmp)
_WinAPI_ReleaseDC(0, $hDC)
EndFunc ;==>_Delete_Bitmap32
Func _CreateNewBmp32($iwidth, $iheight, ByRef $ptr, ByRef $hBmp) ;erstellt leere 32-bit-Bitmap; Rückgabe DC und ptr und handle auf die Bitmapdaten
;by Andy
Local $hcdc = _WinAPI_CreateCompatibleDC(0) ;Desktop-Kompatiblen DeviceContext erstellen lassen
Local $tBMI = DllStructCreate($tagBITMAPINFO) ;Struktur der Bitmapinfo erstellen und Daten eintragen
DllStructSetData($tBMI, 1, DllStructGetSize($tBMI) - 4) ;Structgröße abzüglich der Daten für die Palette
DllStructSetData($tBMI, 2, $iwidth)
DllStructSetData($tBMI, 3, -$iheight) ;minus =standard = bottomup
DllStructSetData($tBMI, 4, 1)
DllStructSetData($tBMI, 5, 32) ;32 Bit = 4 Bytes => AABBGGRR
Local $adib = DllCall('gdi32.dll', 'ptr', 'CreateDIBSection', 'hwnd', 0, 'ptr', DllStructGetPtr($tBMI), 'uint', 0, 'ptr*', 0, 'ptr', 0, 'uint', 0)
$hBmp = $adib[0] ;hbitmap handle auf die Bitmap, auch per GDI+ zu verwenden
$ptr = $adib[4] ;pointer auf den Anfang der Bitmapdaten, vom Assembler verwendet
;_arraydisplay($adib)
_WinAPI_SelectObject($hcdc, $hBmp) ;objekt hbitmap in DC
Return $hcdc ;DC der Bitmap zurückgeben
EndFunc ;==>_CreateNewBmp32
Alles anzeigen
Als "Nachricht" kann man alles mögliche verstecken, z.B. andere Dateien (*.EXE, *.XLS, *.TXT *.MP3). Wobei man nicht festgelegt ist, mit welchen Bits und wo in der Containerdatei welche Daten wie gespeichert werden...
Um der Freundin einen heissen Liebesbrief zu schicken, reicht es ab heute, ihr einen harmlosen Smilie mit entsprechendem Inhalt zu senden....
Fehlt nur noch die Steganographie.UDF....ich habe eine , aber wo bleibt dann der Anreiz für euch ? Baut selbst etwas eigenes...eine digitale Signatur eurer Bilder oder MP3´s mit integriertem Coverbild und Lyrics, HAPPY PROGRAMMING!
Wer das Script einigermassen nachvollzogen hat, der bemerkt, daß die GUI nur zum Anzeigen der Bilder nötig ist. Das "Blitten" und das Ersetzen der Bits findet im Speicher statt! Also auch etwas für "nicht GDI+-Fuzzis
//EDIT 24.04.2014
Eine schöne Umsetzung der Steganographie mittels sehr schnellem Assembler-Codes gibt es vom User Xenon