Newsgroup: it.comp.sicurezza.pgp
Titolo: steganografia: qualche considerazione sui recenti post

Come promesso, ho lavoricchiato durante la scorsa settimana per
preparare qualcosetta, sulla base di quel vecchio documento di cui si e'
gia' parlato nel thread "Crittografia AES-256 in 7-Zip", che,
ovviamente, non c'entrava per nulla :)
Dunque, ho uploadato su un mio vecchio sito preparato per ben altra cosa
http://angelfire.lycos.com/jazz/pwalker
una suite di tre programmini, pngstego. 
Trattasi di un tulletto che prende in ingresso una immagine png a scala
di grigi 8 bit, un file messaggio, e genera un nuovo file png con
steganografato il file messaggio.
Lo stesso tulletto, aggiungendo l'opzione -x, estrae il messaggio
dall'immagine steganografata e lo salva nel file messaggio.
Il metodo utilizzato e' molto banale, la semplice sovrascrittura del bit
meno significativo dell'immagine. 
Sempre nel thread in questione, affermavo che la steganografia soffre di
un problema intrinseco, quello della notevole differenza tra la
correlazione del file immagine e quella del file messaggio. Affermavo,
semplicemente riportando un articolo trovato in giro per la rete
(
http://os.inf.tu-dresden.de/~westfeld/publikationen/ihw99.pdf
) che i
bit meno significativi non sono poi tanto scorrelati, e tutt'altro che
assimilabile a rumore bianco.
Beh, mi sbagliavo.
Come al solito, dipende. L'articolo non riportava come l'immagine e'
stata realizzata, e leggendolo sembra che tale assunto sia applicabile a
qualunque immagine fotografica.
Con un tool fatto ad-hoc (imgthr.c) ho provato a prendere diverse
immagini e a tenere soltanto i bit meno significativi (sogliatura). Dato
che per ora i tool che ho fatto supportano solo immagini a 8 bit
grayscale, le ho convertite a grayscale (erano RGB) e salvate come png.
sorpresa! checche' dica l'articolo, anche la sogliatura dell'immagine
piu'"regolare" possibile non rivela alcuna informazione macroscopica
dell'immagine originale!
Come mai?
Beh, ripensando all'articolo originale, mi e' venuto in mente che esso
trattava delle immagini in formato GIF; tale formato e' sempre un 8 bit
indexed, il file si porta dietro una palette di 256 colori e ciascun
campione rappresenta un indice in detta palette, da cui viene generato
il pixel (lookup table). 
Nella conversione da RGB a 8bit indexed, il programma di grafica applica
un algoritmo di nearest-color che seleziona i valori piu' frequenti.
La grayscale, d'altra parte, e' generata sulla base della luminosita'
del pixel, luminosita' che puo' essere vista come una funzione "distanza
dall'origine" in uno spazio tridimensionale RGB. Un programma un pelo
piu' scaltro potrebbe adattare la luminosita' a seconda della percezione
umana, ma questo e' un altro paio di maniche.
beh, tutto questo per dire cosa?
Che applicando da RGB direttamente la trasformazione grayscale,
quell'effetto di ghost image che si ottiene con la sogliatura scompare,
probabilmente (non ho avuto modo di verificarlo) in parte dovuto anche
al tipo di file di partenza (JPG, quindi con compressione lossly).
mentre se si effettua un doppio passaggio RGB->8bit-indexed->grayscale,
tale effetto si ripresenta.
Un ulteriore smentita alla mia teoria iniziale e' dato dal metodo di
distribuzione dei pixel.
Si e' parlato di correlazione. Immaginiamo di prendere un messaggio
formato da simboli, e applichiamovi una permutazione. Che succede alla
correlazione? La distribuzione dei simboli fa parte dell'informazione
del messaggio.
Immagino quindi che un rilevatore di correlazione dovrebbe essere
abbastanza fuorviato se  e' tarato per rilevare un set di simboli
ordinati, e tali simboli vengono "mescolati" e "distribuiti" in mezzo ad
altra informazione. 
Nella fattispecie, per generare la mappa steganografica (chiamiamolo
cosi' lo schema di distribuzione dei bit steganografati all'interno
dell'immagine ospite) ho utilizzato un generatore di numeri
pseudo-casuali come generatore di rumore deterministico: si inizializza
tale PRNG con un seme determinato dall'utente che funge come chiave.
All'atto dell'estrazione, il PRNG genera la stessa sequenza, permettendo
l'estrazione del file.
Attacchi possibili:
1) Statistico: effettivamente per quanto poco la correlazione su
immagini "poco disturbate" tende a crescere, permettendo quindi un
rilevamento della steganografia
2) Forza bruta: si genera tutti i possibili semi per il PRNG e si
estraggono tutti i possibili messaggi. Il sistema soffre di una
debolezza, che e' quella di dover memorizzare la lunghezza del messaggio
originario nei primi 32 bit steganografati, per cui si potrebbe scartare
i semi non compatibili, che generano quindi una lunghezza al di fuori
della capacita' del programma ospite. E' un metodo che richiede molto
tempo nonostante la semplicita' dell'algoritmo.
Queste sono le considerazioni che mi sono venute spontanee durante la
stesura di questi programmi.
Non vogliono, naturalmente, essere programmi di una qualche utilita' al
di fuori di quella puramente accademica e speculativa, sono lungi dal
voler essere utilizzati per qualche cosa di critico che sia al di fuori
della chiacchierata tra hobbysti. Soprattutto le tecniche utilizzate
sono molto banali, frutto del mio scazzo serale (che volete, la TV
italiana fa piuttosto schifo), e per di piu' mi sono interessato a
questo campo solo di recente.
Ogni critica o commento e' piu' che apprezzato.
Fatemi sapere
HappyCactus
PS: non dimenticate di dare una occhiata al mio desktop :PPP
-- 
HappyCactus - Linux User #209744 - LFS User #6046 - >>> SMSPM1050 <<<
              YAGF Member Group >>> 
