Skip to content
KitploitKITPLOIT
StrumentiBlog
Invia
StrumentiBlog
Invia

Strumenti di Hacking, PenTest e Cybersecurity per il tuo Arsenale di Sicurezza!

Kitploit è una directory di strumenti di hacking, cybersecurity e pentesting. Scopri gli ultimi aggiornamenti dei progetti per trovare vulnerabilità, analizzare sistemi, automatizzare i test e rafforzare la tua sicurezza.

··Feed·Contatto·Privacy·© 2026 Kitploit

Directory degli strumenti

Categorie

Vedi tutte le categorie
Loading categories
Strumenti/GitHubGitHub/calebfenton/simplify
Sicurezza AndroidAnalisi Dinamica (Sandboxing)Reverse EngineeringAnalisi MalwareAnalisi di Binari
GitHubcalebfenton/simplify

simplify

Macchina virtuale Android e deoffuscatore

Vedi Repository
4.7k45515 anni faRevisionato da Kitploit

Più Popolari

Vedi tutti →

Scopri gli strumenti più utilizzati dalla nostra community.

Esplora tutti gli strumenti

Sfoglia la nostra collezione di strumenti

Vedi tutti gli strumenti →
Condividi

Simplify

Build Status Coverage Status Coverity Scan Build Status

Deoffuscatore Android Generico

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.

Prima e Dopo

Il codice a sinistra è una decompilazione di un'app offuscata, e il codice a destra è stato deoffuscato.

Molte chiamate a metodi, nessun significato chiaro Wow, così letterale, molto significato

Panoramica

Ci sono tre parti nel progetto: smalivm, simplify e l'app demo.

  1. smalivm: Fornisce una sandbox di macchina virtuale per eseguire metodi Dalvik. Dopo aver eseguito un metodo, restituisce un grafo contenente tutti i possibili valori di registro e classe per ogni percorso di esecuzione. Funziona anche se alcuni valori sono sconosciuti, come I/O di file e rete. Ad esempio, qualsiasi condizionale if o switch con un valore sconosciuto porta a prendere entrambi i rami.
  2. simplify: Analizza i grafi di esecuzione da smalivm e applica ottimizzazioni come propagazione delle costanti, rimozione del codice morto, de-riflessione e alcune ottimizzazioni peephole. Queste sono abbastanza semplici, ma se applicate insieme ripetutamente, decifrano stringhe, rimuovono la riflessione e semplificano notevolmente il codice. Non rinomina metodi e classi.
  3. demoapp: Contiene esempi semplici e ampiamente commentati per l'uso di smalivm nel proprio progetto. Se stai costruendo qualcosa che deve eseguire codice Dalvik, dai un'occhiata.

Utilizzo

root@kitploit:~
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

Costruzione

La costruzione richiede l'installazione del Java Development Kit 8 (JDK).

Poiché questo progetto contiene sottomoduli per i framework Android, clona con --recursive:

root@kitploit:~
git clone --recursive https://github.com/CalebFenton/simplify.git

Oppure aggiorna i sottomoduli in qualsiasi momento con:

root@kitploit:~
git submodule update --init --recursive

Quindi, per costruire un unico jar che contiene tutte le dipendenze:

root@kitploit:~
./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):

root@kitploit:~
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.

Risoluzione dei Problemi

Se Simplify fallisce, prova questi suggerimenti, in ordine:

  1. Punta solo a pochi metodi o classi usando l'opzione -it.
  2. Se il fallimento è dovuto al superamento del numero massimo di visite, prova con valori più alti di --max-address-visits, --max-call-depth e --max-method-visits.
  3. Prova con -v o -v 2 e segnala il problema con i log e un hash del DEX o APK.
  4. Riprova, ma non distogliere lo sguardo. Simplify percepisce la paura.

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.

Contribuire

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.

Segnalare Problemi

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).

Strategie di Ottimizzazione

Propagazione delle Costanti

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:

root@kitploit:~
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:

root@kitploit:~
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."

Rimozione del Codice Morto

Il codice è morto se la sua rimozione non può alterare in alcun modo il comportamento dell'app. Il caso più ovvio è se il codice è irraggiungibile, ad es. if (false) { // morto }). Se il codice è raggiungibile, può essere considerato morto se non influisce su alcuno stato al di fuori del metodo, cioè non ha effetto collaterale. Ad esempio, il codice potrebbe non influenzare il valore di ritorno del metodo, alterare variabili di classe o eseguire I/O. Questo è difficile da determinare nell'analisi statica. Fortunatamente, smalivm non deve essere intelligente. Semplicemente esegue stupidamente tutto ciò che può e assume che ci siano effetti collaterali se non può esserne sicuro. Considera l'esempio dalla Propagazione delle Costanti:

root@kitploit:~
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."

In questo codice, invoke-static non influisce più sul valore di ritorno del metodo e supponiamo che non faccia cose strane come scrivere byte nel filesystem o su un socket di rete, quindi non ha effetti collaterali. Può essere semplicemente rimosso.

