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:

Sample non-encrypted 1

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:

Sample non-encrypted 1-1

Se cerchiamo le stringhe puoi vedere che tutte le nostre informazioni sensibili sono visibili:

Sample non-encrypted 1-2

Una volta evidenziata la stringa, puoi aprire la vista del decompilatore e vedere tutto il codice rilevante:

Sample non-encrypted 1-3

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:

Sample non-encrypted 2

È 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:

Step 1

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:

Step 2

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:

Step 3

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:

Step 4

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:

Step 5

Se apriamo il nuovo campione in IDA (o Ghidra) le stringhe crittografate non sono visibili:

Step 6

Ho menzionato che ci sono alcune stringhe intenzionalmente lasciate in chiaro in questo campione. Il motivo è che possiamo seguirle per vedere il codice:

Step 7

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:

Step 8

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 😘

Become a Patron