Skip to content
KitploitKITPLOIT
ToolsBlog
Einreichen
ToolsBlog
Einreichen

Hacking-, PenTest- und Cybersicherheits-Tools für Ihr Sicherheitsarsenal!

Kitploit ist ein Verzeichnis von Hacking-, Cybersicherheits- und Pentesting-Tools. Entdecken Sie die neuesten Projekt-Updates, um Schwachstellen zu finden, Systeme zu analysieren, Tests zu automatisieren und Ihre Sicherheit zu stärken.

··Feeds·Kontakt·Datenschutz·© 2026 Kitploit

Tool-Verzeichnis

Kategorien

Alle Kategorien anzeigen
Loading categories
simplify — Android-Virtual-Maschine und Deobfuskator | Kitploit
Tools/GitHubGitHub/calebfenton/simplify
Android-SicherheitDynamische Analyse (Sandboxing)Reverse EngineeringMalware-AnalyseBinäranalyse
GitHubcalebfenton/simplify

simplify

Android-Virtual-Maschine und Deobfuskator

Repository anzeigen
4.7k4551vor 5 JahrenVon Kitploit geprüft

Beliebteste

Alle anzeigen →

Entdecken Sie die meistgenutzten Tools unserer Community.

Alle Tools erkunden

Durchsuchen Sie unsere Tool-Sammlung

Alle Tools anzeigen →
Teilen

Simplify

Build Status Coverage Status Coverity Scan Build Status

Generischer Android-Entobfuskator

Simplify führt eine App virtuell aus, um ihr Verhalten zu verstehen, und versucht dann, den Code so zu optimieren, dass er sich identisch verhält, aber für einen Menschen leichter zu verstehen ist. Jeder Optimierungstyp ist einfach und generisch, sodass es keine Rolle spielt, welche spezifische Art der Verschleierung verwendet wird.

Vorher und Nachher

Der Code auf der linken Seite ist eine Dekompilierung einer verschleierten App, und der Code auf der rechten Seite wurde entobfuskiert.

Viele Methodenaufrufe, keine klare Bedeutung Wow, so literal, viel Bedeutung

Übersicht

Das Projekt besteht aus drei Teilen: smalivm, simplify und der Demo-App.

  1. smalivm: Stellt eine virtuelle Maschinen-Sandbox zur Ausführung von Dalvik-Methoden bereit. Nach der Ausführung einer Methode wird ein Graph mit allen möglichen Register- und Klassenwerten für jeden Ausführungspfad zurückgegeben. Es funktioniert auch, wenn einige Werte unbekannt sind, z. B. bei Datei- und Netzwerk-E/A. Beispielsweise werden bei einem if- oder switch-Bedingung mit unbekanntem Wert beide Zweige ausgeführt.
  2. simplify: Analysiert die Ausführungsgraphen von smalivm und wendet Optimierungen wie Konstantenpropagation, Entfernung von totem Code, Entspiegelung und einige Peephole-Optimierungen an. Diese sind recht einfach, aber wenn sie wiederholt gemeinsam angewendet werden, entschlüsseln sie Zeichenketten, entfernen Reflection und vereinfachen den Code erheblich. Es benennt Methoden und Klassen nicht um.
  3. demoapp: Enthält einfache, ausführlich kommentierte Beispiele zur Verwendung von smalivm in eigenen Projekten. Wenn Sie etwas bauen, das Dalvik-Code ausführen muss, sehen Sie es sich an.

Verwendung

root@kitploit:~
usage: java -jar simplify.jar <input> [options]
deobfuscates a dalvik executable
 -et,--exclude-types <pattern>   Exclude classes and methods which include REGEX, eg: "com/android", applied after include-types
 -h,--help                       Display this message
 -ie,--ignore-errors             Ignore errors while executing and optimizing methods. This may lead to unexpected behavior.
    --include-support            Attempt to execute and optimize classes in Android support library packages, default: false
 -it,--include-types <pattern>   Limit execution to classes and methods which include REGEX, eg: ";->targetMethod\("
    --max-address-visits <N>     Give up executing a method after visiting the same address N times, limits loops, default: 10000
    --max-call-depth <N>         Do not call methods after reaching a call depth of N, limits recursion and long method chains, default: 50
    --max-execution-time <N>     Give up executing a method after N seconds, default: 300
    --max-method-visits <N>      Give up executing a method after executing N instructions in that method, default: 1000000
    --max-passes <N>             Do not run optimizers on a method more than N times, default: 100
 -o,--output <file>              Output simplified input to FILE
    --output-api-level <LEVEL>   Set output DEX API compatibility to LEVEL, default: 15
 -q,--quiet                      Be quiet
    --remove-weak                Remove code even if there are weak side effects, default: true
 -v,--verbose <LEVEL>            Set verbosity to LEVEL, default: 0