www.google.com
 <<<
Ci sono 10 categorie di persone al mondo: quelle che capiscono
il sistema binario e quelle che non lo capiscono.

 Fatemi sapere
Non dubitare... ;-)
-- 
Carlo Luciano
GPG ElG/DSA 4096/1024 Key: 
http://web.tiscali.it/clbianco/clbianco.asc
ID: 0x5324A0DA - Fingerprint: 8B00C61034120506111B143DEDBF71B45324A0DA

 Non dubitare... ;-)
Nel frattempo provo a vedere se riesco ad estendere l'uso del programma
anche ai 256 colori e ai 24 bit.


 anche ai 256 colori e ai 24 bit.
E io intanto mi studio un po' di documentazione delle libpng, e magari mi 
scarico una versione aggiornata... ;-)


 mi scarico una versione aggiornata... ;-)
E' piu' probabile che sia la woody non proprio aggiornatissima...


 E' piu' probabile che sia la woody non proprio aggiornatissima...
No, mi sa che il problema e' nel Makefile. La riga di comando
gcc -lpng pngstego.o pnghelper.o -o pngstego
produce l'errore, mentre con la riga di comando
gcc pngstego.o pnghelper.o -o pngstego -lpng
tutto sembra funzionare bene. Inutile dire che "make" si intestardisce ad
eseguire la prima delle due... ;-)
Tutto questo per quanto riguarda CygWin. Ho provato anche a compilarlo con 
MinGW "liscio", ma ho dei problemi sulle funzioni "random" e "srandom"...


 "srandom"...
Non conosco minimamente MinGW (quasi manco so che cosa e') ma se
risolvi, fammi sapere che introduco l'eventuale modifica (con relativi
define).
BTW, ho aggiornato alla versione 0.3, che supporta anche il formato RGB.
Ho trovato delle cose interessanti:
Anche convertendo da formato da jpg, il piano dei bit meno significativi
conservano una certa informazione, e sono tutt'altro che aleatori. La
cosa e' lampante nel formato RGB.
semi-premessa. 
Il tool imgthr permette di selezionare alcuni piani dell'immagine. esso
accetta una tripla di valori nel formato r,g,b che viene utilizzata in
AND con i dati della matrice immagine, uno per ciascun canale del
colore. 
Dando il comando
imgthr -m 1,0,0 imgin.png imgout.png
viene creata una immagine con evidenziati i soli bit meno significativi
del canale rosso dell'immagine sorgente. il bit in realta' viene
mascherato ed evidenziato, altrimenti il pixel di livello 1 non verrebbe
visualizzato: if (pix & mask) newpix=255; else newpix=0; .
Applicando tale filtro ad una immagine convertita dall'RGB, non si
ottiene alcuna immagine residua, almeno ad occhio.
E' interessante pero' filtrare su tutti e tre i piani
imgthr -m 1,1,1 imgin.png imgout.png
magia! Ecco comparire un'immagine che anche per una immagine jpeg ha una
rassomiglianza con quella originale.
alcune idee per chi ha voglia di pastrocchiare con il C.
1) valutare la derivata discreta dell'immagine steganografata,
sogliandola a 2, cioe' evidenziare i punti in cui la differenza con
quelli vicini e' inferiore a 2. Tra essi necessariamente ci sara'
qualche pixel contenente l'informazione steganografata.
2) valutare le curve di livello dell'immagine (segmentazione?)
3) studio statistico? valutare i parametri statistici per zone
dell'immagine.


 alcune idee per chi ha voglia di pastrocchiare con il C.
Ehm... Non e' che hai in programma una versione in Fortran? ;-))))


 Ehm... Non e' che hai in programma una versione in Fortran? ;-))))
Purtroppo non conosco il fortran :(((


 Purtroppo non conosco il fortran :(((
Beh, io non conosco il C... :-((


 Beh, io non conosco il C... :-((
Mi pare che come team funzioni, comunque :)


 Mi pare che come team funzioni, comunque :)
Direi di si'... ;-)


eseguire la prima delle due... ;-)
Sě, le librerie devono essere sempre l'ultima cosa della riga di comando di
gcc, č risaputo ^_^
Credo sia piů "colpa" del Makefile che non di "make"^_^
-- 
L a p o   L u c h i n i
l a p o @ l a p o . i t
w w w . l a p o . i t /

per perdere definitivamente i dati!
Ecco la soluzione (portabile) ai tuoi problemi 0=)
http://www.math.keio.ac.jp/~matumoto/emt.html


 dell'immagine.
Questo, invece, l'ho capito :-)
Cristiano

 
http://www.math.keio.ac.jp/~matumoto/emt.html
Incredibile! In tutto il mondo ho trovato uno che la pensa come me. :-)
Non necessariamente per il generatore consigliato (che è ottimo) quanto
per il concetto: perché usare un generatore di serie (di dubbia qualità
e diverso da un compilatore ad un altro) piuttosto che usare un
generatore di ottima qualità, veloce, che non varia in funzione del
compilatore?
Ovviamente se qualcuno ritiene che per il prorpio programma MT19937 è
"troppo", può sempre ripiegare per lfsr113 o un mwc che sono ottimi e
velocissimi.
Cristiano

velocissimi.
Beh, è difficile considerarlo "troppo"... dato che oltre a essere miliardi
di volte migliore di rand() (ha un ciclo di 2^19937-1 se non erro) è anche
quattro volte più veloce 0=)
...se solo il prossimo standard C lo includesse 0=)
(già è utilizzato come standard in molti posti, compresi alcuni compilatori)


 compilatori)
Se pensi che razza di generatori implementano di serie nei compilatori
sotto winzozz... Credo che vedere incluso di serie MT19937 sia solo un
sogno (almeno nei compilatori commerciali).
Io credo che gli stessi "progettisti" dei compilatori abbiano una certa
ignoranza in materia di generatori.
Per dirne una, nel compilatore della Borland (che usa un lcg) hanno
invertito i bit meno significativi con quelli più significativi  :-(*) e
i risultati si vedono.
Cristiano

i risultati si vedono.
Ecco, già i numeri di base erano abbastanza orrendi, se poi li incasini
pure... 0=)


 ^_^
Volendo definire un generatore di numeri pseudo-casuali (prng) come uno
la cui sequenza dei numeri in uscita non è distinguibile da una generata
da un generatore di numeri realmente casuali (rng), un lcg non dovrebbe
nemmeno essere considerato un prng in quanto fallisce la maggior parte
dei test di uso generale a dimostrazione che la sequenza è distinguibile
da quella di un rng.
Probabilmente qualcuno riuscirebbe a scrivere un test ultra complesso in
grado di far fallire qualunque prng, ma un lcg ha proprio delle
caratteristiche troppo "strane" per essere considerato propriamente un
prng.
Cristiano

 Questo, invece, l'ho capito :-)
Pensavo di raffrontare le trasformate di fourier bidimensionali del
piano dei bit meno significativi con quelli subito successivi.
In una immagine "normale" dovrebbero avere una certa correlazione (?),
su una immagine stenografata totalmente il primo sara' una trasformata
ovunque uniforme (rumore bianco) mentre la prima sara' uno immagine con
dei picchi... tutta da valutare, questa ipotesi.
Faccio presente che un eventuale "nasconditore" avrebbe comunque
interesse a utilizzare immagini molto rumorose di loro... Quindi il
detecting si fa decisamente piu' complicato.
-- 
HappyCactus - Linux User #209744 - YAGF 
http://www.google.com
 
http://pngstego.sourceforge.net


 Progresso) 
