IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C Discussion :

Stéganographie, bitmap et offset


Sujet :

C

  1. #1
    Candidat au Club
    Homme Profil pro
    Inscrit en
    Mars 2011
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Mars 2011
    Messages : 8
    Points : 4
    Points
    4
    Par défaut Stéganographie, bitmap et offset
    Bonjour à tous,

    désirant coder mon propre logiciel de stéganographie, avec lequel il serait possible de cacher un message dans une image (méthode Least Significant Bit), je souhaiterais savoir s'il est possible en C via un appel-système ou autres de connaître les différentes caractéristiques des fichiers images devant contenir les messages cachés. Dans un premier temps, seul le format bitmap (bmp) est accepté pour les images.

    Avant toutes choses, j'ai voulu tester manuellement la méthode LSB: j'ai donc édité un fichier bmp en modifiant (ou non) le bit de poids faible de chaque octet en fonction du message à cacher. Il s'est avéré qu'une modification intempestive et incontrôlée de ce genre a corrompu le fichier (écrasement de certains bits du/des en-tête(s) du fichier), devenu illisible. J'en ai donc conclu qu'une méthode telle que LSB était valable à condition que seuls les octets correspondant aux pixels de l'image puissent être modifiés.

    Ainsi, après plusieurs analyses de différents fichiers bmp et quelques recherches sur la toile, j'ai pu observer que l'offset de l'image (i.e. l'adresse du 1er octet correspondant au 1er pixel de l'image) est donné dans l'en-tête du fichier, codé sur 4 octets (les octets 10, 11, 12 et 13 de l'en-tête du fichier).

    J'ai donc voulu, en utilisant des fonctions/appels-systèmes comme open(), read(), lseek() et quelques buffers, extraire 'manuellement' l'offset de l'image et positionner le curseur du fichier bmp sur le 1er octet correspondant au 1er pixel, afin de pouvoir masquer le message sans endommager le fichier. Après quelques heures de réflexion, cette entreprise m'apparait plus laborieuse qu'efficace.

    Je souhaiterais donc savoir s'il existe un moyen plus propre et plus efficace concernant l'extraction de l'offset et le positionnement du curseur.


    Par ailleurs, étant un jeune disciple de la stéganographie (et de l'informatique en général) mais plutôt passioné, tous les bon tuyaux m'intéressent. On en apprend tous les jours, tous vos conseils sont les bienvenus (qu'ils portent ou pas sur le sujet du topic) .


    Merci à tous pour votre attention et votre patience (long message.. )


    Heisen

  2. #2
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 369
    Points : 23 623
    Points
    23 623
    Par défaut
    Bonjour,

    C'est bien de cette manière que l'on procède pour traiter tous les fichiers, et tes images *.BMP en font partie. Toutefois, tu peux utiliser dans une certaine mesure le File Mapping, comme mmap(), pour demander au système de projeter directement l'image de ton fichier en mémoire. Tu n'auras plus qu'à aller lire les bons offsets.

  3. #3
    Expert éminent sénior

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 603
    Détails du profil
    Informations personnelles :
    Âge : 66
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 603
    Points : 17 913
    Points
    17 913
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par Heisen Voir le message
    Je souhaiterais donc savoir s'il existe un moyen plus propre et plus efficace concernant l'extraction de l'offset et le positionnement du curseur.
    A mon avis, pour faire quelque chose de général, je commencerais par faire une fonction de lecture qui prend un nom de fichier et en ressort le(s) buffer(s) de pixels directement, et une d'écriture kif-kif.

    Comme ça de l'extérieur tu ne vois que ton buffer à traiter, indépendamment du format. Ensuite, dans les routines de lecture et d'écriture, tu te préoccupes du format, et décode (par exemple en soirtant la taille de l'entête).

    Je verrais donc :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    lit-fichier
        lit-bmp
        lit-jpeg
        ...
     
    ecrit-fichier
       ecrit-bmp
       ecrit-jpeg
       ...
     
    encode-message
     
    main
       lit-fichier
       encode-message
       ecrit-fichier
    Suivant les formats, l'extraction de l'entête et/ou le parsing du(des) buffers sera différent. En général les fonctions lisent soit d'un coup en mémoire tout le fichier sous forme de bytes, et analysent, soit lisent byte par byte, et décodent. Et il y a des bibliothèques libres qui font déjà ça (par exemple libjpg ou libtiff ou gd (pour gif))
    "Un homme sage ne croit que la moitié de ce qu’il lit. Plus sage encore, il sait laquelle".

    Consultant indépendant.
    Architecture systèmes complexes. Programmation grosses applications critiques. Ergonomie.
    C, Fortran, XWindow/Motif, Java

    Je ne réponds pas aux MP techniques

  4. #4
    Candidat au Club
    Homme Profil pro
    Inscrit en
    Mars 2011
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Mars 2011
    Messages : 8
    Points : 4
    Points
    4
    Par défaut
    merci pour vos réponses,

    je vais donc me documenter sur mmap et sur les bibliothèques libres, puis adapter mon code. Je reviendrai si j'ai d'autres questions

    Cordialement,
    Heisen.

  5. #5
    Candidat au Club
    Homme Profil pro
    Inscrit en
    Mars 2011
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Mars 2011
    Messages : 8
    Points : 4
    Points
    4
    Par défaut
    Amis noctambules, bonsoir

    j'ai donc effectué quelques nouvelles recherches concernant mmap et les bibliothèques libres (notamment libjpeg); ces deux méthodes semblent bien respecter mes attentes dans la réalisation de mon programme.

    Si j'ai bien compris:

    - d'une part, mmap permet de placer un fichier en mémoire centrale et de le manipuler (octet par octet dans notre cas) via un pointeur; par cette méthode il est donc possible de récupérer les informations ( 'manuellement' ) du fichier spécifié;
    - d'autre part, en utilisant des bibliothèques libres, des fonctions et structures déja disponibles (par exemple jpeg_read_header() dans libjpeg) permettent d'obtenir directement (et plus simplement) les informations du fichiers.

    Par ailleurs, j'ai cru comprendre que mmap causait un problème de portabilité, ne faisant pas partie des fonctions disponibles dans la bibliothèque standard du C. Bien que très interessé par l'aspect portabilité d'un programme, je ne suis encore qu'un novice dans ce domaine. Je n'ai pas l'intention ni la capacité de créer un programme ultra-portable, cependant je souhaiterais qu'il le soit le plus possible. Si vous avez des conseils, ils sont toujours les bienvenus.

    Enfin, ce projet n'étant qu'un projet personnel, je souhaiterais en profiter pour acquérir un maximum de nouvelles connaissances (tout est relatif, bien sûr..). Je me demande donc quelle est la méthode la plus intéressante à approfondir :
    - mmap, qui me ferait travailler sur la manipulation bas-niveau d'un fichier en C (et d'autres aspects qui m'échappent certainement)
    - les bibliothèques libres, présentant un travail 'tout cuit' et qui me ferait plus pencher sur un aspect d'intégration/adaptation de code.


    Merci encore pour votre attention.

    Bien cordialement,
    Heisen

  6. #6
    Expert éminent sénior

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 603
    Détails du profil
    Informations personnelles :
    Âge : 66
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 603
    Points : 17 913
    Points
    17 913
    Billets dans le blog
    2
    Par défaut
    personellement je ne vois pas l'utilité de mmap...

    Dans la plupart des librairies disponibles la lecture se fait via un fgetc ou équivalent.

    A la limite on peut faire l'équivalent d'un mmap qui est simplement trouver la taille totale du fichier (via fstat) et toute lire d'un coup via un fread dans un buffer de bytes..

    Mais la plupart du temps la lecture/écriture est faite et correcte...
    "Un homme sage ne croit que la moitié de ce qu’il lit. Plus sage encore, il sait laquelle".

    Consultant indépendant.
    Architecture systèmes complexes. Programmation grosses applications critiques. Ergonomie.
    C, Fortran, XWindow/Motif, Java

    Je ne réponds pas aux MP techniques

  7. #7
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2010
    Messages
    40
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2010
    Messages : 40
    Points : 40
    Points
    40
    Par défaut
    Bonjour

    Regarde à tout hasard du côté d'OpenCV, si cela peut t'aider.

  8. #8
    Nouveau Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2011
    Messages
    1
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2011
    Messages : 1
    Points : 1
    Points
    1
    Par défaut
    Salut !

    Je tombe par hasard sur ce topic, donc bon, je ne sais pas trop si ça peut encore t'être utile, mais bon.
    Alors, comme tu le sais probablement, un fichier BMP est constitué d'un en-tête et des données de l'image. Les fichiers bitmap commencent toujours pas "BM", suivi des informations d'en-tête, puis des données de l'image.
    Pour connaître les infos d'en-tête, tu peux utiliser une structure correspondant aux données que tu retrouves dans l'en-tête, que tu remplis en lisant le fichier à partir du troisième char.

    Voici un petit programme en C permettant de lire les données d'en-tête et de les afficher dans la console:

    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    #include <string.h>
    #include <math.h>
     
     
    typedef struct  
     {
    	long TailleFichier;   // taille totale du fichier
    	long Reserves;        // 4 octets reserves usage futur
    	long PositionImage;   // position de l'image dans le fichier (déplacement
                          // par rapport au début du fichier)           
    	long TailleEntete;    // taille de l'entête d'information (ce champ + ce qui suit
    	long Largeur;         // largeur de l'image en pixel
    	long Hauteur;         // hauteur de l'image en pixel
    	short NombrePlan;     // nombre de plans utilises par la carte d'affichage  
    	short NombreBit;      // nombre de bits utilises pour coder un pixel  
    	long TypeCompres;     // type de compression utilisee (0 => RIEN)
    	long TailleImage;     // taille de l'image (hauteur * largeur)
    	long ResolutionH;     // resolution horizontale en pixel par metre
    	long ResolutionV;     // resolution verticale en pixel par metre
    	long NombreCouleur;   // nombre de couleurs => C dans le tableau
    	long CouleurImport;   // nombre de couleurs importantes
     }EnteteBmp;
     
     
    // Declaration des prototypes
    	void	affiche_params_structEnteteBMP( EnteteBmp argEntete );
     
    int main(void)
    {
    	FILE* image = NULL;
     
    	char firstChars[3] ; 	// Obligatoirement « BM » pour du BMP
    	EnteteBmp enteteStruct;			// La structure contenant les donnees d'entete
     
    	char* nomFichierSource = "image.bmp";
     
     
    	// Ouverture du fichier source
    		image = fopen( nomFichierSource,"rb");
    		if( image == NULL) // Si l'image n'a pas pu etre ouverte
    		{
    			printf("Erreur d'ouverture du fichier %s:\n", nomFichierSource);
    			perror("Error");
    			exit( __LINE__ );
    		}
     
    	// Lecture des deux premiers chars
    		fread( firstChars, sizeof( char ), 2, image );
    		firstChars[2] = '\0';
     
    	// Verification des firstChars	
    		if( strcmp( firstChars, "BM" ) != 0 )
    		{
    			printf("Le fichier %s n'est pas une image BMP !!\n", nomFichierSource);
    			fclose( image );
    			exit( __LINE__ );
    		}
     
     
    	// Lecture de l'en-tête
    		fread( &enteteStruct, sizeof( EnteteBmp ), 1, image );
     
    	// Affichage des parametres
    		affiche_params_structEnteteBMP( enteteStruct );
     
    	// Fermeture du fichier source
    		fclose( image );
     
     
    	return EXIT_SUCCESS;
    }	
     
    void affiche_params_structEnteteBMP( EnteteBmp argEntete )
    {
    	printf("Taille fichier \t= %ld\n", argEntete.TailleFichier );
    	printf("Reserves \t\t= %ld\n", argEntete.Reserves );
    	printf("Position image \t= %ld\n", argEntete.PositionImage );
    	printf("Taille entete \t= %ld\n", argEntete.TailleEntete );
    	printf("Largeur \t\t= %ld\n", argEntete.Largeur );
    	printf("Hauteur \t\t= %ld\n", argEntete.Hauteur);
    	printf("Nombre plans \t= %hd\n", argEntete.NombrePlan );
    	printf("Nombre bits \t= %hd\n", argEntete.NombreBit );
    	printf("Type Compress. \t= %ld\n", argEntete.TypeCompres );
    	printf("Taille Img \t\t= %ld\n", argEntete.TailleImage );
    	printf("Resolution H \t= %ld\n", argEntete.ResolutionH );
    	printf("Resolution V \t= %ld\n", argEntete.ResolutionV );
    	printf("Nombre de couleurs \t= %ld\n", argEntete.NombreCouleur );
    	printf("Couleur importantes \t= %ld\n", argEntete.CouleurImport );
    	fflush( stdout );
    	return;
    }

    Pour info, je l'ai testé sous Linux, donc il faudra l'adapter si tu es sous Windaube (les system("PAUSE"); qui vont bien... )

    J'espère que ça pourra t'aider, j'ai essayé de commenter le code, mais si il y a une question, pas de soucis, et si il y a des améliorations possibles, n'hésitez pas à m'en faire part !

    Allez, @+!

  9. #9
    Membre chevronné
    Profil pro
    Inscrit en
    Août 2006
    Messages
    1 104
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 1 104
    Points : 1 750
    Points
    1 750
    Par défaut
    Voici un petit programme en C permettant de lire les données d'en-tête et de les afficher dans la console:
    Le problème, c'est que ce code n'est pas portable, pour des questions de taille de type (qui ne sont pas figés, en C), d'alignement et de boutisme.
    Ca peut marcher tout comme ça peut ne pas marcher.

Discussions similaires

  1. Modifier l'offset d'un bitmap en python
    Par jadlab dans le forum Général Python
    Réponses: 5
    Dernier message: 21/09/2011, 08h19
  2. Lecture et interprétation d'un offset d'une bitmap
    Par nico92856 dans le forum VB 6 et antérieur
    Réponses: 10
    Dernier message: 11/03/2006, 17h01
  3. Pb Lecture de bitmap monochrome
    Par Loïc38 dans le forum C++Builder
    Réponses: 4
    Dernier message: 02/07/2002, 18h24
  4. Lecture d'une image bitmap
    Par Geronimo dans le forum x86 32-bits / 64-bits
    Réponses: 18
    Dernier message: 28/06/2002, 12h01
  5. Comment faire pour créer un bitmap
    Par GliGli dans le forum C++Builder
    Réponses: 2
    Dernier message: 24/04/2002, 15h41

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo