Cacher mot de passe dans bitmap - steganographie

Soyez le premier à donner votre avis sur cette source.

Vue 6 360 fois - Téléchargée 676 fois

Description

Bonjour,

J'ai cherché à cacher un mot de passe sans que cela ne se voit trop.
Je ne voulais pas utiliser la base de registre mais un lieu tellement évident qu'on ne le soupçonne pas : dans une image.

Avec l'exemple fourni (l'image test-source est dans un fichier .res), on ne voit pas trop le mot de passe une fois inséré dans l'image. On peut bien sûr modifier tous les paramètres et la clé de cryptage Xor utilisée pour le cryptage du mot de passe (dans le fichier .res également)

Le mot de passe n'est pas inséré en fin de fichier mais dans l'image :

Pour l'exemple, j'utilise un bitmap (obligatoirement 24 bits) et je code à la ligne 3, du 3ème au 46ème pixel à l'aide du paramètre RGB bleu. Du coup, je peux coder une chaîne de 43 caractères sur cette ligne. Je pense que ce n'est pas trop visible.

Merci à Steff : http://www.vbfrance.com/code.aspx?ID=16929 qui a largement inspiré mon code.

Cordialement, ym_trainz

Source / Exemple :


'In the zip

'2 versions du projet :
'une avec tracé des images (capture)

'l'autre sans tracé mais sous forme d'un module, plus facilement insérable dans un projet :

Public Function MpassToBmp(PassWord As String, BmpFilePathSource As String, _
        BmpFilePathDest As String, KeyEncrypt As String, ToWrite As Boolean, _
        LineToInsert As Integer, FirstColPix As Integer, LastColPix As Integer) As Boolean
    '-------------------------------
    'la fonction à appeler
    'ym_trainz 2008
    '-------------------------------
    'paramètres :
    '
    'PassWord : mot caché (à lire ou à écrire dans l'image
    '           la longueur du mot maxi est LastColPix - FirstColPix (car 1 caractère réservé pour la longueur du mot)
    '           Limite 254 caractères quand même, à cause de Dim TabMo() As Byte (tableau des caractères)
    'BmpFilePathSource : chemin de l'image bitMpas 24bit source
    'BmpFilePathDest : chemin de l'image bitMpas 24bit destination
    '                  (n'est utile que si on écrit le mot caché, laisser vide pour une lecture)
    'KeyEncrypt : clé de crytage Xor pour coder le mot à cacher
    'ToWrite : True pour écrire , False pour lire
    'LineToInsert : indice de la ligne où se situe le mot à lire ou à écrire (1 à InfoHeader.Height)
    'FirstColPix et  LastColPix : premier et dernier pixel (colonne) pour le champ du mot à écrire ou à lire
    '                           (LastColPix - FirstColPix)<=254

Conclusion :


Il existe déjà des sources sur le sujet mais je pense que le mot de passe est plutôt bien camouflé ;-)
L'image test est automatiquement crée au démarrage (form_load) Elle se régénère donc automatiquement.

La version module permettra une utilisation plus simple à l'aide d'une seule fonction MpassToBmp()

Codes Sources

A voir également

Ajouter un commentaire

Commentaires

Messages postés
162
Date d'inscription
vendredi 27 janvier 2006
Statut
Membre
Dernière intervention
21 avril 2015

Bonsoir PWM63

Je te remercie beaucoup pour ce code que j'essaierai d'intégrer dans le projet.
Je me pencherai également sur le codage Rijndael.
Pour l'heure, je n'ai pas trop le temps de travailler sur ce projet mais dès que j'aurai un peu temps, je m'y mettrai ;-)

Encore tous mes remerciements,

Cordialement,
ym_trainz
Messages postés
127
Date d'inscription
lundi 11 octobre 2004
Statut
Membre
Dernière intervention
18 mai 2016

Bonjour ym_trainz,

Oui, j'ai l'algo. Mais comme c'est du code qui n'était pas prévu pour être posté, il n'y a pas de commentaire (juste à 1 endroit)

Mais les contrôles et variables sont explicitement nommées.

Bon courage tout de même ! :)

Pour la clef Xor, rien de plus facile de la trouver ! C'est déconcertant tellement c'est facile ! Cherche plutôt du côté de Rijndael, il n'y a pas mieux.

Algo pour marquer :

Dim w, h, x, y As Integer

Private Sub Button_Marquer_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button_Marquer.Click

marque()

End Sub

Function marque() As Boolean

If Me.TextBox_PathImageSource.Text > "" And _
Me.TextBox_PathImageMarquée.Text > "" And _
Me.TextBox_PathImageSource.Text <> Me.TextBox_PathImageMarquée.Text And _
Me.TextBox_Pass1.BackColor = Color.Green And _
Me.TextBox_Pass2.BackColor = Color.Green And _
Me.TextBox_ConfirmPass1.BackColor = Color.Green And _
Me.TextBox_ConfirmPass2.BackColor = Color.Green And _
Me.TextBox_Texte_clair.Text > "" Then

Dim img As Bitmap = Me.PictureBox_ImageSource.Image.Clone
Dim nb_pxl, pas As Integer
Dim txt_clair As String = Me.TextBox_Texte_clair.Text
Dim pass1 As String = Me.TextBox_Pass1.Text
Dim pass2 As String = Me.TextBox_Pass2.Text
Dim cryptage As New Rijndael(pass1, pass2)
Dim txt_crypté As String = cryptage.EncryptText(txt_clair)
Dim r, g, b, gris_rg, gris_b As Integer
Dim r2, g2, b2 As Byte

Me.TextBox_Texte_crypté.Text = txt_crypté

w = img.Width
h = img.Height
nb_pxl = w * h
x = 0
y = 0

If nb_pxl > txt_crypté.Length + 1 + txt_crypté.Length.ToString.Length + 1 Then

img.SetPixel(x, y, Color.FromArgb(Asc("w"), Asc("m"), Asc("k")))

For i = 0 To txt_crypté.Length.ToString.Length - 1

xy(1)
img.SetPixel(x, y, Color.FromArgb(img.GetPixel(x, y).R, Asc(txt_crypté.Length.ToString.Substring(i, 1)), img.GetPixel(x, y).B))

Next

xy(1)
img.SetPixel(x, y, Color.FromArgb(Asc("w"), Asc("m"), Asc("k")))

pas = Math.Truncate((nb_pxl - x - ((y + 1) * w)) / (txt_crypté.Length + 9))

If pas = 0 Then Return False

For i = 0 To txt_crypté.Length - 1

xy(pas)

'Modifie la couleur du pixel en gardant le plus possible le même ton
'ex :
'couleur source = 70,10,50
'code caractère = 61
'la couleur cryptée deviendra 90,30,71

r = img.GetPixel(x, y).R
g = img.GetPixel(x, y).G
b = img.GetPixel(x, y).B

gris_rg = Asc(txt_crypté.Substring(i, 1)) / 3
gris_b = Asc(txt_crypté.Substring(i, 1)) - (2 * gris_rg)

If r + gris_rg <= 255 Then
r2 = r + gris_rg

Else
r2 = r - gris_rg

End If

If r + gris_rg <= 255 Then

If g + gris_rg <= 255 Then
g2 = g + gris_rg

Else
g2 = g - gris_rg

End If

Else

If g - gris_rg >= 0 Then
g2 = g - gris_rg

Else
g2 = g + gris_rg

End If

End If

If r + gris_rg <= 255 And g + gris_rg <= 255 Then

If b + gris_b <= 255 Then
b2 = b + gris_b

Else
b2 = b - gris_b

End If

ElseIf r - gris_rg >= 0 And g - gris_rg >= 0 Then

If b - gris_b >= 0 Then
b2 = b - gris_b

Else
b2 = b + gris_b

End If

Else

If b + gris_b <= 255 Then
b2 = b + gris_b

Else
b2 = b - gris_b

End If

End If

img.SetPixel(x, y, Color.FromArgb(r2, g2, b2))

Next

Me.PictureBox_ImageMarquée.Image = img

Return True

End If

End If

Return False

End Function

Sub xy(ByVal pas As Integer)

x += pas

While x >= w

x -= w
y += 1

End While

End Sub

Et pour démarquer (autre form) :

Dim w_source, h_source, w_marquée, h_marquée, x, y As Integer

Private Sub Button_Démarquer_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button_Démarquer.Click

démarque()

End Sub

Function démarque() As Boolean

If Me.TextBox_PathImageSource.Text > "" And _
Me.TextBox_PathImageMarquée.Text > "" And _
Me.TextBox_PathImageSource.Text <> Me.TextBox_PathImageMarquée.Text And _
Me.TextBox_Pass1.Text > "" And _
Me.TextBox_Pass2.Text > "" And _
Me.TextBox_Pass1.Text <> Me.TextBox_Pass2.Text Then

Dim img_source As Bitmap = Me.PictureBox_ImageSource.Image.Clone
Dim img_marquée As Bitmap = Me.PictureBox_ImageMarquée.Image.Clone
Dim nb_pxl, pas As Integer
Dim pass1 As String = Me.TextBox_Pass1.Text
Dim pass2 As String = Me.TextBox_Pass2.Text
Dim cryptage As New Rijndael(pass1, pass2)
Dim txt_crypté As String = ""
Dim r, g, b, r2, g2, b2 As Byte
Dim couleur As Color
Dim txt_len As Integer = 0
Dim val As Byte

w_source = img_source.Width
h_source = img_source.Height
w_marquée = img_marquée.Width
h_marquée = img_marquée.Height
nb_pxl = w_marquée * h_marquée
x = 0
y = 0

If w_source <> w_marquée Or h_source <> h_marquée Then Return False

If img_marquée.GetPixel(x, y) <> Color.FromArgb(Asc("w"), Asc("m"), Asc("k")) Then Return False

xy(1)
couleur = img_marquée.GetPixel(x, y)

While couleur <> Color.FromArgb(Asc("w"), Asc("m"), Asc("k"))

If Not IsNumeric(Chr(couleur.G)) Then Return False

val = Conversion.Val(Chr(couleur.G))
txt_len *= 10
txt_len += val
xy(1)
couleur = img_marquée.GetPixel(x, y)

End While

xy(1)
pas = Math.Truncate((nb_pxl - x - ((y + 1) * w_marquée)) / (txt_len + 9))

If pas = 0 Then Return False

For i = 0 To txt_len - 1

xy(pas)
r = img_source.GetPixel(x, y).R
g = img_source.GetPixel(x, y).G
b = img_source.GetPixel(x, y).B
r2 = img_marquée.GetPixel(x, y).R
g2 = img_marquée.GetPixel(x, y).G
b2 = img_marquée.GetPixel(x, y).B
val = Math.Abs(r - r2) + Math.Abs(g - g2) + Math.Abs(b - b2)
txt_crypté &= Chr(val)

Next

Me.TextBox_Texte_crypté.Text = txt_crypté

Try
Me.TextBox_Texte_crypté.Text = cryptage.DecryptText(txt_crypté)

Catch ex As Exception
Return False

End Try

Return True

End If

Return False

End Function

Sub xy(ByVal pas As Integer)

x += pas

While x >= w_marquée

x -= w_marquée
y += 1

End While

End Sub
Messages postés
162
Date d'inscription
vendredi 27 janvier 2006
Statut
Membre
Dernière intervention
21 avril 2015

Merci PWM 63 !

Bon, là, d'accord, on entre vraiment dans le détail.
As-tu l'algo qui va bien pour ta modif RGB ?

Pour le Xor, il faut déjà avoir la clé de cryptage, mais bon, si tu as encore mieux...

Cordialement,
ym_trainz
Messages postés
127
Date d'inscription
lundi 11 octobre 2004
Statut
Membre
Dernière intervention
18 mai 2016

Quitte à faire du watermarking, ne pas utiliser xor comme système de cryptage, ce n'est pas très sécurisé.

Si tu gardes l'original et la copie modifiée, il est également possible de dispatcher chaque pixel modifié dans l'image, quelle que soit sa taille. Et pour que ce soit encore moins visible, il est possible de modifier le pixel en gardant le même ton de couleur.

'Modifie la couleur du pixel en gardant le plus possible le même ton
'ex :
'couleur source = 70,10,50
'code caractère = 61
'la couleur cryptée deviendra 90,30,71
Messages postés
162
Date d'inscription
vendredi 27 janvier 2006
Statut
Membre
Dernière intervention
21 avril 2015

Oups... Désolé Rey !
Je corrige.
Cela fera une version 3 puisque je viens d'UL une version avec module.

Cordialement,
ym_trainz
Afficher les 6 commentaires

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.