Erstellung

Zum Erstellen muss das Java Development Kit 8 (JDK) installiert sein.

Da dieses Projekt Submodule für Android-Frameworks enthält, klonen Sie entweder mit --recursive:

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

Oder aktualisieren Sie die Submodule jederzeit mit:

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

Um dann ein einzelnes JAR zu erstellen, das alle Abhängigkeiten enthält:

root@kitploit:~
./gradlew fatjar

Das Simplify-JAR befindet sich in simplify/build/libs/. Sie können testen, ob es funktioniert, indem Sie die bereitgestellte verschleierte Beispiel-App vereinfachen. So führen Sie es aus (möglicherweise müssen Sie simplify.jar ändern):

root@kitploit:~
java -jar simplify/build/libs/simplify.jar -it "org/cf/obfuscated" -et "MainActivity" simplify/obfuscated-app.apk

Um zu verstehen, was entobfuskiert wird, sehen Sie sich das README der verschleierten App an.

Fehlerbehebung

Wenn Simplify fehlschlägt, versuchen Sie diese Empfehlungen in der Reihenfolge:

  1. Zielen Sie nur auf wenige Methoden oder Klassen mit der Option -it.
  2. Wenn der Fehler aufgrund überschrittener maximaler Besuche auftritt, versuchen Sie es mit höheren Werten für --max-address-visits, --max-call-depth und --max-method-visits.
  3. Versuchen Sie es mit -v oder -v 2 und melden Sie das Problem mit den Protokollen und einem Hash des DEX oder APK.
  4. Versuchen Sie es erneut, aber brechen Sie keinen Blickkontakt. Simplify spürt Angst.

Wenn unter Windows erstellt wird und der Build mit einem Fehler ähnlich dem folgenden fehlschlägt:

Could not find tools.jar. Please check that C:\Program Files\Java\jre1.8.0_151 contains a valid JDK installation.

Das bedeutet, dass Gradle keinen gültigen JDK-Pfad finden kann. Stellen Sie sicher, dass das JDK installiert ist, setzen Sie die Umgebungsvariable JAVA_HOME auf Ihren JDK-Pfad und schließen und öffnen Sie die Eingabeaufforderung, die Sie zum Erstellen verwenden, erneut.

Mitwirken

Seien Sie nicht schüchtern. Ich halte virtuelle Ausführung und Entobfuskation für faszinierende Probleme. Jeder, der interessiert ist, ist automatisch cool, und Beiträge sind willkommen, selbst wenn es nur darum geht, einen Tippfehler zu korrigieren. Stellen Sie gerne Fragen in den Issues und reichen Sie Pull Requests ein.

Probleme melden

Bitte fügen Sie einen Link zum APK oder DEX sowie den vollständigen Befehl hinzu, den Sie verwenden. Das erleichtert die Reproduktion (und damit die Behebung) Ihres Problems erheblich.

Wenn Sie das Beispiel nicht teilen können, fügen Sie bitte den Datei-Hash (SHA1, SHA256 usw.) hinzu.

Optimierungsstrategien

Konstantenpropagation

Wenn eine Operation einen Wert eines Typs platziert, der in eine Konstante umgewandelt werden kann, z. B. eine Zeichenkette, Zahl oder Boolean, ersetzt diese Optimierung diese Operation durch die Konstante. Beispiel:

root@kitploit:~
const-string v0, "VGVsbCBtZSBvZiB5b3VyIGhvbWV3b3JsZCwgVXN1bC4="
invoke-static {v0}, Lmy/string/Decryptor;->decrypt(Ljava/lang/String;)Ljava/lang/String;
# Decrypts to: "Tell me of your homeworld, Usul."
move-result v0

In diesem Beispiel wird eine verschlüsselte Zeichenkette entschlüsselt und in v0 platziert. Da Zeichenketten „konstantisierbar“ sind, kann move-result v0 durch ein const-string ersetzt werden:

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

Entfernung von totem Code

