Affichage des articles dont le libellé est Stéganographie. Afficher tous les articles
Affichage des articles dont le libellé est Stéganographie. Afficher tous les articles

dimanche 27 février 2011

Détection de LSB

Comme vu dans un de mes précédents articles, une technique largement utilisée en stéganographie consiste à cacher des informations dans les bits de poids faible (LSB) d'une image. Je vais décrire ici une méthode qui permet dans de nombreux cas de savoir si oui ou non une information est cachée dans ces bits.
Attention, il n'est pas question ici d'extraire cette information, car il existe une infinité de façon de cacher les données dans le LSB :
  • Un bit sur deux, un bit sur trois...
  • Choix des bits de certaines composantes de l'image uniquement (que dans la composante verte, rouge, bleue, ou toutes les combinaisons possibles)
  • Ordre des bits en lisant l'image ligne par ligne, colonne par colonne, une ligne sur 2....
  • Lecture des bits à l'envers ou non
  • Utilisation des bits de poids le plus faible, ou de poids un peu plus important (avec comme conséquence une altération de l'image plus importante)
  • ...
Toutes les techniques ou combinaisons de techniques sont possibles tant qu'elles sont partagées par l'émetteur du message stéganographié et son récepteur.

Le point important est que toutes les méthodes stéganographiques à base de LSB altèrent le contenu de l'image et que même si cette légère modification n'est pas visible à l'œil nu, elle peut quand même être décelée si on utilise les bonnes techniques.

L'idée est la suivante, même si les bits de poids faibles sont porteurs de très peu d'information (comme vu dans mon article sur le LSB), ils ne sont tout de même pas distribués aléatoirement dans l'image. Porteur de très peu d'information, ne veut pas dire porteur d'aucune information. Dans une zone ou il n'y a qu'une couleur présente par exemple, il y a peu de chance qu'en plein milieu il y ait un pixel différent de tous ses voisins... possible, mais peu probable. Les bits de poids faibles respectent en règle générale l'apparence de l'image et les pixels sont cohérents entre eux.

Le but va donc être de visualiser cette cohérence entre les bits de poids faibles. Pour cela on va recréer l'image en "vidant" chaque bit des informations inutiles (c'est à dire les bits de poids fort). Seuls les bits susceptibles de cacher de l'information vont donc être gardés. Comme ce sont des bits de poids faibles, ils ont un impact faible sur le rendu de l'image et il sera donc très difficile de distinguer quoique soit. Il suffit pour cela d'augmenter le poids du bit en faisant un simple décalage binaire vers la gauche.
// On enlève les informations inutiles
composante = composante & 1;

// On augmente le poids du bit
composante = composante << 7;

Exemple :
Composante (décimale) 255 0 111 56
Composante (binaire) 11111111 00000000 01101111 00111000
Devient (binaire) 10000000 00000000 10000000 00000000
Devient (décimale) 128 0 128 0
Pour effectuer cette petite transformation sur les images j'utilise un petit outil que j'ai écrit :

# ./lsb.rb -h
lsb.rb [options] -i input_image -o output_image
Version 1.1
--colors|-c r|g|b: couleur que l'on veut garder
--bit|-b bit: bit que l'on va utiliser (par defaut 0)
--help|-h : affiche cette aide
--version|-v : affiche le numero de version

Utilisons ce petit programme sur cette image qui ne cache aucune information à l'intérieur.

# ./lsb.rb tux.png -o tux_lsb.png

Comme on peut le voir très clairement ici, la structure de l'image est ici conservée, et cela même dans les bits de poids faibles.

Cachons maintenant des informations dans notre image de départ et regardons le résultat :

# ./lsb_hide.rb -f hide.txt tux.png -o tux_hidden.png
# ./lsb.rb tux_hidden.png -o tux_hidden_lsb.png
On voit très clairement ici que quelque chose s'est passé sur le haut de l'image, puisque cette partie n'est plus du tout cohérente. La raison est qu'un message a été caché, et celui-ci étant court, toute l'image n'a pas été nécessaire pour le cacher.

Cette technique ne fonctionnera pas dans tous les cas, à plus forte raison si l'image est bruitée ou par exemple si elle avait été préalablement compressée en jpg. Cependant, je la trouve suffisamment intéressante pour être citée. De plus elle m'a rendu de précieux services lors de certains challenges.

dimanche 30 janvier 2011

Least Significant Bit ou LSB

Introduction

Une technique fréquemment utilisée en stéganographie pour cacher des informations est la technique du Least Significant Bit, LSB ou bits de poids faible. Contrairement à mon article sur le padding BMP, cette méthode peut être utilisée sur plusieurs formats d'images, tant que celui-ci n'utilise pas de compression avec perte. Il est donc possible de l'utiliser sur les formats BMP, PNG, GIFF... mais ne pourra pas être appliquée au format JPG. L'objectif du LSB est de modifier de façon imperceptible l'image pour cacher de l'information.

Principe

