[C(++)]Steganographie en plusieurs étapes

Bonjour,

j’ai encore besoin de vos lumières z’éclairées. Je cherche à faire un programme léger et simple de stéganographie, assez ciblé: cacher une image en bmp 24 bits, dans une autre du même acabit. La plupart des source codes précédement trouvés ne proposaient de ne cacher dans des images que des fichiers texte. Ne sachant pas vraiment comment extraire les octets d’une images pour les copier dans un point texte, et encore moins accomplir l’action inverse T_T.

L’idée de base est de prendre deux image bmp 24bits, une petite (qu’on appellera pour l’occasion PT) et une grande (GD) au moins 4 fois plus grande. explication du pourquoi 4 fois: chaque octet de couleur de chaque pixel sera divisé en paire de bit, ces paires remplaçant alors les deux bits de poids faibles de chaque octet de couleur des pixels de GD. Agnahagh? Explication²:
Premier pixel de PT:
R:00011011
V:11001100
B:10011110

Premier pixel de GD:
R:1100100100
V:1001010001
B:1101001010
Second pixel de GD:
R:1101001011
V:1010011111
B:1001000000
Troisième pixel de GD:
R:1001011011
V:0010010100
B:1000010110
Quatrième pixel de GD:
R:1010011111
V:0010110111
B:1000011010

Bref, pour l’heure j’ai gratter un bout de code permettant de copier une image. Juste ça. Et là tout dérape!
Le code (ci dessous) ne copie qu’une bande de l’image, en bas O_o:
(image reconverties en jpg pour pouvoir les poster)
Image originale:
[attachment=1330:Copie_de_chat.JPG]
Image “copiée”:
[attachment=1331:Copie_de_chat2.JPG]
(On retourve le bas noir et le bas des flèches blanches, il suffit d’ouvrir la photo dans un autre fenêtre ^^)
En gros 10% de l’image…

[codebox]#include
#include
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>

using namespace std;

struct y
{
unsigned char R;
unsigned char V;
unsigned char B;
}pixel;

struct x
{
unsigned char u;
unsigned char v;
unsigned char w;
}header;

int image()
{
FILE *fpbin,*finbin;
unsigned char moyenne;
int x,y,i;
unsigned char j;
fpbin = fopen(“image.bmp”,“r”);
printf(“Lecture de l’image\n”);
finbin = fopen(“image2.bmp”,“a+”);
printf(“Creation de l’image2\n”);
printf(“entete installée\n”);
for(i = 0;i<18;i++)
{
header.u = fgetc(fpbin);
putc(header.u,finbin);
header.v = fgetc(fpbin);
putc(header.v,finbin);
header.w = fgetc(fpbin);
putc(header.w,finbin);
}
printf(“Entete terminée\n”);
for(x = 0;x<(450000);x++)
//Voir plus bas pour le pourquoi du 450000
{
pixel.R = fgetc(fpbin);
putc(pixel.R,finbin);
pixel.V = fgetc(fpbin);
putc(pixel.V,finbin);
pixel.B = fgetc(fpbin);
putc(pixel.B,finbin);
}
fclose(fpbin);
fclose(finbin);
printf(“Ca a marché\n”);
return 0;
}

int main(int argc, char *argv[])
{
if(argc != 3)
{
printf(“Erreur pas d’arguments\n”);
return 1 ;
}
image();
return 0;
}[/codebox]
//L’image du chat fait 1350054 octets, -54 pour le header bmp, le tout par 3 (3couleurs), ce qui nous laisse 450000 triplettes d’octets à copier).
//Pour l’heure le programme ne se fera que sur cette image, je ne suis pas sûr de savoir comment compter les octets d’une image,
//peut être avec un while(1), un tableau, et un break, à méditer…
//A noter, que le programme ne “copie l’imagee” que si l’on rentre un valeur entre 10% et 1000%, soit ici, 45000 et 4500000, tout en gardant la même image fianle. Etrange…