http://pngstego.sourceforge.net
 :)
Quando vado sulla pagina di download mi da un:
"This Project Has Not Released Any Files".


 "This Project Has Not Released Any Files".
Sono sul CVS solamente, per ora.
Volevo inserire un README nel tar.gz, prima di fare il rilascio dei
sorgenti.
Abbi ancora un po' di pazienza! peraltro non sono cambiati dall'ultima
volta se non per l'inserimento dei tuoi due Makefile


 volta se non per l'inserimento dei tuoi due Makefile
Non ti preoccupare, non volevo assolutamente metterti fretta. Avevo solo
paura che ci fosse stato qualche problema con il server di SourceForge e
quindi volevo informarti della cosa. 
Scusami, forse il mio post era un po' brusco, il fatto e' che a una
certa ora non connetto piu' molto... ;-) 


 certa ora non connetto piu' molto... ;-) 
ettecredo, alle 2.41 della notte! Io non ho piu' l'eta' per certe cose.
BTW, hai mai dato una occhiata a questo:
http://www.outguess.org/
http://www.outguess.org/articles.php
in particolare ho dato una occhiata al primo articolo, "Detecting
Steganographic Content on the Internet"
http://www.citi.umich.edu/u/provos/cv.html#papers
molto interessante.


 molto interessante.
Si', e' sembrato anche a me dalla scorsa che gli ho dato. Ma si dedica
solo ai Jpeg o sbaglio? E' vero che la steganografia in files Jpeg non ha
il problema dell'analisi visuale, ma mi sembra che anche lei uscisse
maluccio dall'analisi statistica di quell'altro articolo di cui abbiamo
discusso un paio di settimane fa... 
Alla fine di quell'articolo sembrava che la cosa migliore fosse
steganografare dentro immagini RGB in BMP con S-Tools4, a patto pero' che
i bit del messaggio fossero *molto pochi* rispetto ai bit totali
dell'immagine...


 dell'immagine...
Questo senz'altro. Se i bit sono "molto pochi" e' difficile che abbiano
una rilevanza statistica "globale", sull'intero insieme dei dati, ma,
imho, potrebbero avere una debolezza su un'analisi statistica locale... 
Non so, devo rifletterci ancora molto.
Intanto provo a trovare il tempo di inserire un'analisi di fourier nei
miei tool, devo studiare le librerie wfft...


 miei tool, devo studiare le librerie wfft...
Se ti serve una libreria ultra-veloce in c per la fft non fare
complimenti :-)
Cristiano

 vedi i parametri
definiti da un ANSI C di non so bene che versione... mentre un "man rand"
sul mioFreeBSD (aggiornato a pochi giorni fa) dice:
The rand() and srand() functions conform to ISO/IEC 9899:1990 (``ISO C89'').
Mentre su cygwin (che usa la newlibc), dice:
`rand'  is required by ANSI, but the algorithm for pseudo-random number
generation is not specified; therefore, even if you use the same random
seed,  you  cannot expect the same sequence of results on two different
systems.
BTW: difficile leggere lo standard ISO 9899:1990 vero e proprio... costa
44chf anche in PDF...


 standard C89, ma forse non lo è nellaprima versione del C.
Sì, ma afaik lo standard, purtroppo, si limita a dire che RAND_MAX deve
essere da almeno 15 bit, niente di più.
Cristiano

essere da almeno 15 bit, niente di più.
Dagli spizzichi e bocconi che ho trovato in giro questo è quello che diceva
il "vecchio C", mentre *credo* che dalla C89 in poi sia definito "meglio".
Difficile da verificare, dicevo, dato che lo standard non è uno standard
"libero"... e non ho certo voglia di spendere decine di dollari solo per
togliermi questo vezzo eheh 0=)


 dollari solo per togliermi questo vezzo eheh 0=)
Nemmeno io :-) Ma tanto noi non abbiamo paura ad usare generatori
decenti... che ce ne frega :-)
Cristiano

 miei tool, devo studiare le librerie wfft...
In bocca al lupo!


 stesso del GCC di FreeBSD ^_^)
Tieniti forte. Questo e' CygWin:
athlon:~/mingw>gcc -malign-double -ffast-math -fstrength-reduce -
fexpensive-optimizations -funroll-loops -O6 -frerun-loop-opt -falign-loops 
-mcpu=athlon -march=athlon -mfpmath=387 -mmmx -m3dnow prnd.c -o prnd.exe
athlon:~/mingw>time ./prnd.exe
Ciclo: 946779788
real    0m30.089s
user    0m0.000s
sys     0m0.000s
athlon:~/mingw>gcc -malign-double -ffast-math -fstrength-reduce -
fexpensive-optimizations -funroll-loops -O6 -frerun-loop-opt -falign-loops 
-mcpu=athlon -march=athlon -mfpmath=387 -mmmx -m3dnow -mno-cygwin prnd.c -o 
prnd.exe
athlon:~/mingw>time ./prnd.exe                                                  
Ciclo: 12444                                                                    
real    0m0.075s
user    0m0.000s
sys     0m0.000s
E questo e' MinGW/MSYS:
Carlo Luciano Bianco@ATHLON ~
$ gcc -malign-double -ffast-math -fstrength-reduce -fexpensive-
optimizations -f unroll-loops -O6 -frerun-loop-opt -falign-loops -
mcpu=athlon -march=athlon -mfpmath=387 -mmmx -m3dnow prnd.c -o prnd.exe
Carlo Luciano Bianco@ATHLON ~
$ time ./prnd.exe 
Ciclo: 12444
real    0m0.110s
user    0m0.000s
sys     0m0.000s
Se non altro non c'e' differenza tra CygWin con -mno-cygwin e MinGW...


 In bocca al lupo!
Vi terro' informati, naturalmente


 Non sono ancora riuscito a buttare giu' il readme :(
Non ti preoccupare, non c'e' fretta... ;-))


 Non ti preoccupare, non c'e' fretta... ;-))
L'ho scritto ieri sera ed e' disponibile su sourceforge.
pngstego.sourceforge.net
ah, tu hai mail :)


 ah, tu hai mail :)
Uhm... per quella dovro' aspettare stasera, ti faro' sapere... ;-)


 Appena scaricato! ;-)
Oggi ho un pochetto lavorato sul modulo FFT, vediamo che ne viene
fuori...
-- 
HappyCactus - Linux User #209744 - 
http://pngstego.sourceforge.net
 
              pngstego 0.3.2 has been released! 
/* Ci sono 10 categorie di persone al mondo: quelle che capiscono */
/* il sistema binario e quelle che non lo capiscono.              */

 fuori...
Tienici informati... ;-)
