Ho ricevuto diverse richieste di spiegazioni sulla steganografia, specialmente da parte di curiosi che chiedono come iniziare a smanettarci, e devo dire che questa curiosita' mi fa piacere. Di seguito posto un esempio puramente didattico - ma potete iniziare a smanettarci se vi va - che vi spiega come steganografare un file dentro un altro.
Si tratta di una versione molto semplice della steganografia, per spiegare la quale usero' un linguaggio facile da reperire anche nelle installazioni aziendali piu' paranoiche, che e' perl.
Per la manipolazione grafica useremo una libreria, GD, semplice da leggere, cosi' anche chi non vuole usare perl potra' usare lo stesso concetto con qualsiasi altra libreria. Ripeto: lo scopo e' spiegare il concetto, per farlo avere cristallino in mente , non di fornire uno strumento. Chi e' un programmatore poi potra' sviluppare la cosa.
Partiremo da un'ipotesi semplice, di avere un'immagine "nascondiglio" a 256 colori. Ovviamente, per usare maschere piu' grandi, bastera' aver capito per estenderlo a piacere.
Il file da nascondere nel nostro esempio e' un file di testo che contiene "Grosse tette." dentro. Per prima cosa dobbiamo trasformarlo in una maschera di bit.
Il file da nascondere nel nostro esempio e' un file di testo che contiene "Grosse tette." dentro. Per prima cosa dobbiamo trasformarlo in una maschera di bit.
open(my $FH, "<", "danascondere.txt") or die("$!\n");
binmode($FH);
my $file; { local $/; $file = <$FH>; }
my $binary = unpack('B*', $file);
my @chars = split("", $binary);
#print $binary; # to testnel file "danascondere.txt" c'e' la vostra roba da nascondere. Quello che ottenete e' un oggetto contenente la rappresentazione della stringa che volete nascondere in binario. Se scommentate la parte con print , e lo fate su un file che contiene la stringa: "Grosse tette." ottenete questo:
010001110111001001101111011100110111001101100101 001000000111010001100101011101000111010001100101 0010111000001010@chars non e' altro che un vettore contenente gli uni e gli zeri indicizzati.
Una volta splittato il file che volete in bit, dobbiamo andare a nasconderlo dentro un'immagine. Sia chiaro che dobbiamo scegliere bene l'immagine. Se la nostra immagine ha 8 bit per pixel di profondita' colore, per nascondere qualcosa ci serve otto volte la dimensione iniziale (a meno di compressioni , ma poi le menziono). Se andiamo ad usare una fotografia che usa 32 bit per ogni pixel, dobbiamo considerare che ci servono 32 bit per nasconderne uno.
In generale, pero', rimane valida l'assunzione che ci serva un pixel per ogni bit.
Adesso andiamo ad operare sul file:
use GD;
use strict;
use warnings;
#con questo apriamo il file
open(my $FH, "<", "danascondere.txt") or die("$!\n");
binmode($FH);
my $file; { local $/; $file = <$FH>; }
my $binary = unpack('B*', $file);
my @chars = split("", $binary);
#dentro chars abbiamo il binario
# definiamo i file di immagine su cui lavorare
my $source = GD::Image->new( 'boobs.png' );
# steg.png e' dove metteremo tutto, boobs.png e' dove nasconderemo le cose.
my $numerobit = @chars; #vediamo quanti simboli ci sono dentro @chars
my $x; #definiamo le coordinate per i pixel
my $y; #definiamo le coordinate per i pixel
#per tutti i bit dentro @chars
for my $n (0 .. $numerobit -1) {
$x = $n % $source->height; #trasformiamo in coordinate l'indice $n.
$y = $n / $source->height;
my $m_idx = $chars[$n]; # prendiamo l'ennesimo elemento dell'array di bit
# otteniamo il colore in RGB del corrispondente pixel x,y:my ( $int ) = $source->rgb( $source->getPixel( $x, $y ) );
# andiamo a scrivere i nostri bit nel bit meno significativo del colore
if ($m_idx=='0')
{
$int = $int & 254; # se e' uno zero , assegnamo 0 all'ultimo bit della maschera.
}
else
{
$int = $int | 1; # se e' un uno, assegnamo 1 all'ultimo bit della maschera.
}
$source->setPixel( $x, $y, $int ); # correggiamo il colore dentro il nostro file.
}
open OUT, ">steg.png" || die $!;
binmode OUT;
print OUT $source->png; # e buttiamo fuori il file corretto con un altro nome
close OUT;
in pratica, stiamo prendendo il file png che si chiama "boobs.png" , e stiamo correggendo lievemente alcuni bit, in modo da scriverci le cose che vogliamo nascondere. La parte interessante l'ho scritta in rosso. E' la parte in cui anneghiamo il contenuto nel bit meno significativo del colore.
- La maschera "254" ha senso se abbiamo otto bit per pixel. Se ce ne fossero sedici avremmo dovuto usare 65534 , e cosi' via. I programmatori in ascolto conosceranno un sacco di metodi alternativi per mettere a zero un bit.
- Poiche' correggiamo i bit meno significativi, che vengono regolarmente potati via da JPEG, comprimere questa immagine di fatto cancella il messaggio.
questo esempio - e ripeto, e' un esempio scritto a mente (1)-, personalmente non uso questo , ma ADA non e' cosi' leggibile per spiegare.
Il concetto pero' e' semplice: se ogni pixel ha un colore, diciamo espresso in otto bit, cosi': 0000 0000 (nero) , nello steganografare andiamo a usare SOLO il bit meno significativo : 00000000
Fatto in questo modo, ovviamente il metodo e' poco resistente all'analisi, e per questo non ho messo molta cura nello scrivere il codice dell'esempio: fare cosi' serve contro un attaccante che sa poco e niente, quindi contro la media dei "periti dei tribunali" italiani, moltissimi degli amministratori di dominio windows troppo curiosi, e molti degli "esperti" della Polizia Postale, ma non contro chiunque, perche' chi intende attaccare potrebbe notare che unendo insieme gli ultimi bit ottiene un messaggio compiuto.
Questo problema si puo' risolvere facilmente criptando il messaggio PRIMA di inserirlo dentro l'immagine: a quel punto e' difficile capire SE ci sia un messaggio criptato nascosto dentro il file: normalmente il messaggio criptato in binario appare come una sequenza casuale.
Un altro problema per chi LEGGE il file prodotto in questo modo e' che non sa bene quanto sia grande il messaggio. In questo senso, vi conviene zippare il messaggio prima di nasconderlo: zip, per sua natura, tiene un indice all'inizio del file, ed ignora tutto quello che eventualmente eccede la sua misura. Ha pero' lo svantaggio di creare un header visibile.
ovviamente ne potrete produrre diverse varianti: potete agire solo sui pixel pari, su quelli dispari, su pixel scelti secondo una maschera a vostra scelta (per esempio un altro file di immagini della stessa dimensione).
I crittografi inorridiranno perche' mi diranno che una crittazione non deve basarsi sulla segretezza dell'algoritmo, ma il punto e' che non stiamo facendo crittazione, siamo facendo steganografia: non stiamo nascondendo il messaggio, MA IL CANALE.
E la segretezza della cosa e' importante nella segretezza della cosa? Si.
In pratica , per fare un esempio nel mondo dello spionaggio cinematografico, la cifratura e' un codice segreto, mentre la steganografia e' il modo segreto con cui comunichiamo con gli altri. Se il nostro agente incontra un altro agente e gli dice "Geronimo 123" e' crittazione. Se sono travestiti da assicuratori e si incontrano in un ufficio di un'agenzia di assicurazioni, e' steganografia.
Le due cose non si escludono: un messaggio in codice nascosto dentro un barile di sarde in salamoia puo' essere cifrato. In quel caso, "nascosto nel barile delle sarde in salamoia" e' steganografia, mentre il codice usato per rendere illeggibile il messaggio e' crittografia.
In maniera estremamente sintetica, la crittografia fa si che il messaggio sia illeggibile, la steganografia si preoccupa che il messaggio sia introvabile.
Perche' ho scritto che sia fondamentale nel mondo di NSA?
Chiediamoci come NSA si paghi lo stipendio. Di certo non e' contro il terrorismo che fanno controlli a tappeto, e l'attentato alla maratona ne e' la prova: DOPO hanno trovato il profilo dei tizio ceceno, DOPO hanno trovato le sue comunicazioni, eccetera.
NSA si paga le sovvenzioni governative che costa semplicemente intercettando le comunicazioni commerciali (le cosiddette "offerte" ) delle aziende, durante le grandi gare internazionali, per passarle ai concorrenti americani, in modo da farli vincere.
nel fare questo, catturano a tappeto ogni cosa si scriva in qualsiasi cloud pubblico, qualsiasi cosa passi , in chiaro o meno , attraverso qualche dispositivo che loro hanno messo sotto sorveglianza.
nel fare questo, pero', non hanno solo bisogno di decodificare il traffico. Hanno bisogno di individuare i dati che cercano nel traffico.
Chiaramente, sanno come rompere i codici che hanno inventato. Ma rimane ancora il vecchio gioco di nascondere il dato. Con quello possono fare poco, perche' quando la ricerca del dato si fa spinta, il dato stesso e' piu' inventato che reale.
Prendiamo un programma di steganografia come quello che ho scritto (ma ne trovate diversi):
- Mi chiede una password per crittografarlo e una per la posizione.
- Lo crittografa.
- Crittografa la posizione per sapere da dove cominci il documento.
- Lo scrive nel file di immagini , partendo da un offset casuale anziche' dall'inizio. Usa uno degli ultimi 4 bit di 32, ma non sempre quello.
- lo fa in modo che una minima modifica al formato di archiviazione sia fatale per il contenuto, producendo un jpg.
ora, i nostri eroi che vanno a leggere i miei file sul cloud microsoft che il mio cliente usa per "salvare" i suoi dati, vedono solo una raccolta di wallpapers. Tutto quello che e' classificato piu' di C2 viene messo in una serie di immagini salvate sul disco.
Adesso, spazzolando le immagini a tappeto, potrebbro fare diversi errori: il primo e' di pensare che siano solo immagini. Il secondo e' di archiviarle per un uso futuro comprimendole un minimo o cambiando il formato. Ma specialmente, non saprebbero mai da dove inizi il documento nascosto e dove finisca.
Possono tentare di ricostruirlo usando crittanalisi di OGNI bit del file di immagini? Certo. Ma la ricostruzione sarebbe piu' che altro un'invenzione. Dal loro punto di vista si tratta di:
- Ipotizzare che ci sia qualcosa in un dato file. Che non succede per tutti i file.
- Ipotizzare quale dei 4 bit si sia usato, pixel per pixel.
- Ipotizzare che un dato insieme di bit sia il marcatore per l'inizio del documento nascosto.
- Ipotizzare che sia criptato con un dato algoritmo.
- Ipotizzare quale sia la chiave che ho usato per crittare oppure rompere la crittazione.
il problema e' che per trovare il documento occorre rispondere a tutte queste ipotesi. E spazzolare OGNI documento del mondo chiedendosi se contenga qualche altra cosa , in questo modo, non e' semplicemente fattibile.
Cosi', se volete portare fuori qualcosa da un'azienda che vi concede accesso ad un servizio di cloud pubblico qualsiasi, ma controlla tutto cio' che entra ed esce, non avete da fare altro che avere una larga collezione di musica, wallpapers, video, e steganografarci dentro le cose.
In questo senso, il problema dell'attaccante NON e' SOLO di non saper decodificare il messaggio, ma di non avere modo di sapere che il messaggio sia li'. I file, infatti , sono assolutamente utilizzabili come immagini: nel file che vedete sotto ho nascosto un altro file di testo. Come vedete, appare ancora usabile quale immagine jpg.
Questo file contiene un altro file segreto. |
quindi, con buona pace di NSA, il terrorista (o Snowden), o l'azienda concorrente alla grande azienda americana, puo' fargli passare sotto il naso tutto quel che vuole, perche' con un sistema di monitoraggio di massa, che salva in gran parte i metadati , non e' letteralmente possibile avere la sorveglianza che cercano.
Per questa ragione, sebbene la steganografia "fragile" (quella per la quale un minimo cambiamento di formato del file distrugge il dato nascosto) sia una tecnica relativamente semplice, non troverete molti tool di steganografia in giro: se qualcuno facesse oggi , negli USA, un tool di steganografia semplice da usare, riceverebbe una bella visita da FBI.
Perche' trovare un disco criptato e' un conto: sapete che li' dentro c'e' nascosto qualcosa. Ma trovare un disco steganografato significa che vi metterete a cercare e non troverete nulla di nulla.
Per questa ragione, sebbene la steganografia "fragile" (quella per la quale un minimo cambiamento di formato del file distrugge il dato nascosto) sia una tecnica relativamente semplice, non troverete molti tool di steganografia in giro: se qualcuno facesse oggi , negli USA, un tool di steganografia semplice da usare, riceverebbe una bella visita da FBI.
Perche' trovare un disco criptato e' un conto: sapete che li' dentro c'e' nascosto qualcosa. Ma trovare un disco steganografato significa che vi metterete a cercare e non troverete nulla di nulla.
(1) Se facendolo girare ottenere qualche errore, consideratelo un compito a casa. Sto scrivendo un articolo su un blog, non sto lavorando che devo correggere tutto.