Code ist tot, wenn seine Entfernung das Verhalten der App unmöglich verändern kann. Der offensichtlichste Fall ist, wenn der Code unerreichbar ist, z. B. if (false) { // dead }. Wenn Code erreichbar ist, kann er als tot betrachtet werden, wenn er keinen Zustand außerhalb der Methode beeinflusst, d. h. er hat keinen Nebeneffekt. Beispielsweise beeinflusst Code möglicherweise den Rückgabewert der Methode nicht, ändert keine Klassenvariablen und führt keine E/A durch. Dies ist bei der statischen Analyse schwer zu bestimmen. Glücklicherweise muss smalivm nicht clever sein. Es führt einfach alles aus, was es kann, und nimmt Nebeneffekte an, wenn es sich nicht sicher ist. Betrachten Sie das Beispiel aus der Konstantenpropagation:

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 diesem Code beeinflusst invoke-static nicht mehr den Rückgabewert der Methode, und nehmen wir an, es macht nichts Seltsames wie das Schreiben von Bytes in das Dateisystem oder in einen Netzwerk-Socket, sodass es keine Nebeneffekte hat. Es kann einfach entfernt werden.

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

Schließlich weist das erste const-string einem Register einen Wert zu, aber dieser Wert wird nie verwendet, d. h. die Zuweisung ist tot. Es kann ebenfalls entfernt werden.

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

Hurra!

Entspiegelung

Eine große Herausforderung bei der statischen Analyse von Java ist Reflection. Es ist einfach nicht möglich, die Argumente für Reflection-Methoden zu kennen, ohne eine sorgfältige Datenflussanalyse durchzuführen. Es gibt intelligente, clevere Möglichkeiten, dies zu tun, aber smalivm tut es, indem es den Code einfach ausführt. Wenn es einen reflektierten Methodenaufruf wie diesen findet:

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

Kann es die Werte von v0, v1 und v2 kennen. Wenn es sicher ist, was die Werte sind, kann es den Aufruf von Method.invoke() durch einen tatsächlichen, nicht reflektierten Methodenaufruf ersetzen. Gleiches gilt für reflektierte Feld- und Klassenlookups.

Peephole-Optimierungen

Für alles, was nicht sauber in eine bestimmte Kategorie passt, gibt es Peephole-Optimierungen. Dazu gehört das Entfernen nutzloser check-cast-Operationen, das Ersetzen von Ljava/lang/String;-><init>-Aufrufen durch const-string usw.

Entobfuskationsbeispiel

Vor der Optimierung

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

Alles, was dies tut, ist v0 = 1.

Nach Konstantenpropagation

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 wird durch const/4 v0, 0x1 ersetzt. Dies liegt daran, dass es nur einen möglichen Rückgabewert für intValue()I gibt und der Rückgabetyp konstant gemacht werden kann. Die Argumente v0 und v1 sind eindeutig und ändern sich nicht. Das heißt, es gibt einen Konsens der Werte für jeden möglichen Ausführungspfad bei intValue()I. Andere Werttypen, die in Konstanten umgewandelt werden können:

  • Zahlen – const/4, const/16 usw.
  • Zeichenketten – const-string
  • Klassen – const-class

Nach Entfernung von totem Code

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

    const/4 v0, 0x1

    return v0
.end method

Da der Code oberhalb von const/4 v0, 0x1 den Zustand außerhalb der Methode nicht beeinflusst (keine Nebeneffekte), kann er entfernt werden, ohne das Verhalten zu ändern. Wenn es einen Methodenaufruf gäbe, der etwas in das Dateisystem oder Netzwerk schreibt, könnte er nicht entfernt werden, da er den Zustand außerhalb der Methode beeinflusst. Oder wenn test()I ein veränderliches Argument wie LinkedList nähme, könnten alle Anweisungen, die darauf zugreifen, nicht als tot betrachtet werden.

Weitere Beispiele für toten Code:

  • Nicht referenzierte Zuweisungen – Zuweisungen von Registern, die nicht verwendet werden
  • Nicht erreichte / nicht erreichbare Anweisungen – if (false) { dead_code(); }

Lizenz

Dieses Tool ist unter einer dualen Lizenz verfügbar: einer kommerziellen Lizenz, die für Closed-Source-Projekte geeignet ist, und einer GPL-Lizenz, die in Open-Source-Software verwendet werden kann.

Je nach Ihren Bedürfnissen müssen Sie eine davon auswählen und deren Richtlinien befolgen. Ein Detail der Richtlinien und Vereinbarungen für jeden Lizenztyp finden Sie in den Dateien LICENSE.COMMERCIAL und LICENSE.GPL.

Weiterführende Literatur

  • 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"
  • Erfolgsgeschichten:
    • Android Dynamic Class Loading mit "AES/CFB/NoPadding"-Verschlüsselung. Werfen Sie einen Blick vor & nach. Verwendetes Tool: #simplify. #Android #obfuscation #classencryption #dex
    • Entschlüsseln der Zeichenkettenverschlüsselung von Malware
Tool herunterladen