
Macchina virtuale Android e deoffuscatore
Simplify esegue virtualmente un'app per comprenderne il comportamento e poi cerca di ottimizzare il codice in modo che si comporti identicamente ma sia più facile da comprendere per un umano. Ogni tipo di ottimizzazione è semplice e generico, quindi non importa quale specifico tipo di offuscamento sia stato utilizzato.
Il codice a sinistra è una decompilazione di un'app offuscata, e il codice a destra è stato deoffuscato.
Ci sono tre parti nel progetto: smalivm, simplify e l'app demo.
if o switch con un valore sconosciuto porta a prendere entrambi i rami.usage: java -jar simplify.jar <input> [options]
deobfuscates a dalvik executable
-et,--exclude-types <pattern> Esclude classi e metodi che includono REGEX, ad es: "com/android", applicato dopo include-types
-h,--help Mostra questo messaggio
-ie,--ignore-errors Ignora errori durante l'esecuzione e l'ottimizzazione dei metodi. Ciò potrebbe portare a comportamenti imprevisti.
--include-support Tenta di eseguire e ottimizzare le classi nei pacchetti della libreria di supporto Android, default: false
-it,--include-types <pattern> Limita l'esecuzione a classi e metodi che includono REGEX, ad es: ";->targetMethod\("
--max-address-visits <N> Abbandona l'esecuzione di un metodo dopo aver visitato lo stesso indirizzo N volte, limita i cicli, default: 10000
--max-call-depth <N> Non chiamare metodi dopo aver raggiunto una profondità di chiamata di N, limita ricorsione e lunghe catene di metodi, default: 50
--max-execution-time <N> Abbandona l'esecuzione di un metodo dopo N secondi, default: 300
--max-method-visits <N> Abbandona l'esecuzione di un metodo dopo aver eseguito N istruzioni in quel metodo, default: 1000000
--max-passes <N> Non eseguire ottimizzatori su un metodo più di N volte, default: 100
-o,--output <file> Output semplificato su FILE
--output-api-level <LEVEL> Imposta la compatibilità API DEX di output al LIVELLO, default: 15
-q,--quiet Stai zitto
--remove-weak Rimuovi codice anche se ci sono effetti collaterali deboli, default: true
-v,--verbose <LEVEL> Imposta la verbosità al LIVELLO, default: 0
La costruzione richiede l'installazione del Java Development Kit 8 (JDK).
Poiché questo progetto contiene sottomoduli per i framework Android, clona con --recursive:
git clone --recursive https://github.com/CalebFenton/simplify.git
Oppure aggiorna i sottomoduli in qualsiasi momento con:
git submodule update --init --recursive
Quindi, per costruire un unico jar che contiene tutte le dipendenze:
./gradlew fatjar
Il jar di Simplify sarà in simplify/build/libs/. Puoi testare che funzioni semplificando l'app di esempio offuscata fornita. Ecco come eseguirla (potresti dover cambiare simplify.jar):
java -jar simplify/build/libs/simplify.jar -it "org/cf/obfuscated" -et "MainActivity" simplify/obfuscated-app.apk
Per capire cosa viene deoffuscato, consulta README di Obfuscated App.
Se Simplify fallisce, prova questi suggerimenti, in ordine:
-it.--max-address-visits, --max-call-depth e --max-method-visits.-v o -v 2 e segnala il problema con i log e un hash del DEX o APK.Se stai costruendo su Windows e la costruzione fallisce con un errore simile a:
Could not find tools.jar. Please check that C:\Program Files\Java\jre1.8.0_151 contains a valid JDK installation.
Ciò significa che Gradle non riesce a trovare un percorso JDK corretto. Assicurati che JDK sia installato, imposta la variabile d'ambiente JAVA_HOME al percorso del tuo JDK e assicurati di chiudere e riaprire il prompt dei comandi che usi per costruire.
Non essere timido. Penso che l'esecuzione virtuale e il deoffuscamento siano problemi affascinanti. Chiunque sia interessato è automaticamente figo e i contributi sono benvenuti, anche solo per correggere un errore di battitura. Sentiti libero di fare domande negli issue e inviare pull request.
Includi un link all'APK o DEX e il comando completo che stai usando. Questo rende molto più facile riprodurre (e quindi risolvere) il tuo problema.
Se non puoi condividere il campione, per favore includi l'hash del file (SHA1, SHA256, ecc).
Se un op piazza un valore di un tipo che può essere trasformato in una costante come una stringa, numero o booleano, questa ottimizzazione sostituirà quell'op con la costante. Ad esempio:
const-string v0, "VGVsbCBtZSBvZiB5b3VyIGhvbWV3b3JsZCwgVXN1bC4="
invoke-static {v0}, Lmy/string/Decryptor;->decrypt(Ljava/lang/String;)Ljava/lang/String;
# Decifra in: "Tell me of your homeworld, Usul."
move-result v0
In questo esempio, una stringa crittografata viene decifrata e inserita in v0. Poiché le stringhe sono "costantizzabili", move-result v0 può essere sostituito con un const-string:
const-string v0, "VGVsbCBtZSBvZiB5b3VyIGhvbWV3b3JsZCwgVXN1bC4="
invoke-static {v0}, Lmy/string/Decryptor;->decrypt(Ljava/lang/String;)Ljava/lang/String;
const-string v0, "Tell me of your homeworld, Usul."