FreeBASIC – Esercizi

Steganografia
Vi propongo un altro esercizio per il FreeBASIC. Si tratta di un programmino scritto da me che consente di leggere un messaggio “nascosto” in una immagine. Il file immagine che contiene il messaggio è questo qui sotto:

foto con messaggio nascosto :)

Si tratta, come vedete, di una immagine in formato BMP con 256 toni di grigio. L’utilizzo di questo formato è dettato dalla semplicità di decodifica di tale tipo di file. Invito chiunque fosse interessato (basta fare una ricerca su Google) a studiare cosa c’è scritto nell’intestazione (lo header) di un file .BMP ; non è per niente complicato.
Bene: come possiamo “nascondere” un testo in una fotografia ? Semplice… ogni pixel di una foto in formato BMP a 256 toni di grigi è un byte che può avere un valore da 0 a 255 ; lo zero rappresenta il nero totale, il 255 invece è il bianco pieno. Tutti i valori intermedi sono i vari livelli di grigio. Allora noi che facciamo ? prendiamo il bit meno significativo di ognuno di questi bytes e lo modifichiamo per comporre una sfilza di bits che saranno il nostro messaggio testuale “nascosto”. Cambiare il colore di un pixel da 255 a 254, per esempio, risulterà totalmente invisibile all’occhio umano, perché si passerà da un bianco pieno a un bianco appena un po’ meno pieno. Lo stesso dicasi di un pixel che aveva valore 000 (tutto nero) e passa a 001 (appena un po’ meno nero). L’occhio non percepisce queste piccole differenze, specie perché è attirato dalla visione “globale” della fotografia.
Vi propongo il listato del programma sorgente in FreeBASIC che esegue il lavoro di decodifica. Appena lo avrete compilato, mandatelo in esecuzione e vi troverete un nuovo file di testo, chiamato epgficara.txt, contenente un mio breve curriculum vitae. Nota importante: mettete nella stessa cartella il programma che compilerete e il file immagine epgficara.bmp che potrete scaricare da questa pagina cliccando con il tasto destro e facendo “salva con nome” e assicuratevi che la cartella in cui mettete le cose sia provvista dei diritti di scrittura, altrimenti il programma non potrà produrre il file di testo in uscita.
Ecco, quindi, il file sorgente per FreeBASIC:

dim shared as string nfi, a
dim shared as long start, leng, fl
dim shared as ubyte db, src

print "Decodifica steganografia in file BMP - 256 livelli grigio - V13.0316 - (c)2013 Emilio P.G. Ficara"
nfi = "epgficara.bmp" ' nome del file da decodificare
If Dir(nfi) = "" then
  Print "Errore: il file ";nfi;" non esiste"
  Goto exits
EndIf

Open nfi for binary as #1 ' apri il file da leggere
a = Input$(54,#1) ' leggi solo l'intestazione (header)
If Left(a, 2) <> (Chr(&h42) + Chr(&h4d)) then ' se errato il "magic number"
  Print "Errore: non è un file BMP"
  Goto exits
EndIf
If Mid(a,&h1C+1,2) <> (Chr(8)+Chr(0)) then ' se non è 8 bit per pixel
  Print "Errore: non è 8 bit per pixel"
  Goto exits
EndIf
If Mid(a,&H1E+1,4) <> (Chr(00)+Chr(00)+Chr(00)+Chr(00)) then ' se è compresso
  Print "Errore: è compresso RLE-8 o RLE-4"
  Goto exits
EndIf
If Mid$(a,&H2E+1,4) <> (Chr(00)+Chr(01)+Chr(00)+Chr(00)) then ' se non è 256 toni di grigio
  Print "Errore: non è 256 toni di grigio"
  Goto exits
EndIf

start = Asc(Mid(a,&H0a+1,1)) ' calcola l'indirizzo di inizio del primo pixel d'immagine
start = start + Asc(Mid(a,&H0b+1,1))*&H100
start = start + Asc(Mid(a,&H0c+1,1))*&H10000
start = start + Asc(Mid(a,&H0d+1,1))*&H1000000

leng = Asc(Mid(a,&H22+1,1)) ' calcola lunghezza in bytes dell'immagine
leng = leng + Asc(Mid(a,&H23+1,1))*&H100
leng = leng + Asc(Mid(a,&H24+1,1))*&H10000
leng = leng + Asc(Mid(a,&H25+1,1))*&H1000000

Open "epgficara.txt" for output as #9 ' apri file di uscita (testo)

fl = 54 ' salta la tabella dei colori
While fl < start
  get #1,,src ' leggi un pixel (un byte) del file BMP
  fl = fl+1
Wend

fl = 0 ' contatore dei bytes in input
db = 0 ' byte ricomposto dai singoli bits (inizialmente a 0)
While fl < leng
  If (fl > 0) And ((fl and 7) = 0) then ' per 8 bytes di immagine (excludendo il primo)
    Print #9, Chr(db); ' scrivi un carattere sul file di output (testo)
    db = 0 ' azzera il byte per la ricomposizione dei bits
  EndIf

  get #1,,src ' leggi un pixel (un byte) dal file BMP
  If (src and &H01) then ' se il nostro bit nascosto è 1
    db = db Or (2 ^ (fl and 7)) ' metti a 1 il relativo bit nel byte ricomposto
  EndIf
  If db = &Hff then exit while ' se trovo la combinazione &HFF (8 volte 1), il testo è finito
  fl = fl + 1 ' altrimenti incremento il numero di bytes letti
Wend

exits:
close ' chiudi tutti i files aperti
End

P.S. se qualcuno preferisse avere il programma già compilato e pronto per essere eseguito, potrà scaricare il file stegodec.zip , decomprimerlo in una qualsiasi cartella, aggiungere -come detto prima- il file BMP da decrittare e lanciare l’eseguibile. Non è richiesta alcuna installazione, non viene modificata nessuna voce di registro.