Pour commencer il est nécessaire de comprendre comment sont stockées les informations dans une image. Chaque image est constituée de pixels codés généralement par 3 couleurs : rouge, vert et bleu (RGB). Chaque pixel représente donc une certaine quantité de rouge, une certaine quantité de vert et une certaine quantité de bleue.
Si on prend le cas ou chaque couleur de chaque pixel est codée sur un octet il y a donc 256 valeurs pour une couleur de 0 (la couleur n'est pas présente) à 255.

On peut donc représenter 256^3 soit 16777216 couleurs au total. L'idée est que l'œil humain ne va pas être capable de distinguer parfaitement toutes ces couleurs et que donc de légères modifications sur la couleur des pixels ne seront pas distinguables en tout cas pour l'œil humain.

Prenons un exemple, la couleur suivante est constituée uniquement de rouge et a la valeur 255,0,0 (255 de rouge, 0 de vert et 0 de bleu), la suivante a la valeur 254,0,0.

Comme on peut le voir la différence est difficilement visible. L'image suivante contient les couleurs suivantes sur la première ligne 255,0,0 0,255,0 0,0,255 et sur la deuxième ligne les couleurs suivantes 254,0,0 0,254,0 0,0,254.

Représentation binaire

Le but est donc de trouver un moyen d'altérer la couleur de l'image d'une façon imperceptible. Cette technique va se baser sur la représentation du nombre en binaire. Comme dit précédemment, une couleur est codée sur un octet, soit 8 bits. On peut donc représenter n'importe quelle couleur par une suite de 8 bits. Ce qui est intéressant dans cette approche c'est que chaque bit n'est pas porteur de la même quantité d'information. Le bit de poids faible (le bit le plus à droite) a un poids de 1, c'est à dire que le fait qu'il soit à 1 ou à 0 ne modifiera la valeur finale que de 1, alors que le bit de poids fort (le bit le plus à gauche) a un poids de 128.

Le tableau suivant détaille le poids de chaque bit :

Représentation binaire de 153 = 10011001b


bit 7bit 6bit 5bit 4bit 3bit 2bit 1bit 0
Valeur binaire10011001
Poids du bit1286432168421

Pour vérifier : 153 = 1*128 + 0*64 + 0*32 + 1*16 + 1*8 + 0*4 + 0*2 + 1*1

L'idée finale est donc d'altérer les bits qui portent le moins d'informations pour y stocker notre message caché. Etant donné que ces bits sont porteurs de peu d'information, l'aspect visuel de l'image sera peu altéré.

Cacher de l'information

Prenons un exemple concret où nous voulons cacher la lettre "A" dans 3 pixels. Les 3 pixels seront 153,74,186 255,255,255 0,0,0. La lettre "A" a la valeur ASCII 65 soit 01000001b en binaire. Comme dit précédemment, on va modifier les bits de poids faible de chaque couleur pour stocker notre information.

Pixel 1 RougePixel 1 VertPixel 1 BleuPixel 2 RougePixel 2 VertPixel 2 BleuPixel 3 RougePixel 3 VertPixel 3 Bleu
Valeur Décimale15374186255255255000
Valeur Binaire100110010100101010111011111111111111111111111111000000000000000000000000
Bit à cacher01000001padding
Couleur finale binaire100110000100101110111010111111101111111011111110000000000000000100000000
Couleur finale15275186254254254010


La nouvelle suite de couleur passe à 152,75,186 254,254,254 0,1,0. Comme on peut donc le voir, une légère modification a lieu.

Pour aller plus loin

L'exemple ici porte sur la façon de cacher de l'information dans le bit 0, celui qui est porteur du moins grand nombre d'informations. Il est toutefois possible d'utiliser plusieurs bits comme par exemple les bits 0, 1 et 2. L'image sera au final altérée de façon plus importante, mais la quantité d'information cachée sera plus grande. En stégagnographie tout est question de compromis : Plus on cachera d'information et plus on détériorera le support et donc plus il sera facile de déceler qu'une information est cachée.

Exemple d'information cachée

L'image suivante possède une information cachée dans ses bits de poids de faible. Ici contrairement au padding BMP, aucune chance de ne voir quoique ce soit en ouvrant l'image dans un editeur hexa ;)

mercredi 5 janvier 2011

Padding BMP

Suite à mon introduction sur le concept de la stéganographie, voilà un exemple appliqué sur les images bitmap plus communément appelées BMP. Cette technique assez basique fonctionne exclusivement sur les images BMP car elle utilise une des particularités de ce format : le padding (le bourrage en français). La norme BMP dit que chaque ligne de l'image doit être codée par un nombre d'octets multiple de 4. Si ce n'est pas il faut combler le manque d'octets avec la valeur nulle. On appelle ça le padding.
  On se retrouve donc avec un fichier possédant des octets qui n'apportent aucune information et qui sont même complètement ignorés par la totalité des programmes. Il est donc possible d'utiliser ce padding pour cacher des données à l'intérieur. L'image apparaitra totalement inchangée dans votre viewer préférée. Cette technique très simple n'est possible que si une ligne n'est pas codée avec un nombre d'octets multiple de 4 bien entendu, sinon le padding sera inexistant. On peut donc écrire la formule suivante qui donnera la taille du nombre d'octet que l'on peut cacher dans une image BMP en utilisant cette technique :
Nb_Bytes = L*((4-((C*S)%4))%4)

L : Nombre de lignes de l'image

C : Nombre de colonnes de l'image

S : Taille en octet d'un pixel

Petit exemple : la première image ici est l'image originale.

 La deuxième image contient un message caché de 173 octets (on aurait pu aller jusqu'à 508 !).
 
 Comme on peut le voir elles ont exactement le même aspect et font exactement le même poids. Le programme python suivant permet de savoir si oui ou non l'image que l'on passe en paramètre ne contient que des octets nuls dans son padding (attention à n'utiliser que sur des images BMP non indexées).
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import sys,struct

class BMP:
 def __init__(self,path):
  f = open(path,"rb")
  data = f.read()
  f.close()

  names = ["magick","size_file","creator1","creator2","start_data","header_image","width","height","plan","colors","compression","raw_size","horizontal","vertical","color_palette","important_colors"]

  values = struct.unpack('<2sLHHLLLLHHLLLLLL',data[:54])
  self.data = data[54:]

  self.header = dict()

  for i in range(len(names)):
   self.header[names[i]] = values[i]

  # On stocke quelques éléments pour ne pas être obligé de toujours les calculer
  self.size_pixel = self.header['colors']/8
  self.padding_size = self.padding_size()

 # Retourne la taille du padding par ligne
 def padding_size(self):
  return ((4-(self.header['width']*self.size_pixel)%4)%4)

 # Retourne un tableau contenant le padding dans le fichier bmp
 def padding(self):
  r = []

  if self.padding_size != 0:
   start = 0
   for row in range(self.header['height']):
    start += (self.size_pixel*self.header['width'])
    r += struct.unpack('c'*self.padding_size,self.data[start:start+self.padding_size])
    start += self.padding_size

  return r

if len(sys.argv) != 2:
 print "Manque le fichier bmp"
 sys.exit(1)

bmp = BMP(sys.argv[1])
print "Taille padding : %i" % (bmp.padding_size*bmp.header["height"])
for e in bmp.padding():
 if e != 0:
  print "Padding non nul !"
  sys.exit(0)

print "Padding nul"
sys.exit(0)
Cette technique à l'avantage de ne pas du tout altérer l'image, et de ne pas modifier sa taille. Cependant, outre le fait qu'elle soit très basique, il faut bien faire attention aux informations cachées dans le padding. La simple ouverture de l'image dans un fichier texte peut révéler des parties de l'information cachée, qui se trouvera en clair. Un élément important avec cette technique à préciser est la structure d'un fichier BMP. Contrairement à la plupart des formats d'images les lignes sont stockées dans l'ordre inverse : la dernière ligne est codée, puis l'avant dernière, ... et enfin la première. De plus (mais ça n'a pas réellement d'impact ici), le codage d'un pixel se fait dans l'ordre bleu-vert-rouge, contrairement aux rouge-vert-bleu habituels.

vendredi 3 décembre 2010

Stéganographie

La stéganographie est un domaine que je ne connaissais pas du tout et que j'ai appris à apprécier grâce à des sites de challenges informatiques comme newbiecontest, wechall ou encore bright-shadows.

Contrairement à la cryptographie dont l'objectif va être de rendre une information non intelligible pour les personnes non autorisées, la stéganographie va cacher une information dans un contenu de telle sorte qu'on ne puisse pas savoir que quelque chose est cachée. Pourquoi chercher quelque chose si on ne sait même pas que ce quelque chose existe ?
Les différents supports dans lesquels on peut cacher des informations peuvent être très variés : images, vidéos, sons, système de fichier, texte... tout est possible.

La difficulté pour cacher l'information ou pour déceler qu'une information est cachée dépend vraiment de la technique utilisée. Certaines peuvent très simples, comme la célèbre lettre de George Sand à Alfred de Musset qui doit se lire une ligne sur deux :
Je suis très émue de vous dire que j'ai
bien compris, l'autre jour, que vous avez
toujours une envie folle de me faire
danser. Je garde un souvenir de votre
baiser et je voudrais que ce soit
là une preuve que je puisse être aimée
par vous. Je suis prête à vous montrer mon
affection toute désintéressée et sans cal-
cul. Si vous voulez me voir ainsi
dévoilée, sans aucun artifice mon âme
toute nue, daignez donc me faire une visite.
Et nous causerons en amis et en chemin.
Je vous prouverai que je suis la femme
sincère capable de vous offrir l'affection
la plus profonde et la plus étroite
amitié, en un mot, la meilleure amie
que vous puissiez rêver. Puisque votre
âme est libre, alors que l'abandon où je
vis est bien long, bien dur et bien souvent
pénible, ami très cher, j'ai le cœur
gros, accourez vite et venez me le
faire oublier. À l'amour, je veux me sou-
mettre entièrement.
D'autres très compliquées et faisant appel à des analyses statistiques et des calculs mathématiques complexes.

La stéganographie est un sujet vaste et de nombreuses études sont faites à ce sujet aujourd'hui, car c'est un moyen très puissant pour transmettre des informations qui ne devraient pas être connues.