Steganografia Un esempio pratico
Il formato TAR Possiamo pensare ad un archivio TAR come ad un contenitore di file. Per ogni file nellarchivio viene memorizzato: –il contenuto del file –informazioni aggiuntive (nome file, permessi, ecc.) Possiamo usare alcuni byte delle informazioni aggiuntive per memorizzare un messaggio steganografato.
Informazioni aggiuntive Per ogni file presente nellarchivio sono presenti le seguenti informazioni: nome permessi user id, user name group id, group name dimensione tempo dellultima modifica altre informazioni per gestire file non regolari (es. link, device, ecc.)
Il campo mtime Il campo mtime, di 36 bit, memorizza la data dellultima modifica al file. 36 bit Essa è codificata come il numero di secondi trascorsi dalle ore 0:00 del 01/01/1970. Possiamo usare gli ultimi 8 bit per memorizzare un byte di informazione. La data originale è distorta al più di 255 secondi, ovvero 4 minuti e 15 secondi.
Codifica di un messaggio Dato un messaggio lungo n byte, lo codifichiamo su n+4 byte. I primi 4 byte rappresentano la lunghezza del messaggio. I successivi n byte contengono il messaggio vero e proprio. Lunghezza massima di un messaggio: 4 Gb. Esempio: –messaggio = ciao –lunghezza = 4 –archivio di 9 file Nome mtime File1 xxxxxxx File2xxxxxxx File3xxxxxxx File4xxxxxxx File5xxxxxxx File6xxxxxxx File7xxxxxxx File8xxxxxxx File9xxxxxxx xx ciaociao F F xx
Codice sorgente - steganotar.py Scritto in Python 2.3 ( Perché Python? –Semplice –Portabile (Linux, Windows, Mac, ecc.) –Modulo standard per i file TAR Chi non conosce Python? –Sembra pseudocodice. In laboratorio è installato Python 1.5, perciò steganotar.py non funziona.
Codifica di un messaggio Data una stringa in input, dobbiamo produrre unaltra stringa così formata: –i primi 4 byte memorizzano la lunghezza, espressa in notazione big endian. –i successivi byte memorizzano il messaggio vero e proprio. La funzione struct.pack effettua la conversione tra intero a 32 bit e stringa di byte in big endian. def encode_message(data): length = struct.pack('!i', len(data)) return length + data
Decodifica di un messaggio Dato un messaggio codificato, dobbiamo decodificarlo per produrne una rappresentazione usabile. Prima di tutto leggiamo i primi 4 byte e li convertiamo in un intero a 32 bit (con la funzione struct.unpack). Ora che sappiamo la lunghezza, sappiamo quanti byte leggere per ottenere il messaggio originale. def decode_message(data): length = struct.unpack('!i', data[:4])[0] return data[4:4+length]
for index, filename in enumerate(files): tarinfo = tar.gettarinfo(filename) if index < len(data): char = data[index] tarinfo.mtime &= MASK tarinfo.mtime |= ord(char) tar.addfile(tarinfo, file(filename)) Creazione di un archivio Alcune variabili utilizzate: –data: messaggio gia` codificato (array di byte) –tar: oggetto che rappresenta l'archivio tar –files: lista di nomi di file da inserire nell'archivio –MASK = 0xFFFFFFF00
Lettura di un archivio def read_tar(filename): tar = tarfile.open(filename, 'r') data = [] for tarinfo in tar: # ottiene lultimo byte di mtime char = tarinfo.mtime & 0xFF data.append(chr(char)) tar.close() return ''.join(data)
Dimostrazione pratica tmp]$ ls prova file01 file02 file03 file04 file05 file06 file07 file08 file09 file10 file11 file12 file13 file14 file15 tmp]$ ls -l prova/file05 -rw-r--r-- 1 anto anto 0 dic 12 15:21 file05 tmp]$ steganotar.py --encode prova.tar prova/ Messaggio tmp]$ tar tvf prova.tar | grep file05 -rw-r--r-- anto/anto :22:53 prova/file05 tmp]$ steganotar.py --decode prova.tar Messaggio
Memorizzare un intero file Se dalla linea di comando non è specificato alcun messaggio, steganotar.py lo legge da standard input. Possiamo sfruttare questa caratteristica per steganografare file arbitrari in un archivio TAR. Esempio: creiamo un archivio che contiene i sorgenti del kernel di Linux: sono file, quindi possiamo memorizzare circa 14 Kb di informazioni. tmp]$ steganotar.py --encode linux.tar /usr/src/linux < \ Steganography.txt tmp]$ steganotar.py --decode linux.tar > Steganography2.txt tmp]$ diff Steganography.txt Steganography2.txt
Implementazioni alternative Abbiamo scelto di usare il campo mtime, ma potevamo anche scegliere diversamente. In particolare, i campi uid e gid non sono quasi mai utilizzati: i corrispettivi user name e group name hanno sempre la precedenza. I campi uid e gid ci avrebbero permesso di memorizzare 4 byte per ogni file nellarchivio. Purtroppo nella maggior parte dei file TAR i campi uid e gid hanno sempre lo stesso valore, per cui sarebbe facile scoprire che un file è steganografato.