Che cos’è l’offuscamento?
Il Ottobre 25, 2021 da adminChe cos’è l’offuscamento del codice?
L’offuscamento del codice è il processo di modifica di un eseguibile in modo che non sia più utile a un hacker ma rimanga completamente funzionale. Mentre il processo può modificare le istruzioni effettive del metodo o i metadati, non altera l’output del programma. Per essere chiari, con abbastanza tempo e sforzo, quasi tutto il codice può essere sottoposto a reverse engineering. Tuttavia, su alcune piattaforme come Java, Android, iOS, o .NET (ad esempio Xamarin, C#, VB.NET, F#) i decompilatori gratuiti possono facilmente eseguire il reverse engineering del codice sorgente da un eseguibile o una libreria praticamente in pochissimo tempo e senza sforzo. L’offuscamento automatico del codice rende il reverse engineering di un programma difficile ed economicamente non fattibile.
Perché usare un offuscatore di codice?
Rendendo un’applicazione molto più difficile da reingegnerizzare, è possibile proteggersi dal furto di segreti commerciali (proprietà intellettuale), dall’accesso non autorizzato, dall’aggiramento di licenze o altri controlli e dalla scoperta di vulnerabilità.
Come funziona l’offuscamento?
L’offuscamento del codice consiste di molte tecniche diverse che possono completarsi a vicenda per creare una difesa a strati. È più efficace per i linguaggi che creano qualche forma di istruzioni di livello intermedio come Java o i linguaggi .NET come C#, VB.NET, Managed C++, F#, ecc. Alcuni esempi tipici di offuscamento e tecniche di sicurezza delle applicazioni includono:
Rename Obfuscation
Renaming altera il nome di metodi e variabili. Rende il sorgente decompilato più difficile da capire per un umano, ma non altera l’esecuzione del programma. I nuovi nomi possono utilizzare schemi diversi come “a”, “b”, “c”, o numeri, caratteri non stampabili o invisibili. E i nomi possono essere sovraccaricati, purché abbiano uno scopo diverso. L’offuscamento dei nomi è una trasformazione di base utilizzata dalla maggior parte degli offuscatori .NET (C#, ecc.), iOS, Java e Android.
Crittografia delle stringhe
In un eseguibile gestito, tutte le stringhe sono chiaramente scopribili e leggibili. Anche quando i metodi e le variabili sono rinominati, le stringhe possono essere utilizzate per individuare sezioni di codice critiche cercando riferimenti alle stringhe all’interno del binario. Questo include i messaggi (specialmente quelli di errore) che vengono visualizzati all’utente. Per fornire una barriera efficace contro questo tipo di attacco, la crittografia delle stringhe nasconde le stringhe nell’eseguibile e ripristina il loro valore originale solo quando necessario. Decifrare le stringhe in fase di esecuzione comporta tipicamente una leggera penalizzazione delle prestazioni in fase di esecuzione.
Control Flow Obfuscation
L’offuscamento del flusso di controllo sintetizza costrutti condizionali, ramificati e iterativi che producono una logica eseguibile valida, ma danno risultati semantici non deterministici quando decompilati. Più semplicemente, rende il codice decompilato simile alla logica degli spaghetti che è molto difficile da comprendere per un hacker. Queste tecniche possono influenzare le prestazioni di runtime di un metodo.
Instruction Pattern Transformation
Converte istruzioni comuni create dal compilatore in altri costrutti meno ovvi. Queste sono istruzioni del linguaggio macchina perfettamente legali che potrebbero non mappare in modo pulito in linguaggi di alto livello come Java o C#. Un esempio è il caching delle variabili transitorie che sfrutta la natura basata sullo stack dei runtime Java e .NET.
Inserimento di codice fittizio
Inserimento di codice nell’eseguibile che non influenza la logica del programma, ma rompe i decompilatori o rende molto più difficile analizzare il codice inverso.
Rimozione di codice e metadati inutilizzati
Rimozione di informazioni di debug, metadati non essenziali e codice usato dalle applicazioni per renderle più piccole e ridurre le informazioni disponibili per un attaccante. Questa procedura può migliorare leggermente le prestazioni di runtime.
Binary Linking/Merging
Questa trasformazione combina più eseguibili/librerie di input in uno o più binari di output. Il linking può essere usato per rendere la tua applicazione più piccola, specialmente se usato con la rinominazione e il pruning, può semplificare gli scenari di distribuzione e può ridurre le informazioni disponibili agli hacker.
Opaque Predicate Insertion
Offusca aggiungendo rami condizionali che valutano sempre a risultati noti, risultati che non possono essere facilmente determinati tramite analisi statica. Questo è un modo per introdurre codice potenzialmente scorretto che non verrà mai eseguito, ma confonde gli attaccanti che cercano di capire l’output decompilato.
Anti-Tamper
Un offuscatore può iniettare l’autoprotezione dell’applicazione nel codice per verificare che l’applicazione non sia stata manomessa in alcun modo. Se viene rilevata una manomissione, può arrestare l’applicazione, limitare le funzionalità, invocare crash casuali (per mascherare il motivo del crash), o eseguire qualsiasi altra azione personalizzata. Potrebbe anche inviare un messaggio a un servizio per fornire dettagli sulla manomissione rilevata.
Anti-Debug
Quando un hacker sta cercando di piratare o contraffare la vostra applicazione, rubare i vostri dati, o alterare il comportamento di un pezzo critico del software dell’infrastruttura, quasi certamente inizierà con il reverse engineering e l’analisi della vostra applicazione con un debugger. Un offuscatore può stratificare l’autoprotezione dell’applicazione iniettando codice per rilevare se la vostra applicazione di produzione viene eseguita all’interno di un debugger. Se un debugger viene utilizzato, può corrompere i dati sensibili (proteggendoli dal furto), invocare crash casuali (per nascondere che il crash è il risultato di un controllo di debug), o eseguire qualsiasi altra azione personalizzata. Potrebbe anche inviare un messaggio a un servizio per fornire un segnale di avvertimento.
Dovrei offuscare la mia applicazione?
Considerate fortemente di utilizzare l’offuscamento e l’autoprotezione runtime dell’applicazione se rilasciate software che gira in un ambiente non fidato e ha proprietà intellettuale, fornisce accesso a informazioni sensibili, o ha funzionalità gated. L’offuscamento rende molto più difficile per gli attaccanti rivedere il codice e analizzare l’applicazione. Rende anche difficile per gli hacker il debug e la manomissione dell’applicazione. L’obiettivo finale è quello di aggiungere uno strato di protezione per rendere difficile estrarre o scoprire informazioni utili, come segreti commerciali (IP), credenziali o vulnerabilità di sicurezza da un’applicazione. Dovrebbe anche rendere più difficile modificare la logica dell’applicazione o riconfezionare un’applicazione con codice dannoso.
Lascia un commento