Steganographie



  • moin moin allerseits,

    unsere Klasse hat in der eben vergangennen Woche ein neues Projekt bekommen was uns doch in staunen versetzte denn es hat keiner irgend eine Ahnung wie wir das anpacken sollen.

    Das Projekt heißt, wie im Titel schon gennant, Steganographie.

    Unsere Aufgabenstellung lautet wie folgt:

    Erstellen Sie ein Programm, um die Steganographie zu nutzen mit folgenden Anforderungen:

    - Ändern des LSB eines Farbbytes.
    - Vor dem Verstecken überprüfen des Bildes, ob es geeignet ist.
    - Vor dem Entpacken überprüfen, ob das Bild Daten enthält.
    - Speichern des ursprünglichen Dateinamens.
    - Abfragen, ob das Originalbilderhalten oder gelöscht werden soll.
    - Verstecken und vollständige Wiederherstellung (exakte Größe) einer Datei.
    - Keiner Veränderung der Größe des Zielbildes
    - Parametereingabe entweder im Programmablauf oder bei Programmaufruf mit Parameterübergabe, z.b. stegano.exe entpack bild.bmp datei.nam
    - /? bei Programmaufruf erklärt die Möglichkeiten der Parameterübergabe.
    - NUR BMP Unterstützung

    das währs dann.
    Ganz schön happig wie ich finde, da wir das Fach erst seit ein paar Monaten haben.

    Ich bitte euch darum mir/uns Hilfestellungen zu geben wie wir das ganze anpacken können.
    Wie z.b. auslesen und umgehen mit dem BMP Code, usw.
    Ich währe auch nicht abgeneigt ein paar Programmschnipsel einzusehen um zu sehen wie das umgesetzt wurde.

    DANKE schon einmal.


  • Administrator

    -> Wikipedia Artiekl durchlesen ... unten hat es anscheinend sogar Links mit Quelltext
    -> www.google.de
    -> www.codeguru.com
    -> www.codeproject.com
    -> http://msdn2.microsoft.com/en-us/library/default.aspx (z.b. für BMP Definition)
    -> http://www.c-plusplus.net/forum/search-var-.html (vielleicht gibt es schon was in unserem Forum ^^)
    -> www.amazon.de (Bücher können auch helfen 😉 )

    Ansonsten frag was konkretes und ich helfe gerne. Aber was soll man da grossartig schon sagen. Ihr müsst das Projekt machen, nicht wir. Wenn ihr spezifische Fragen habt, dann fragt!

    Grüssli



  • in deutsch haste net zufällig ein paar links oder?

    konkrete Fragen, ok:

    1. ich weis, dass die BMP Files nen Header haben und ich weis dass die wirklichen Bildinformationen immer an einer anderen stelle anfangen können, außerdem weis ich dass die information, wo die bildaten anfangen im Header stehen.
    nur wo stehen die?

    2. ich weis auch dass ein Pixel aus den 3 Grundfarben besteht (Rot, Grün und Blau) und dass diese verschieden gesättigt sind (intensität) die von 0-255 pro Grundfarbe sein sollte.
    wie wandel ich jetzt den BMP Code so um, dass ich sehen kann wie hoch die intensität pro farbe ist?

    denn den wert brauch ich ja, um z.b. in eine 8 bit dualzahl umzuwandeln womit ich dann auch gleich das letzte bit auf 1 bzw. 0 setzen kann und somit die dateiinformation der zu versteckenden datei ins LSB setzen kann.



  • Dieser Thread wurde von Moderator/in HumeSikkins aus dem Forum C++ in das Forum Rund um die Programmierung verschoben.

    Im Zweifelsfall bitte auch folgende Hinweise beachten:
    C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?

    Dieses Posting wurde automatisch erzeugt.


  • Administrator

    http://www.google.ch/search?hl=de&q=File+Format+BMP&btnG=Suche&meta=
    Die Beste Website für File Formats ist leider down: http://www.wotsit.org/

    Ums Englisch kommst du übrigens beim Programmieren so gut wie nicht herum. Also fang besser gleich damit an, englische Texte zu lesen, dann fällt es dir später leichter 😉

    Grüssli



  • gibts irgenwie ne möglichkeit die größe eines arrays ner variable zuzuweisen.

    also wenn ich nen text von z.b. 10 zeichen habe währe es schwachsinnig das array vorher mit ner größe von z.b. 1000 zu deklarieren.

    außerdem währe es praktischer, weil da muss ich nichts festlegen wo schluss ist.



  • Du kannst mit new[] dynamisch Speicher zur Laufzeit allokiieren (musst du mit delete[] wieder löschen) Oder du nimmst gleich std::string (sollte irgendetwas das hier verhinder entschuldige ich mich)



  • ist es dmit auch möglich den kompletten inhalt einer Bilddatei einzulsen ohne dass es probleme gibt?

    das mit dem std::string also die 2 Doppelpunkte das haben wir in der schule noch nicht gelernt. könnte mir da einer weiterhelfen?



  • Search&Destroy schrieb:

    1. ich weis, dass die BMP Files nen Header haben und ich weis dass die wirklichen Bildinformationen immer an einer anderen stelle anfangen können, außerdem weis ich dass die information, wo die bildaten anfangen im Header stehen.
    nur wo stehen die?

    Ziemlich weit vorne im Bitmap-Header (Bytes 10..13).

    2. ich weis auch dass ein Pixel aus den 3 Grundfarben besteht (Rot, Grün und Blau) und dass diese verschieden gesättigt sind (intensität) die von 0-255 pro Grundfarbe sein sollte.
    wie wandel ich jetzt den BMP Code so um, dass ich sehen kann wie hoch die intensität pro farbe ist?

    Das hängt von der Farbtiefe (biBitCount) ab, die du verwendest. Bis 8 Bit hast du eine Farbtabelle, in der die Zuordnungen stehen. Bei 16 Bit hast du drei Farbmasken, mit denen du die Werte verknüpfen mußt, um die Farbanteile zu erhalten. Bei 24 und 32 Bit folgen Blau, Grün und Rot (je ein Byte, bei 32 Bit noch der Alpha-Kanal).

    Und ja, normalerweise reicht der Speicherplatz aus, um ein komplettes Bitmap einlesen zu können. Wenn du Angst hast, könntest du das Bild auch zeilenweise lesen und verarbeiten.

    PS @std:: - google mal nach "C++ Namensraum".



  • CStoll schrieb:

    2. ich weis auch dass ein Pixel aus den 3 Grundfarben besteht (Rot, Grün und Blau) und dass diese verschieden gesättigt sind (intensität) die von 0-255 pro Grundfarbe sein sollte.
    wie wandel ich jetzt den BMP Code so um, dass ich sehen kann wie hoch die intensität pro farbe ist?

    Das hängt von der Farbtiefe (biBitCount) ab, die du verwendest. Bis 8 Bit hast du eine Farbtabelle, in der die Zuordnungen stehen. Bei 16 Bit hast du drei Farbmasken, mit denen du die Werte verknüpfen mußt, um die Farbanteile zu erhalten. Bei 24 und 32 Bit folgen Blau, Grün und Rot (je ein Byte, bei 32 Bit noch der Alpha-Kanal).

    Und ja, normalerweise reicht der Speicherplatz aus, um ein komplettes Bitmap einlesen zu können. Wenn du Angst hast, könntest du das Bild auch zeilenweise lesen und verarbeiten.

    PS @std:: - google mal nach "C++ Namensraum".

    also vom BMP her ... es reicht das 24 Bit format von paint, schließlich sind wir noch blutige Anfänger.

    hab ma nach "C++ Namensraum" gegoogelt und naja so ganz versteh ichs net is immer auf "neunmalklug" beschrieben anstatt das die es mal für jeden verständlich machen aber naja egal.

    auf jeden fall schon ma thx für die antworten

    P.S. sehe ich das richtig?
    der File Header und der Info Header sind insgesammt 54 byte groß und der rest ist ALLES nur Bildmaterial?
    Und wenn ich jetzt die Header in ein Array packen würde, dann von stelle 10-13 auslese hätte ich (quasi) die "koordniate" für den beginn der bilddatei?



  • der File Header und der Info Header sind insgesammt 54 byte groß und der rest ist ALLES nur Bildmaterial?

    Nope.
    Am besten du lädst erstmal das gesamte File auf einmal in den Speicher. Der Anfang des Files kann so aussehen:

    Version 1:
    BITMAPFILEHEADER
    danach
    BITMAPCOREHEADER
    danach *irgendwann* die Bilddaten.

    Version 2:
    BITMAPFILEHEADER
    danach
    BITMAPINFOHEADER
    danach *irgendwann* die Bilddaten.

    Ob eine BITMAPCOREHEADER oder BITMAPINFOHEADER Struktur enthalten ist bekommst du über das erste DWORD dieser beiden Strukturen raus, das enthält nämlich bei beiden die Grösse der Struktur (und die ist unterschiedlich). In der Struktur findest du dann die Grösse des Bildes (Breite, Höhe) und die Bitanzahl (Farbtiefe), und (nur BITMAPINFOHEADER) Informationen über evtl. verwendete Kompression etc.. Das prüfst du alles ob es ein Format ist mit dem du umgehen kannst, also 24 Bit, keine Kompression, und ob die Grösse des Bildes ausreicht um die Daten darin zu verstecken.

    Schliesslich findest du über das bfOffBits in der BITMAPFILEHEADER Struktur den Offset der Daten im File heraus. Also einfach einen char* auf den Anfang der Datei (= Anfang der BITMAPFILEHEADER Struktur) holen, und bfOffBits draufaddieren, dort stehen die Daten. Bei einem 24 Bit Bild stehen dort einfach immer 3 Bytes pro Pixel, also eine Zeile besteht auf Breite * 3 Bytes. Dabei ist noch zu beachten dass der Offset der nächsten Zeile immer auf eine Gerade Zahl aufgerundet wird falls nötig. Ist komisch und stammt aus der Zeit wo das "Maschinenwort" auf PCs noch 16 Bit war, aber egal, ist eben so.

    Im Prinzip kannst du dann schon Bit für Bit deine Daten reinklatschen, wobei du einfach das LSB überschreibst, also auf den alten Wert keinerlei Rücksicht nimmst. Ich würde die Daten vorher noch irgendwie verschlüsseln, den Key (den du am besten zufällig erstellst) kannst du ja einfach vor die Daten dranpacken damit es danach ohne Key wieder "entpackt" werden kann. Egal ob verschlüsselt oder unverschlüsselt musst du noch einige weitere Dinge tun: 1) die Grösse mit abspeichern, das Bild wird wohl kaum immer genau gleich viel Daten aufnehmen können wie du verstecken möchtest sondern meistens mehr -- also muss die Grösse abgespeicher werden. Eine Prüfsumme muss auch noch mit rein, damit du rausbekommen kannst ob das "einfach nur ein Bild" ist, oder ob da Daten drinnen versteckt sind. Weiters würde ich in die Pixel die übrigbleiben Zufallsdaten reinschreiben -- sonst könnte man evtl. was sehen, würde komisch aussehen wenn z.B. im oberen Drittel des Bildes ein leichtes Hintergrundrauschen zu sehen wäre, darunter aber nichtmehr bzw. nur viel weniger. Ok, Dateiname hab' ich noch vergessen, den kopierst du auch irgendwo rein.

    Den ganzen Datenblock, also Grösse, Name, Checksumme etc. würde ich erstmal so zusammenbasteln, und DANN erst verschlüsseln. Dann Key vorne dran packen, und Rest mit Zufallsdaten auffüllen. Und dann eben Bit für Bit rein ins Bild.

    Die Bytes die u.U. beim "Aufrunden auf gerade" übersprunden werden würde ich nicht anrühren. Die sollten eigentlich 0 sein (müssen aber AFAIK nicht), und es wäre doof dort "Spuren zu hinterlassen".

    Nachdem du das gemacht hast kannst du den Block im Speicher einfach wieder 1:1 in eine Datei schreiben, du hast ja nur Bilddaten modifiziert, und alle anderen Dinge wie Header etc. bleiben ja unverändert.

    Ahja, die "Intensität der Farbe" ist einfach das entsprechende Byte für Rot, Grün oder Blau. Die Farbe ergibt sich aus der Mischung der Primärfarben im Verhältnis der 3 Bytes (bzw. genauergenommen müsstest du vorher noch eine Gammakorrektur von ~2.2 drübermachen, aber das ist erstmal egal. Die "empfundene" relative Intensität ist inetwa analog zum gepseicherten Wert, und das reicht). Also 50 Rot, 0 Grün, 100 Blau ist ein Dunkelviolett, 255 Rot, 0 Grün, 255 Blau ist ein helles Lila etc. Kann dir aber egal sein, solange nicht der Bildinhalt auf "Eignung" überprüft werden muss -- du überschreibst ja einfach nur das LSB jedes Bytes und damit hat's sich.

    Wie man allerdings prüfen soll ob ein Bild "geeignet" ist... naja, gross genug muss es sein (klar), aber wenn der Bildinhalt auf "Eignung" überprüft werden soll wird es komplizierter, da müsste man dann irgendwie "abschätzen" ob ein "zufälliges" Rauschen im LSB auffallen würde. Ein paar einache Tests kann man natürlich machen, wie die Anzahl der gesamt verwendeten eindeutigen Farben zählen (dürfen nicht zu wenig sein), gucken ob es grössere Fälchen mit exact gleicher Farbe gibt, und ob das Bild nicht viel viel zu dunken ist, bzw. die Originaldaten im LSB nicht zu regelmässig. Natürlich könnte man dann noch ein paar Dinge tun um die neuen LSB Werte besser an den Bildinhalt anzupassen, aber das wäre wohl etwas kompliziert - nicht zuletzt weil das ganze ja auch reversibel bleiben muss.

    Ist eigentlich ganz einfach, ist in ein paar Tagen zu erledigen, auch wenn man nicht 8 Stunden am Tag dran arbeitet. Als Programmieranfänger wirst du entsprechend länger brauchen, aber auch kein Monat oder so.

    Was "Programmschnippsel" angeht schliesse ich mich aber hier der Allgemeinheit an und sage: wenn du Programmieren lernen sollst, dann werd' ich dir hier nix vorkauen. Wie man was inetwa macht habe ich beschrieben, wenn du bei einem bestimmten Punkt Probleme mit der Umsetzung hast stell spezifische Fragen, und es wird dir "mit an Sicherheit grenzender Wahrscheinlichkeit" jmd. antworten 🙂



  • hallo zusammen ich beschäftige mich auch gerade mit dieser geschichte...
    habs auch sowit, dass ich meine daten verstecke...
    das problem was ich bei der ganzen sache allerdings habe ist folgendes:
    zuerst öffne ich meine datei, dann lade ich jeden char in einen vector <int> (mit der summe aller chars als größe) und verarbeite dann den entsprechenden teil (sprich bmp datenteil ohne header) byte für byte indem ich das LSB änder...
    das ganze stelle mich aber vor des problem, dass mein programm eine halbe stunde braucht, weil es bei jedem bit den int wert erst in Bin umwandelt dann das LNB ändert und dann wieder zurücksetzt... dann alles aus dem vector wieder in die bmp schreiben....
    das muß doch auch schneller gehen oder?
    aber wenn ich es mit einem int array mache kann ich die länge auch dynamisch ändern?

    vielen dank schon einmal für die posts



  • Wozu erst umwandeln "in Bin" (was genau meinst du damit?) - der Computer rechnet doch sowieso binär. Da kannst du die LSB's einfach mit x|=1;[c] setzen bzw. mit [c]x&=~1; zurücksetzen.



  • ups 😛 hmmm das ist wohl echt mal eine eher dumme frage von mir gewesen....
    *scharmesröte


Anmelden zum Antworten