Cacher un fichier dans une image bmp (8, 16, 24 et 32 bits). stéganographie. [borland 5, bcb]

Description

Vous souhaitez cacher un fichier quelconque sans que personne ne puisse soupçonner son existence. Ce programme montre comment cacher n'importe quoi dans un document au format BMP (Bit Map).
Plusieurs programmes similaires existes déjà sur ce cite, cependant aucun ne fait tous ceci :
- Integration dans une image BMP 8, 16, 24 ou 32 bits.
- Convertion dans les formats connus.
- Interface graphique.
- Calcule de l'alteration de l'image.
- Espacement régulier des informations dans les pixels en fonctions de l?espace libre dans l'image.
- Detection d'images stéganographié
- Aperçu de l'image final.
- Zoom sur l'images

Un pixel est défini selon trois composantes : l'intensité de bleu, vert et rouge (les trois couleurs primaires en optique). Parfoit, le pixel est composé d'une quatrième composante : la transparence.
On code ces informations chromatiques dans un certain nombre de bit. Ainsi, une image est qualifiée de N bits (où N est le nombre de bit) en fonction du nombre de bit qui lui sont allouée pour coder les couleurs.
Les images Bitmap peuvent coder les couleurs sur :
- 1 bit (Noir et Blanc)
- 4 bits (16 couleurs prédéfinies. C'est une forme de compression.)
- 8 bits (256 couleurs prédéfinies. Idem.)
- 16 bits (65536 couleurs)
- 24 bits (16777216 couleurs)
- 32 bits (4294967296 couleurs)

Pour plus d'information sur le principe de la stéganographie dans les images allez voir le TPE de TheWhiteShadow contenu le zip à l'adresse suivante :
http://www.cppfrance.com/code.aspx?ID=22340

Pour plus d'information sur le codage d'un bitmap win32 reportez vous au fichier "Format d'un bitmap win32.txt" dans mon zip.

Voici comment integrer un fichier dans un bitmap.
Attention, le code qui suit permet seulement de simplifié la lecture du code et ainsi de mieux visualisé la partie la plus importante. Il est impossible de bien intégrer ou extraire un fichier avec le code qui suit.
Pour le code correcte, le chargement de l'image et du texte, les calculs d'altérations de l'image, l'interface graphique et l'aperçu consulter le zip.

Source / Exemple :


char *ImgO, *ImgM; // Image originale et modifier
char *DataAdd; // Fichier quelquonque inseré dans l'image
char *cSave; // Chaine qui sera sauvegardée
unsigned long lenImg, lenData; // Nonmbre d'octet dans l'image et dans le fichier
unsigned long ImgHaut, ImgLarg; // Hauteur et largeur de l'image
unsigned long ImgNbOctet; // Taille du fichier
unsigned long ImgDebPixel; // Position du premier pixel
unsigned long lenSave; // Nombre d'octet à sauvegarder
int ImgResol; // Resolution de l'image
char nbit; // Nombre de bit à integrer dans un octet

void __fastcall TTexteChild::Integrer(void)
{
unsigned long length, ind;
unsigned char DA, O1, O2, CT, ChT[3], X, ibit, p, i;

    p = (unsigned char) Puissance(2,nbit);

    ImgM = new char [lenImg];
    lenSave = lenImg;

    for (length=0;length<ImgDebPixel;length++) {
        ImgM[length] = ImgO[length];
    }

    ind = 0;
    ibit = 0;

    if ((ImgResol == 8) || (ImgResol == 24) || (ImgResol == 32)) { // format 8, 24 ou 32 bit

        for (;length<lenImg;length++) {
            DA = ImgO[length];

            if (ind <= lenData){
                CT = GetMessag(ind,ibit);

                DA = (DA & ~p) | CT;
            }

            ImgM[length] = DA;
        }
    } else if (ImgResol == 16) { // format 16 bit

        for (length=ImgDebPixel;length<lenImg;length+=2) {
            O1 = ImgO[length+1];
            O2 = ImgO[length];

            X = 0x80 & O1;
            ChT[0] = (O1 & 0x7F) >> 2;
            ChT[1] = ((O1 & 0x03) << 3) | (O2 >> 5);
            ChT[2] = O2 & 0x1F;

            for(i=0;i<3;i++) {
                if (ind <= lenData){
                    CT = GetMessag(ind,ibit);

                    ChT[i] = (ChT[i] & ~p) | CT;
                }
            }
            ImgM[length+1] = X | (ChT[0] << 2) | (ChT[1] >> 3);
            ImgM[length] = (ChT[1] << 5) | ChT[2];
        }
    }

    cSave = ImgM;

/*
    if (ind < lenData)
        Etat1->Caption = "Intégrer partiellement";
    else
        Etat1->Caption = "Intégrer";

  • /
} //--------------------------------------------------------------------------- void __fastcall TTexteChild::Extraire(void) { unsigned long length, ind; int val; unsigned char DA, O1, O2, CT, ChT[3], ibit, i, *pt; bool etape; AnsiString tmp = " "; etape = true; DataAdd = new char [2]; lenData = 0; Calcul: ind = 0; DataAdd[ind] = 0; ibit = 0; if ((ImgResol == 8) || (ImgResol == 24) || (ImgResol == 32)) { // format 8, 24 ou 32 bit for (length=ImgDebPixel;length<lenImg;length++) { if (ind <= lenData){ SetMessag(ind,ibit,ImgO[length]); } } } else if (ImgResol == 16) { // format 16 bit for (length=ImgDebPixel;length<lenImg;length+=2) { O1 = ImgO[length+1]; O2 = ImgO[length]; ChT[0] = (O1 & 0x7F) >> 2; ChT[1] = ((O1 & 0x03) << 3) | (O2 >> 5); ChT[2] = O2 & 0x1F; for(i=0;i<3;i++) { if (ind <= lenData){ SetMessag(ind,ibit,ChT[i]); } } } } if ((ind == 1) && (lenData == 0)) { // premier passage : longueur du nom du fichier val = ((unsigned char)DataAdd[0]); lenData = val +6; free(DataAdd); DataAdd = new char [lenData + 1]; goto Calcul; } if ((ind == lenData+1) && (etape == true)) { // deuxième passage : taille du fichier if (DataAdd[lenData - 5] == '\0') { pt = DataAdd + lenData - 4; lenSave = CharToDWord(pt,4); lenData = lenData + lenSave; free(DataAdd); DataAdd = new char [lenData + 1]; etape = false; goto Calcul; } else { //Etat3->Caption = "Pas de fichier"; lenSave = 0; return; } } if ((ind != lenData+1) && (etape == true)) { lenSave = 0; //Etat3->Caption = "Pas de fichier"; return; } cSave = DataAdd; // Etat3->Caption = "Extration terminé"; } //--------------------------------------------------------------------------- int __fastcall TTexteChild::Puissance(int valeur, int puissance) { int v, v2, i; v = v2 = 1; for (i=1;i<puissance;i++) { v = v * valeur; v2 = v + v2; } return v2; } //--------------------------------------------------------------------------- UCHAR __fastcall TTexteChild::GetMessag(DWORD &ind, unsigned char &ibit) { UCHAR t1, t2, p, ib; DWORD in; in = ind; ib = ibit; p = (UCHAR) Puissance(2,nbit); t1 = DataAdd[in]; t1 = (t1 >> ib) & p; if (ib + nbit > 8) { ib = ib + nbit - 8; in++; p = (UCHAR) Puissance(2,ib); t2 = DataAdd[in]; t2 = t2 & p; t1 = (t2 << (nbit - ib)) | t1; } else { ib += nbit; if (ib >= 8) { in++; ib = 0; } } ind = in; ibit = ib; return t1; } //--------------------------------------------------------------------------- void __fastcall TTexteChild::SetMessag(DWORD &ind, unsigned char &ibit, unsigned char bit) { UCHAR t1, t2, DA, p, ib; DWORD in; in = ind; ib = ibit; p = (UCHAR) Puissance(2,nbit); DA = bit; DA = DA & p; t1 = DataAdd[in]; t1 = t1 | ((p << ib) & (DA << ib)); DataAdd[in] = t1; if (ib + nbit > 8) { ib = ib + nbit - 8; in++; DataAdd[in] = DA >> (nbit - ib); } else { ib += nbit; if (ib >= 8) { in++; ib = 0; DataAdd[in] = 0; } } ind = in; ibit = ib; return ; } //---------------------------------------------------------------------------

Conclusion :


Voilà quelques mise à jours qui devraient plairent. En prévision : l'image stéganographier résiste à une détection mathématique.

Codes Sources

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.