Stringhe crittografate a runtime
Oggi esamineremo le basi delle stringhe crittografate a runtime, perché dobbiamo crittografare le nostre stringhe e impareremo a creare le nostre.
In questo articolo comprenderai e imparerai:
- Cos’è la crittografia e decrittografia a runtime
- Perché devi crittografare le tue stringhe
- Vedere come chiunque può visualizzare i tuoi dati sensibili
- Creare la tua crittografia personalizzata
Cos’è la crittografia e decrittografia a runtime
Si riferisce ai dati crittografati e/o decrittografati durante l’esecuzione di un programma (software, applicazione). I dati possono essere di qualsiasi tipo: blocchi di memoria, traffico di rete, stringhe, ecc.
Uno dei metodi più comuni utilizzati per questo scopo è l’offuscamento (base). Gli altri meccanismi (avanzati) coinvolgono la mutazione/virtualizzazione del codice compilato.
Oggi ci concentreremo su un meccanismo che utilizza l’offuscamento XOR .
Perché crittografare le stringhe?
Nel momento in cui esegui il tuo software, tutto è visibile in memoria. Questo vale anche per i tuoi utenti finali, il che significa che possono vedere tutto.
Una delle prime cose che un attaccante farà è cercare stringhe all’interno del tuo software. Questo gli permetterà di comprendere tutto del tuo software con il minimo sforzo.
Se stai memorizzando dati sensibili (come password o licenze), è fondamentale non conservarli in testo semplice. Conservarli in testo semplice faciliterà la vita di un attaccante.
Esistono diversi modi per analizzare il tuo software. I metodi più noti e comuni sono l’analisi statica e l’analisi a runtime.
Diamo un’occhiata a un semplice esempio usando un’app console:
Compiliamo in modalità Release (per evitare informazioni di debug). Procediamo e testiamo l’analisi statica e a runtime.
Test di analisi statica
Nell’analisi statica il software non ha bisogno di essere eseguito. Detto questo, apriamo il campione in Ghidra .
Dallo screenshot qui sotto puoi vedere che il campione è compilato senza informazioni di debug:
Se cerchiamo le stringhe puoi vedere che tutte le nostre informazioni sensibili sono visibili:
Una volta evidenziata la stringa, puoi aprire la vista del decompilatore e vedere tutto il codice rilevante:
Piuttosto triste, vero? 😕 Immagina di aver lavorato al tuo fantastico software per mesi e di essere pronto a venderlo.
Penso che il resto sia autoesplicativo, ma sono sicuro che hai capito il punto.
Ciò che è ancora più triste è che questo è così semplice che anche un dodicenne può farlo. (e alcuni in effetti lo fanno)
Test di analisi a runtime
Nell’analisi a runtime il software deve essere in esecuzione. Questo significa che dobbiamo usare un software per aprire il processo e leggerlo (normalmente un debugger).
Tuttavia, un debugger non è realmente necessario per questo scopo. Possiamo semplicemente scaricare uno strumento gratuito come Process Hacker e aprire il processo:
È stato piuttosto semplice, vero? E tieni presente che non abbiamo nemmeno collegato un debugger. Un individuo abile e determinato userà un debugger.
Quando colleghi un debugger vedi molto di più, ma quella discussione è per un altro giorno.
Creare stringhe crittografate a runtime
Esistono numerosi modi per ottenere questo risultato:
- Utilizzare software di terze parti come VMProtect , Themida .
- Crittografia delle stringhe in fase di compilazione come xorstr .
- Utilizzare metodi personalizzati
Le prime 2 opzioni potrebbero non soddisfare le tue esigenze. Ci sono molti pro e contro per ognuna, che non discuteremo in questo momento.
Una cosa che devi capire è che la popolarità significa rischio. Quando usi cose trovate casualmente su Google, qualcuno ne è già a conoscenza.
La maggior parte delle persone ha sviluppato uno strumento contro il tuo strumento. È così che vanno le cose. Lo fanno per sfida, o per rubare il tuo lavoro, ma lo fanno.
Con questo in mente, devi andare sul personalizzato. Puoi creare la tua crittografia delle stringhe dal livello base a quello avanzato.
Il piano
- Creare una soluzione facile da usare
- Mantenere le stringhe sempre crittografate
- Decrittografia solo quando ne hai bisogno
- Posizionare le stringhe in posizione casuale (opzionale - non trattato)
- Distruggere le stringhe dopo l’uso (opzionale - non trattato)
La soluzione
Inizia definendo le nostre stringhe una per una come array:
L’array può contenere un numero illimitato di stringhe con un limite di lunghezza di 256.
So che questo è un compito impegnativo, specialmente se le tue stringhe sono lunghe. Questo è solo a scopo dimostrativo e più avanti creeremo una soluzione più pratica.
L’idea è crittografare ogni carattere della stringa. Userò una semplice crittografia XOR per questo.
Di seguito puoi vedere un esempio di come funzionerebbe:
Quanto sopra non ha nulla di complicato, è semplice e lineare ma piuttosto potente. Puoi usarlo all’interno di un’applicazione console.
Dopo la compilazione e l’esecuzione, il risultato sono byte illeggibili per l’occhio umano:
Ecco fatto, il tuo piccolo software per creare stringhe crittografate a runtime. 😏
Il risultato
È tempo di mettere in pratica la nostra soluzione. Creiamo un altro campione a questo scopo e aggiungiamo il nostro codice:
Nota 2 cose importanti:
- Ho lasciato alcune stringhe in testo semplice intenzionalmente per mostrare la differenza
- La funzione di decrittografia necessita della lunghezza (ne parleremo dopo)
Compiliamo quanto sopra in modalità Release e lo eseguiamo. Il nuovo campione funziona normalmente:
Se apriamo il nuovo campione in IDA (o Ghidra) le stringhe crittografate non sono visibili:
Ho menzionato che ci sono alcune stringhe intenzionalmente lasciate in chiaro in questo campione. Il motivo è che possiamo seguirle per vedere il codice:
Ho dovuto scorrere verso il basso per raggiungere il testo nell’immagine sopra. Puoi vedere quanto è diverso il codice compilato.
Abbiamo risolto il problema dell’analisi statica, passiamo al runtime.
Apriamolo in Process Hacker:
Voilà! Abbiamo risolto anche il problema dell’analisi a runtime 😎
Ulteriori informazioni sulle stringhe crittografate
L’esempio sopra non è molto pratico. Definire ogni stringa manualmente è un compito arduo, così come specificare la lunghezza della stringa ogni volta.
Idealmente avremmo bisogno di:
- Leggere un file di testo per le stringhe
- Scrivere le stringhe risultanti in un file di testo
- Aggiungere le sequenze di escape alle stringhe per evitare di specificare la lunghezza ogni volta.
- Aggiungere XOR più complesso o qualsiasi altro metodo (opzionale)
- Posizionare le stringhe in posizioni casuali (opzionale)
Ho preparato una bella soluzione con cui sperimentare. Puoi testare tutto ciò che è scritto in questo articolo e avere anche il tuo strumento pronto all’uso per creare stringhe crittografate a runtime.
Include 4 progetti:
- RuntimeStringEcryptor che legge le stringhe da un file di testo, le crittografa e poi le scrive in un altro file di testo.
- Sample è la semplice console usata per dimostrare con IDA.
- SampleEncryptedStrings è la semplice console con stringhe crittografate per dimostrare con IDA.
- SimpleRuntimeStringEncryption è il playground iniziale dove puoi testare questo metodo.
Note:
- Se non aggiungi una sequenza di escape, la decrittografia non saprà quando “fermarsi”. Il risultato saranno dati illeggibili/nulli fino a raggiungere la dimensione dell’array definita.
- Assicurati di cambiare le chiavi XOR che ho usato nel mio esempio.
- Evita di usare le stesse parole più volte. Genereranno gli stessi byte e c’è il rischio di essere rilevati.
Download
Per scaricare la soluzione pronta all’uso, considera di supportare questo blog 😘
Commenti