root@kitploit:~
const-string v0, "VGVsbCBtZSBvZiB5b3VyIGhvbWV3b3JsZCwgVXN1bC4="
const-string v0, "Tell me of your homeworld, Usul."

Infine, il primo const-string assegna un valore a un registro, ma quel valore non viene mai utilizzato, cioè l'assegnazione è morta. Può anche essere rimosso.

root@kitploit:~
const-string v0, "Tell me of your homeworld, Usul."

Evviva!

De-riflessione

Una delle principali sfide nell'analisi statica di Java è la riflessione. Semplicemente non è possibile conoscere quali siano gli argomenti per i metodi di riflessione senza fare un'attenta analisi del flusso di dati. Ci sono modi intelligenti e furbi per farlo, ma smalivm lo fa semplicemente eseguendo il codice. Quando trova un'invocazione di metodo riflesso come:

root@kitploit:~
invoke-virtual {v0, v1, v2}, Ljava/lang/reflect/Method;->invoke(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;

Può conoscere i valori di v0, v1 e v2. Se è sicuro di quali siano i valori, può sostituire la chiamata a Method.invoke() con una reale invocazione di metodo non riflessa. Lo stesso vale per le ricerche riflesse di campi e classi.

Peephole

Per tutto ciò che non si adatta perfettamente a una particolare categoria, ci sono le ottimizzazioni peephole. Ciò include la rimozione di op check-cast inutili, la sostituzione di chiamate Ljava/lang/String;-><init> con const-string, e così via.

Esempio di Deoffuscamento

Prima dell'Ottimizzazione

root@kitploit:~
.method public static test1()I
    .locals 2

    new-instance v0, Ljava/lang/Integer;
    const/4 v1, 0x1
    invoke-direct {v0, v1}, Ljava/lang/Integer;-><init>(I)V

    invoke-virtual {v0}, Ljava/lang/Integer;->intValue()I
    move-result v0

    return v0
.end method

Tutto ciò fa è v0 = 1.

Dopo la Propagazione delle Costanti

root@kitploit:~
.method public static test1()I
    .locals 2

    new-instance v0, Ljava/lang/Integer;
    const/4 v1, 0x1
    invoke-direct {v0, v1}, Ljava/lang/Integer;-><init>(I)V

    invoke-virtual {v0}, Ljava/lang/Integer;->intValue()I
    const/4 v0, 0x1

    return v0
.end method

move-result v0 viene sostituito con const/4 v0, 0x1. Questo perché c'è un solo possibile valore di ritorno per intValue()I e il tipo di ritorno può essere reso una costante. Gli argomenti v0 e v1 sono non ambigui e non cambiano. Cioè, c'è un consenso di valori per ogni possibile percorso di esecuzione in intValue()I. Altri tipi di valori che possono essere trasformati in costanti:

  • numeri - const/4, const/16, ecc.
  • stringhe - const-string
  • classi - const-class

Dopo la Rimozione del Codice Morto

root@kitploit:~
.method public static test1()I
    .locals 2

    const/4 v0, 0x1

    return v0
.end method

Poiché il codice sopra const/4 v0, 0x1 non influisce sullo stato al di fuori del metodo (nessun effetto collaterale), può essere rimosso senza cambiare comportamento. Se ci fosse stata una chiamata a un metodo che scriveva qualcosa sul filesystem o sulla rete, non potrebbe essere rimossa perché influisce sullo stato al di fuori del metodo. O se test()I avesse preso un argomento mutabile, come un LinkedList, qualsiasi istruzione che lo avesse toccato non potrebbe essere considerata morta.

Altri esempi di codice morto:

  • assegnazioni non referenziate - assegnare registri e non usarli
  • istruzioni non raggiunte / non raggiungibili - if (false) { dead_code(); }

Licenza

Questo strumento è disponibile sotto una doppia licenza: una commerciale adatta a progetti closed source e una licenza GPL utilizzabile in software open source.

A seconda delle tue esigenze, devi sceglierne una e seguirne le politiche. Un dettaglio delle politiche e degli accordi per ciascun tipo di licenza è disponibile nei file LICENSE.COMMERCIAL e LICENSE.GPL.

Letture Consigliate

  • Dalvik Virtual Execution with SmaliVM
  • Guillot, Yoann, and Alexandre Gazet. "Automatic Binary Deobfuscation." Journal in Computer Virology 6.3 (2010): 261-76
  • Unicorn - The ultimate CPU emulator
  • Babak Yadegari, Saumya Debray. "Symbolic Execution of Obfuscated Code"
  • Storie di successo:
    • Android Dynamic Class Loading with "AES/CFB/NoPadding" encryption. Take a peek before & after. Tool used: #simplify. #Android #obfuscation #classencryption #dex
    • Decrypting Malware String Encryption
Scarica lo strumento