Le nostre competenze a vostra disposizione sul blog
Amiamo il nostro lavoro e vogliamo condividerlo con voi! Tenetevi aggiornati su tutte le news e le tecnologie con le quali lavoriamo e di cui potreste avere bisogno! Seguite il nostro blog.
×

Error message

The spam filter installed on this site is currently unavailable. Per site policy, we are unable to accept new submissions until that problem is resolved. Please try resubmitting the form in a couple of minutes.
andrea.piolanti's picture

Se si sta sviluppando un'applicazione Java, è importante sapere che i file .class di Java possono essere facilmente decodificati e decompilati nel codice sorgente originale utilizzando java decompilers come JD GUI o JAD. La soluzione migliore per evitare il reverse engineering è quella di offuscare il codice compilato attraverso opportuni tool. Con offuscamento, in generale, si descrive una pratica che viene utilizzata per rendere intenzionalmente difficile la comprensione di qualcosa. In un contesto di programmazione, significa rendere il codice più difficile da capire o leggere e si adotta per questioni di privacy o motivi di sicurezza. Uno strumento software chiamato offuscatore permette di convertire un applicativo java in uno che funziona allo stesso modo, ma che, quando decompilato, risulta di difficile interpretazione. Un tool di offuscamento, detto obfuscator, in generale si articola in tre fasi diverse:

  • Shrinking
  • Ottimizzazione
  • Offuscamento

La fase di Shrinking determina in modo ricorsivo quali classi e membri della classe sono usati. Tutte le classi ed i membri della classe non utilizzati vengono scartati. Se l'applicazione viene distribuita con una libreria di terze parti, allora il numero di classi, campi e metodi che non vengono effettivamente utilizzati potrebbe essere molto significativo.
La fase di ottimizzazione, ottimizza il codice ed in particolare: accorpa più classi, rimuove gli attributi irrilevanti per l'esecuzione, ordina le variabili locali, raggruppa i metodi in un unica linea di codice, rimuove le costanti inutilizzate, ottimizza i costrutti if, for, switch e in generale rende il codice più compatto e meno user friendly.
Lo step di offuscamento rinomina le classi che non sono “entry point”, gli attributi e i metodi, con nomi senza senso. In generale, un “entry point” è una classe che, se offuscata, impedirà alla libreria o all'applicazione di funzionare correttamente.
Ogni progetto java possiede almeno un “entry point”: per esempio, la classe che contiene il main di un'applicazione Java o ogni classe che contiene API pubbliche per una libreria Java.

Sul web è possibile trovare una grossa quantità di offuscatori, tra questi uno strumento estremamente valido e open source è Proguard (http://proguard.sourceforge.net/ #) che viene sviluppato e mantenuto da Eric Lafortune e dispone di una documentazione completa e un forum attivo e utile.

PostGuard necessita di due diversi input:

  • jars di ingresso specificati con l'opzione -injars, questi sono i jar (war) che vengono elaborati e offuscati da Proguard. Al termine dell’elaborazione Proguard produrrà uno o più jar di uscita (o wars) a seconda della configurazione data.
  • Library jars (o wars) specificati con l'opzione -libaryjars, queste sono essenzialmente le librerie utilizzate dal jars di ingresso. Non verranno offuscate ma sono necessarie al fine di ricostruire l’albero delle dipendenze e così eseguire correttamente le fasi di shrink e ottimizzazione.

proguard-1.png

In aggiunta a questi input è possibile specificare un elenco di opzioni che permettono di configurare lo strumento proguard e così il jars di uscita. Tutte queste opzioni possono essere specificate in un file di configurazione che Proguard avrà come input.
In seguito vi è una breve descrizione delle principali opzioni che vale la pena prendere in considerazione e conoscere poichè valide per ogni offuscatore. Per maggiorni dettagli si può fare riferimento al manuale di Proguard (http://proguard.sourceforge.net/index.html#manual/introduction.html)

Come descritto precedentemente ogni progetto java ha uno o più “entry points” che devono essere preservati dall’offuscamento. Proguard permette di specificare gli “entry points” che si vogliono escludere dall’offuscamento, con l'opzione-keep.
Per esempio l’opzione:

-keep public class *{
    public static void main(java.lang.String[]);
}

permette di conservare tutte le classi che contengono il main.
Ci sono anche altre classi o parti di software che devono essere preservati, per esempio:

  • ogni dichiarazione di codice nativo se si usa JNI
    -keepclasseswithmembernames class * {
    native ;
    }
  • annotazioni, questo è necessario se l’app per esempio usa jsonSerialization o JAXB
    -keepattributes * Annotazioni *
  • per produrre stacktrace utili o log è importante per mantenere invariati i numero delle righe (a causa della fase di ottimizzazione le classi del jar offuscato hanno infatti una struttura diversa da quelle originali)
    -keepattributes LineNumberTable
    Se l'applicazione utilizza la reflection è necessario preservare tutte le entità a cui si accede con la reflection
    -keep classi pubbliche className o un pacchetto
  • generalmente, ogni classe che è creata o invocata dinamicamente attraverso i costrutti Class.forName(), SomeClass.class, … Infatti in fase di esecuzione il costrutto Class.forName() può riferirsi ad ogni classe.

Infine, una nota importante sull’offuscamento di una library Java. Se si deve distribuire una library stand alone è necessario preservare tutti i punti di accesso della library (public API) altrimenti la library risulterà essere inutilizzabile. Tuttavia, se la library è utilizzata anche da un’altra applicazione e si vuole distribuire l’applicazione assieme alla library, potrebbe essere opportuno offuscare completamente la library cosicchè nessuno, ad esclusione dell’applicazione distribuita, potrà utilizzarla.
A tal fine si può sfruttare l’incremental obfuscation e offuscare così sia la library che l’applicazione nello stesso processo di compilazione. Ad esempio, se l’applicazione Java A (a.jar) usa una Library B (B.jar) si può configurare Proguard come segue:

  • injars ‘B.jar’
  • outjars B_obfuscated.jar
  • injars ‘A.jar’
  • outjars A_obfuscated.jar

In questo modo Proguard computa le dipendeze tra i vari jar di Input e utilizza l’output del primo JAR come input nell’offuscamento del secondo JAR. Così facendo la library B sarà totalmente offuscata.

Concludendo, Proguard è uno strumento utile a compattare, ottimizzare e offuscare il codice Java. Nonostante la configurazione non sia tra le più semplici, permette di ottenere un JAR di output in grado di soddisfare ogni requisito. Come ogni offuscatore, il jar di output può essere decompilato ma per interpretarlo sarà necessario perdere molto tempo, pazienza e probabilmente ti farà impazzire.

Aggiungi un commento

Filtered HTML

  • Web page addresses and e-mail addresses turn into links automatically.
  • Allowed HTML tags: <a> <em> <strong> <cite> <blockquote> <code> <ul> <ol> <li> <dl> <dt> <dd>
  • Lines and paragraphs break automatically.

Plain text

  • No HTML tags allowed.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.