Voilà, là est mon problème. Je n’arrive à pas comprendre que l’imagee ne soit que partiellement copiée, et ce que par le bas.
De plus, cette proportion de recopiage (environ 10%), se retrouve quand j’essaye de copier d’autre images (en changeant la valeur de 450000 évidement ^^)

Auriez vous l’oeil du tigre, l’esprit du homard austral et sauriez vous me dire où j’ai pêché?

Merki d’avance

Capty

J’ai pas encore testé ton code, mais… tu veux vraiment te relouter a lire toi-même ton BMP?
Ca a été fait des centaines de fois par d’autres personnes, pas besoin de reinventer la roue.

Avec une recherche rapide, j’ai deja trouvé 3 libs qui font ca.
Presque toutes fonctionnent sur le meme modele:

Une fonction du type:

Image* Load(char* filename)
pour charger ton fichier
Image est typiquement une struct avec toutes les infos (taille, bits par pixel, etc.)

Ensuite tu as un GetData() ou qqch du genre pour recuperer un pointeur sur les pixels. Tu peux bien sur modifier les valeurs dans ton Image en memoire.

Finalement, un Save(Image* img, char* filename), pour sauver ton image.

Ca me parait plus simple que de bouffer du header BMP toi-meme, et ca evite de te taper un truc que qqn a fait pour toi :slight_smile:

La solution la plus complete que j’aie trouvée est:
DevIL
mais c’est aussi la moins simple d’utilisation.

Sinon, libbmp est ridiculement simple, commentée en francais, mais aucune doc, et pas tres polyvalent.

Ne cherche pas exactement le nom des fonctions que j’ai ecrites, bien sur, c’est juste pour l’exemple.

Desole de ne pas repondre directement, je jette un coup d’oeil a ton code quand j’ai plus de temps.

Merki pour le lien de libbmp :slight_smile:

Le programme est écrirt très clairement et marche très bien (mise à part une erreur du type "voulez vous envoyer un rapport), et qui ne gène en rien, bizare…).
Je vais partir de ça pour mon projet.

Si jamais z’avez des conseils, astuces, autre, je prends aussi :crying:

AU titre, j’ai cru que c’était un thread de Bussière :slight_smile:

Pourquoi tu ouvres tes fichiers en mode texte ? Fais attention à tester la valeur de retour de fopen() et le return 1; dans main() c’est pas standard. :slight_smile:

Son code est en fait clairement du C, ou presque quoi donc standard ou pas je crois qu’il s’en tape.

piaz

Beuh kékila mon titre?
En fait j’ai été interrompu pendant que je l’écrivais, et au final, ça donne un soupçon de mystère ^^

DaP

C’était une des principales idées: copier le code de l’image dans un fichier .txt, mettre le header de côté, et remplacer au fur à mesure toutes les quatrième paire d’octets par le code de la petite image (moins le header). Et pouf ça aurait fait des chocapics (comme dans la pub).

Le C++ autorise à utiliser les fonctions du C (C90 au moins), je crois que return 1 n’est pas portable en C++ non plus mais je peux me tromper. En tout cas dans du code C ce serait plus cohérent d’utiliser EXIT_FAILURE, et il n’y a pas de raison pour ne pas suivre la norme à part si on veut passer pour un kéké.

Le mode texte est prévu pour lire des caractères de façon portable, il faut t’attendre à des trucs louches si tu l’utilises avec un fichier qui contient des données brutes. Par exemple sous Windows 0x0D0A va être considéré comme un seul caractère (le saut de ligne), 0x1A arrêtera la lecture (caractère EOF). Sur un autre système ce sera interprété complètement différemment.

Lundi matin, on reprend dans la joie et la bonne humeur ^^

En effet, j’avais pas pensé aux différents types « d’écritures »

Mais on ne peut pas demander, en C (++), d’afficher la couleur d’un pixel en un tableau d’un octet présenté sous la forme de 8bits, directement dans le programme, sans dépendre d’un fichier externe.

Up.
Peut on partager un octet en paire de bits?
Ca pourrait m’aider pour la suite. En C, encore ^^

Chuis un peu à la ramasse T_T

Edit:
Tiens, sinon, existerait il un type (int, float ou je ne sais quoi) qui tiendrait sur deux bits précisement? Comme ça, hop un p’tit fread en boucle et c’est parti!

Piaf:
Bon apparement les types se tiennent sur minimum 1 octet. Galère!

[quote=“Le-Captain, post:10, topic: 46698”]Piaf:
Bon apparement les types se tiennent sur minimum 1 octet. Galère![/quote]
Sur un char (la plus petite unité adressable par le système), et le nombre de bits par char est donné par la macro CHAR_BIT dans limits.h, mais oui c’est souvent huit bits.
Pour ton problème utilise les champs de bits ou les opérateurs binaires. Tu n’as pas l’impression que tu devrais apprendre à utiliser le C avant de te lancer dans des projets comme ça ?

J’ai déjà trois ans de C derrière moi. Mais il apparait clairmeent qu’on a survolé que les bases (IUT GEII, où le premier I est pour informatique, allez savoir pourquoi…).

Et pusi à part cette petite embûche, ça m’avait l’air relativement simple.

Ou de la faire en autre chose qu’en C… c’est etre maso la quand meme…

Dieu ce que je suis…

Le dirlo est arrivé pour nous parler des projets, et discuter d’un epu de tout. Et il m’a donné un axe de solution! Utiliser des masques avec les opérateurs & et OU. Tout connement. J’ai honte.

Je vous tiens au jus.

C’est ce que je voulais dire avec les opérateurs binaires, mais ça aurait été sûrement plus correct de dire bit à bit. Sinon tu as aussi les champs de bits.

struct joliOctet { unsigned int b0b1:2; unsigned int b2b3:2; unsigned int b4b5:2; unsigned int b6b7:2; };

Pour ce qui est des strucutres, c’est ce que m’avais initialement proposé le dirlo, mais au final ça collait pas.

Hop d’ailleurs, il se pointe, je vais voir ça avec lui.

Up du lundi matin (le dernier snif).

Je savais que le Bitmap se lisait de gaauche à droite, de bas en haut, et en bleu/vert/rouge (Mr Bitmap, je vous hais cordialement), mais ce site m’étonne.
Le header de l’exemple indique un codage en 24 bits, soit 3 octets, mais la couleur bleu se retrouve (par exemple) codée en tant que FFOOOO (encore en BVR), soit sur 6 bits.
Quelqu’un aurait une explication métaphysique?

Ca pourrait expliquer pourquoi je me retrouve avec des groupes de pixels cyan, jaunes, rouge, bleu et noirs (par deux, pour cete dernière couleur), dans mon BMP contenant une image cachée.

FF ? 6 bits ?
tu es sur de ton coup la ?
0xFF, 255 donc, sur 6 bits ?
donc 0xFF FF FF, ca fait 18 bits ?
moi a ta place je recompterais tes bits…

Gneuh? J’ai du mal m’exprimer en fait ^^
Il me dit coder les couleurs sur 24 bits, donc 3 octets, hors, quand je regarde la description des couleurs dans le code, (voir le lien de l’exemple), chaque couleur est sur deux octets, le pixel faisant donc 6 octets, soit 48 bits. Et non 24.
[attachment=1339:test.JPG]
Voilà ce que ça me donne.

J’hésite à mettre le code, car iil prend quand même de la place.

bah non : FF, 255, c’est 8 bit, donc un octet.
Si tu veux du blanc, tu fais 0xFF FF FF (soit tout a fond), si tu veux du rouge 0x0000FF, et si tu veux du violet tu fais 0xFF00FF, donc une couleur, 3 octets. Chaque octet decrit une composante, et non pas, comme tu as l’air de le comprendre: 3 octets, une composante.
C’est plus clair, la ?