Una giovanissima azienda mi ha contatto nelle settimane scorse chiedendomi di verificare la sicurezza del sistema di attivazione online di un loro prodotto commerciale di prossima uscita.
Mi è stato fornito un indirizzo internet al quale possono accedere solo determinati IP. Ad attendermi un form di registrazione per richiedere un codice di attivazione temporaneo di 15 giorni.
Dopo essermi registrato, ed aver ricevuto via email la chiave di attivazione per un periodo di prova di N giorni procedo al setup ed avvio il programma.
Andando a supporre che il programma verrà distribuito unicamente attraverso internet, la prima domanda che mi sono posto è stata, se il loro sistema di attivazione può essere effettuato unicamente Online.. cosa succede se improvvisamente la rete cade e/o il computer su cui gira non è online? In teoria è una cosa che non dovrebbe mai succedere visto che il programma elabora dati presenti su n° internet e li restituisce formattati all’utente. Eccone il risultato.
Nel form di attivazione inserisco il mio codice seguito da altri dati ed invio i dati.
Ed ecco il primo errore di programmazione.
Eccezione .NET non gestita.. “Impossibile contattare il WebService”.
Questo è un grave errore di design dell’applicazione. Come tutti sappiamo, qualunque eccezione andrebbe gestita. Con questa eccezione si capisce che il programma utilizza un WebService per inviare i dati al server centrale dell’azienda.. il quale, dopo averli verificati, consentirà o negherà l’accesso alla risorsa.
Per andare a scoprire realmente cosa fosse successo e in che modo riuscire ad utilizzare il software in questione ho iniziato la mia attività di reverse engineering.
Il primo passo è stato quello di preparare il “Working Enviroment” ovvero.. un ambiente composto da tools e tutto il materiale necessario per la prima fase di analisi del comportamento del software.
Nel mio caso :
Reflector
Blocco Notes
Matita
Gomma
Come abbiamo detto, il software, sia in fase di Trial che in fase di Full Setup deve essere attivato via Internet. Il primo punto su cui andare ad investigare e la void associata al click del bottone presente sul form di attivazione. Dato che, il form viene visualizzato all’apertura del programma, il punto da cui far partire tutte le analisi è l’entry point
Main() : Void
Il sistema parte con un controllo di questo tipo.
#ragionamento 1 “Se l’utente ha un codice di attivazione valido, lancia l’applicazione.. altrimenti fai partire la gestione della Free Trial.”
Siamo al bivio. Il sistema per verificare il sistema di attivazione va ad eseguire una serie d’istruzioni che, alla fine, ritornano un valore booleano. Con il controllo dell’utilizzo delle funzioni si nota che questa funzione viene chiamata due volte.. di cui una da Main e l’altra dal sistema di attivazione SetKey.
Si parte quindi ad andare ad analizzare il sistema di Trial il quale non fa altro che andare a chiamare un metodo di un webservice con parametri input di “codice trial, indirizzo email”.
Il programma si aspetta 4 risposte:
1 – Non esiste alcun prodotto registrato sulla banca dati dell’azienda relativa a quel codice.
2 – Il codice inserito è corretto, ma l’email no
3 – Il prodotto è già stato registrato
4 – Grazie per aver attivato il prodotto!
Questi valori vengono controllati da uno switch.
Il codice del case 4 è il seguente
case 4:
{
LicenseUtils.SetActivationCode(this.m_sActivationCode);
Interaction.MsgBox("Thank you for registering the !", 0x30, null);
this.LaunchApp();
goto Label_00DF;
}
Vedete la funzione sActivationCode? E’ la disfatta totale del sistema di protezione dell’applicazione.
E’ comunque interessante andare a vedere il sistema di generazione codice seriale. Davvero originale J
Per prima cosa viene recuperato il MAC Address tramite WMI (System.Managment), ne viene eseguito lo split su i caratteri “:” e successivamente mescolato in un ordine ben preciso con dei valori stringa del tipo
"00571", textArray1[0], "51-AB", textArray1[1], "ZY", textArray1[2], textArray1[4], "-", textArray1[3], "TP", textArray1[5]
Il risultato di questa operazione è il codice seriale dell’applicazione. Questo valore verrà inserito in una chiave ben precisa del registry tramite una chiamata alle API Win32. Lo switch termina con il lancio dell’applicazione senza alcun tipo di restrizione.
Al successivo riavvio, l’applicazione andrà a verificare, nel caso in cui esista una chiave di registro, il suo valore. Se il valore corrisponde a quello calcolato dalla funzione per la generazione del codice seriale.. l’applicazione parte senza chiamare il WebService.
Le debolezze di questo sistema di autentificazione sono principalmente due.
Non è stato utilizzato alcun sistema per rendere il codice illeggibile ai decompilatori .NET di alcun tipo (Obfuscator etc), la generazione del codice seriale viene eseguito localmente.
La mancanza di utilizzo di un “offuscatore” del codice .NET ha notevolmente velocizzato il sistema di reverse engineering, nel caso in cui, questo fosse stato utilizzato, avrei dovuto effettuare tutte le operazioni andando ad utilizzare un “vero” disassemblatore quale IDA Pro Disassembler. Il risultato sarebbe stato lo stesso.. ma il tempo per effettuare tutta la serie di operazioni sarebbe lievitato.
Non solo; poche persone sanno leggere il codice assembler di una applicazione.. di certo molte ma molte meno di quelle che sanno leggere del codice .NET.