Android

Android Obfuscation

Ultimamente mi sono imbattuto spesso nella problematica dell’offuscamento delle applicazioni Android per cercare di impedire, o comunque rendere più complicate le operazioni di reverse engineering.

Un buon offuscamento sicuramente limita l’utilizzo di tool come Frida, perché risulterà molto più difficile leggere e capire lo pseudo codice dell’applicazione.

Quando segnalo un offuscamento del codice insufficiente qualche volta devo consigliare un sistema per raggiungere l’obiettivo, perché lo sviluppatore spesso non ha mai affrontato il problema e si trova in difficoltà ad implementare una soluzione efficace.

In questo articolo cercherò di dare alcune indicazioni per poter offuscare un’applicazione Android in maniera del tutto free.

Il primo tool da usare è ProGuard, già integrato in Android studio. Questo strumento permette di comprimere e ottimizzare il codice Java rimuovendo anche le funzioni non utilizzate. E’ importante tenere a mente che ProGuard si attiva solamente nella versione di release dell’app, le regole di ProGuard non vengono applicate alla versione debug.

Di seguito le regole da applicare all’interno del file proguard-rules.pro:

# Uncomment this to preserve the line number information for
# debugging stack traces.
-keepattributes SourceFile,LineNumberTable

# If you keep the line number information, uncomment this to
# hide the original source file name.
-renamesourcefileattribute SourceFile

# Numero di cicli di ottimizzazione effettuati da ProGuard
-optimizationpasses 5
-dontpreverify
# Rappresenta quello che sarà il nome del pacchetto dell'app e tutte le classi rinominate saranno spostate al suo interno
-repackageclasses 'it.appoffuscata.app'
-allowaccessmodification
-optimizations !code/simplification/arithmetic
-keepattributes *Annotation*

-verbose

# Crea un resoconto di quando modificato da ProGuard. 
# E' necessario creare la directory obfuscation all'interno della root dell'app. 
# Non è obbligatorio inserire questa configrazione.
-dump obfuscation/class_files.txt
-printseeds obfuscation/seeds.txt
-printusage obfuscation/unused.txt
-printmapping obfuscation/mapping.txt

# Specificando le regole seguenti è possibile indicare una wordlist da cui prelevare i nomi da assegnare alle classi e i metodi del codice. 
# Se non specificato, ProGuard rinomina le classi con le lettere dell'alfabeto.
#-obfuscationdictionary obfuscation/keywords.txt
#-classobfuscationdictionary obfuscation/keywords.txt
#-packageobfuscationdictionary obfuscation/keywords.txt

Mentre il file build.gradle a livello di app dovrà essere modificato così:

    buildTypes {
        release {
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }

Quella che segue è una vista dell’app che non utilizza ProGuard. L’app è molto semplice e ha solo una MainActivity:

Lo pseudo codice all’interno di MainActivity è chiaramente leggibile:

L’app con le regole impostate da ProGuard invece sarà molto diversa:

E’ chiaramente visibile che il codice è stato minificato, è stato eliminato il metodo inutilizzato executeCommand e nel caso in cui ci fossero stati altri metodi o altre classi sarebbero stati rinominati con le lettere dell’alfabeto. Chiaramente la MainActivity è l’entry point dell’app e non è stata rinominata.

Quello che manca per ottenere un offuscamento completo è l’offuscamento delle stringhe. Leggendo questo codice infatti è comunque chiaro che si tratta di una funzione che controlla se l’applicazione è in esecuzione su un emulatore. Offuscando anche le stringhe però sarà molto più difficile capire di cosa si trattata. A tal proposito segnalo questo plugin di gradle, free, che funziona molto bene ed è in grado di offuscare tutte le stringhe presenti nel codice dell’app. Basterà decorare le classi con il decoratore @Obfuscate.

https://github.com/MichaelRocks/paranoid

Per utilizzare il plugin occorre inserire nel file build.gradle a livello root del progetto quanto la dipendenza a paranoid:

buildscript {
    repositories {
        google()
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:4.1.1'
        classpath 'io.michaelrocks:paranoid-gradle-plugin:0.3.2' <====
        classpath 'com.google.gms:google-services:4.3.4'
    }
}

E all’interno del file build.gradle dell’app:

apply plugin: 'io.michaelrocks.paranoid'

E questo è il risultato:

Buon offuscamento!