Crittoanalisi |
Come ho scoperto la cifratura di Microsoft Access. di Riccardo Bartolini |
|
Premesso che questa considerazione vuole essere solo a scopo didattico o al limite come sistema di password recovery, non mi ritengo responsabile dell'uso che verranno fatte di queste informazioni.
Riccardo Bartolini
Mi trovavo alle prese con lo sviluppo delle pagine sulla crittoanalisi di questo sito, e stavo pensando quale esempio potevo utilizzare per attirare l'attenzione di un utente medio. Non volendo perdere troppo tempo e sapendo che la protezione di Microsoft Access era ritenuta debole, ho avuto l'idea di prendere tale programma come cavia. Ero sicuro che non avrei trovato difficoltà, invece... è stato anche più semplice del previsto!
Il risultato di questa mini-esperienza, ovvero il programma che ne è scaturito come esempio, utilizzabile anche come password recovery in caso di perdita della password, è presente in area donwload col nome di AccessPwd.
Materiale utilizzato La lista della "spesa" è molto breve:
Note per "non addetti ai lavori" La rappresentazione esadecimale utilizzata più avanti, è una forma di numerazione in base 16, a differenza del sistema decimale in base 10. Generalmente i numeri esadecimali sono terminati con una lettera "H" (Hex) per distinguerli. La rappresentazione esadecimale è comoda perchè riesce a rappresentare le 255 combinazioni possibili date dagli 8 bit, sempre con soli 2 caratteri, dando luogo ad una visione d'insieme ordinata ed in poco spazio. Per far stare i 255 bytes in soli 2 spazi, l'esadecimale utilizza anche le lettere dell'alfabeto da A ad F. Piccolo esempio/paragone tra decimale e esadecimale:
1=1h 2=2h .... 9=9h 10=Ah 11=Bh .... 15=Fh 16=10h 17=11h ..... 255=FFh
Come ho agito Sono partito con l'analisi di Access 97. Ho creato un data base vuoto (DB1) ed ho impostato una password di 3 caratteri. Ho copiato il file sotto altro nome (DB2) ed ho annullato la password su questa copia del DB. Ho effettuato una comparazione ed ho scoperto quanto riporto:
Confronto dei file D:\db1.mdb e D:\DB2.MDB
Il primo numero rappresenta l'indirizzo relativo da inizio file. I due numeri successivi sono il contenuto del primo DB e del secondo DB. Gli indirizzi visualizzati sono solo quelli che contengono bytes diversi. Attenzione a non creare i due DB tramite Access, trovereste tantissime differenze che non hanno niente a che fare con la password. Il DB2 deve essere una copia del DB1.
A questo punto sono passato a fare esperimenti sulla lunghezza della password per verificare che fosse sequenziale. Poteva anche essere che quell'indirizzo 600 fosse un carattere della password. Inserendo la massima lunghezza consentita dal DB, ho verificato che la comparazione riportasse come differenza tutta la lunghezza. E` stato così, e quindi una conferma che la password inizia all'indirizzo 42H e finisce all'indirizzo 42H + (Lunghezza password-1). Primo passo OK.
Spazi riservati alla password.
Adesso dovevo scoprire come risalire alla password in chiaro da questa serie di Bytes. Infatti, sebbene la protezione sia ridicola, alla Microsoft non arrivano certo ad essere così fiduciosi nel prossimo da lasciare la password dentro il file in chiaro. Se così fosse, avendo inserito la password "aaa" avrei dovuto leggere negli indirizzi 42h, 43h e 44h un valore pari a 61h (97 in decimale). Invece non è stato ovviamente così. Quale metodo avranno applicato per cifrare la password?
La password "aaa" è stata inserita crittografata.
Ci vuole molto poco ad immaginarlo vedendo i due files o anche semplicemente la comparazione sopra esposta: quale operazione trasforma un valore 61h (la lettera "a" minuscola della password) che dovrebbe essere dentro il DB1, nell'equivalente E7h? Potrebbe anche essere una somma, dato che E7h è superiore a 61h, ma potrebbe pure essere un'altra operazione... diciamo l'XOR, molto comoda in programmazione, perchè per decifrare basta compiere una seconda volta la stessa operazione XOR evitando problemi di riporti o somme con modulo. Devo dire che ero sicuro avessero usato l'XOR perché ben si accoppia all'economica protezione usata (in termini di lavoro di programmazione). Essendo quasi certo, per prima cosa ho provato proprio l'XOR. L'XOR è un operatore (chiamato anche Or Esclusivo) che necessita di due operandi, come per l'effettuazione di una normale somma. Non sto a spiegarne il funzionamento altrimenti finisco fuori tema, ma giusto per informazione ai lettori a digiuno di informatica (anche se dubito che tali persone si trovino a leggere questa pagina), dico solo che questo tipo di operatore esegue una somma particolare. La cosa per cui viene spesso utilizzato in questi casi è la sua particolarità di saper riportare la somma effettuata, nel valore precedente, come se fosse la prima volta una somma, la seconda volta una sottrazione, in automatico. Es.: 1 xor 2 = 3 3 xor 1 = 2 3 xor 2 = 1
Proseguiamo. Dovevo quindi scoprire perchè una "a" (valore ascii esadecimale 61h) fosse invece stata scritta nel DB1 come E7h. Quale operazione trasforma 61h <operatore> <2' operando> = E7h ? E dov'è il secondo operando? Domande facili: nelle stesse posizioni occupate adesso dalla password, prima c'era un altro valore. Idea immediata: forse quella è la chiave di crittazione, ovvero, in stesso indirizzo si trova il secondo operando da utilizzare con l'xor. Proviamo a vedere se l'operazione torna:
00000042: E7 86 E7h (valore db1 con password) xor 86h (valore in stesso indirizzo nel db2 senza pass) dovrebbe dare 97h... infatti è così. Lo stesso dicasi di 9Ah xor FBh ecc.
La protezione è ormai forzata.
Note particolari per programmatori A questo punto per creare un programma che visualizzi la password segreta di un DB, basta aprire da programma il db interessato, in binario, leggere le locazioni da 42h fino a 50h e farci l'xor con i valori delle stesse locazioni prese da un DB senza password e visualizzare il corrispondente carattere ASCII che corrisponde a tale valore.
Access 2000 Non mi dilungo troppo: il sistema utilizzato è lo stesso, con la differenza che la password è lunga 20 caratteri invece di 14. Il punto di partenza iniziale è sempre lo stesso, ma deve essere letto un byte si ed uno no (quindi per una lunghezza di 40)
Sperando in nessuna denuncia da parte Microsoft per questo articolo ad esclusivo scopo didattico (e d'altra parte non è colpa mia se non si impegnano a fare protezioni visibili ad occhio nudo), saluto tutti gli amici programmatori della mailing list VB-tips e quelli della editrice Infomedia, molti dei quali si sono prenotati in anticipo per la visita di questo sito.
Note finali Di versione in versione non è detto che la chiave di cifratura resti sempre la stessa. Ammesso che non venga cambiato il metodo, basterà comunque fare l'xor con i nuovi valori prelevabili da un DB senza password di tale versione.
Riccardo Bartolini
|