Skip to content
KitploitKITPLOIT
OutilsBlog
Soumettre
OutilsBlog
Soumettre

Outils de Hacking, PenTest et Cybersécurité pour votre Arsenal de Sécurité !

Kitploit est un répertoire d'outils de hacking, de cybersécurité et de pentesting. Découvrez les dernières mises à jour des projets pour trouver des vulnérabilités, analyser des systèmes, automatiser les tests et renforcer votre sécurité.

··Flux·Contact·Confidentialité·© 2026 Kitploit

Répertoire d'outils

Catégories

Voir toutes les catégories
Loading categories
simplify — Machine virtuelle Android et désobfuscateur | Kitploit
Outils/GitHubGitHub/calebfenton/simplify
Sécurité AndroidAnalyse Dynamique (Sandboxing)Rétro-ingénierieAnalyse de MalwareAnalyse de Binaires
GitHubcalebfenton/simplify

simplify

Machine virtuelle Android et désobfuscateur

Voir le dépôt
4.7k4557il y a 5 ansVérifié par Kitploit

Populaires

Voir tout →

Découvrez les outils les plus utilisés par notre communauté.

Explorer tous les outils

Parcourez notre collection d'outils

Voir tous les outils →
Partager

Simplify

Build Status Coverage Status Coverity Scan Build Status

Désobfuscateur Android Générique

Simplify exécute virtuellement une application pour comprendre son comportement, puis tente d'optimiser le code afin qu'il se comporte de manière identique mais soit plus facile à comprendre pour un humain. Chaque type d'optimisation est simple et générique, de sorte que le type spécifique d'obfuscation utilisé n'a pas d'importance.

Avant et Après

Le code à gauche est une décompilation d'une application obfusquée, et le code à droite a été désobfusqué.

Beaucoup d'appels de méthode, aucun sens clair Wow, tellement littéral, beaucoup de sens

Aperçu

Le projet comporte trois parties : smalivm, simplify et l'application de démonstration.

  1. smalivm : Fournit un bac à sable de machine virtuelle pour exécuter des méthodes Dalvik. Après avoir exécuté une méthode, il renvoie un graphe contenant toutes les valeurs possibles de registre et de classe pour chaque chemin d'exécution. Il fonctionne même si certaines valeurs sont inconnues, comme les entrées/sorties de fichiers et réseau. Par exemple, toute condition if ou switch avec une valeur inconnue conduit à la prise des deux branches.
  2. simplify : Analyse les graphes d'exécution de smalivm et applique des optimisations telles que la propagation de constantes, la suppression de code mort, la désréflexion et quelques optimisations de type peephole. Elles sont assez simples, mais lorsqu'elles sont appliquées ensemble de manière répétée, elles déchiffreront les chaînes, supprimeront la réflexion et simplifieront grandement le code. Il ne renomme pas les méthodes et les classes.
  3. demoapp : Contient des exemples simples et abondamment commentés pour utiliser smalivm dans votre propre projet. Si vous construisez quelque chose qui nécessite d'exécuter du code Dalvik, jetez-y un œil.

Utilisation

root@kitploit:~
usage : java -jar simplify.jar <input> [options]
désobfusque un exécutable Dalvik
 -et,--exclude-types <pattern>   Exclure les classes et méthodes qui incluent REGEX, ex: "com/android", appliqué après include-types
 -h,--help                       Afficher ce message
 -ie,--ignore-errors             Ignorer les erreurs lors de l'exécution et de l'optimisation des méthodes. Cela peut conduire à un comportement inattendu.
    --include-support            Tenter d'exécuter et d'optimiser les classes dans les packages de la bibliothèque de support Android, par défaut : false
 -it,--include-types <pattern>   Limiter l'exécution aux classes et méthodes qui incluent REGEX, ex: ";->targetMethod\("
    --max-address-visits <N>     Abandonner l'exécution d'une méthode après avoir visité la même adresse N fois, limite les boucles, par défaut : 10000
    --max-call-depth <N>         Ne pas appeler de méthodes après avoir atteint une profondeur d'appel de N, limite la récursion et les longues chaînes de méthodes, par défaut : 50
    --max-execution-time <N>     Abandonner l'exécution d'une méthode après N secondes, par défaut : 300
    --max-method-visits <N>      Abandonner l'exécution d'une méthode après avoir exécuté N instructions dans cette méthode, par défaut : 1000000
    --max-passes <N>             Ne pas exécuter les optimiseurs sur une méthode plus de N fois, par défaut : 100
 -o,--output <file>              Écrire l'entrée simplifiée dans FICHIER
    --output-api-level <LEVEL>   Définir la compatibilité API DEX de sortie au NIVEAU, par défaut : 15
 -q,--quiet                      Être silencieux
    --remove-weak                Supprimer le code même en cas d'effets secondaires faibles, par défaut : true
 -v,--verbose <LEVEL>            Définir la verbosité au NIVEAU, par défaut : 0

Construction

La construction nécessite l'installation du Java Development Kit 8 (JDK).

Comme ce projet contient des sous-modules pour les frameworks Android, clonez avec --recursive :

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

Ou mettez à jour les sous-modules à tout moment avec :

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

Ensuite, pour construire un jar unique contenant toutes les dépendances :

root@kitploit:~
./gradlew fatjar

Le jar Simplify se trouvera dans simplify/build/libs/. Vous pouvez tester son fonctionnement en simplifiant l'exemple d'application obfusquée fourni. Voici comment l'exécuter (vous devrez peut-être modifier simplify.jar) :

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

Pour comprendre ce qui est désobfusqué, consultez le README de l'application obfusquée.

Dépannage

Si Simplify échoue, essayez ces recommandations, dans l'ordre :

  1. Ciblez uniquement quelques méthodes ou classes en utilisant l'option -it.
  2. Si l'échec est dû à un dépassement des visites maximales, essayez d'utiliser des valeurs plus élevées pour --max-address-visits, --max-call-depth et --max-method-visits.
  3. Essayez avec -v ou -v 2 et signalez le problème avec les logs et un hachage du DEX ou APK.
  4. Réessayez, mais ne rompez pas le contact visuel. Simplify peut sentir la peur.

Si la construction sous Windows échoue avec une erreur similaire à :

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

Cela signifie que Gradle ne parvient pas à trouver un chemin JDK approprié. Assurez-vous que le JDK est installé, définissez la variable d'environnement JAVA_HOME sur votre chemin JDK, et assurez-vous de fermer et de rouvrir l'invite de commande que vous utilisez pour la construction.

Contribuer

Ne soyez pas timide. Je pense que l'exécution virtuelle et la désobfuscation sont des problèmes fascinants. Toute personne intéressée est automatiquement cool et les contributions sont les bienvenues, même s'il s'agit simplement de corriger une faute de frappe. N'hésitez pas à poser des questions dans les issues et à soumettre des pull requests.

Signaler des problèmes

Veuillez inclure un lien vers l'APK ou le DEX et la commande complète que vous utilisez. Cela facilite grandement la reproduction (et donc la correction) de votre problème.

Si vous ne pouvez pas partager l'échantillon, veuillez inclure le hachage du fichier (SHA1, SHA256, etc.).

Stratégies d'optimisation

Propagation de constantes

Si une opération place une valeur d'un type qui peut être transformé en constante, comme une chaîne, un nombre ou un booléen, cette optimisation remplacera cette opération par la constante. Par exemple :

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

Dans cet exemple, une chaîne chiffrée est déchiffrée et placée dans v0. Comme les chaînes sont « constantisables », le move-result v0 peut être remplacé par 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."

Suppression de code mort

Le code est mort si sa suppression ne peut pas altérer le comportement de l'application. Le cas le plus évident est si le code est inaccessible, par exemple if (false) { // mort }). Si le code est accessible, il peut être considéré comme mort s'il n'affecte aucun état en dehors de la méthode, c'est-à-dire s'il n'a pas d'effet secondaire. Par exemple, le code peut ne pas affecter la valeur de retour de la méthode, modifier des variables de classe, ou effectuer des E/S. C'est difficile à déterminer en analyse statique. Heureusement, smalivm n'a pas besoin d'être intelligent. Il exécute bêtement tout ce qu'il peut et suppose qu'il y a des effets secondaires s'il n'en est pas sûr.

Considérez l'exemple de la Propagation de constantes :

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

Dans ce code, le invoke-static n'affecte plus la valeur de retour de la méthode et supposons qu'il ne fait rien d'étrange comme écrire des octets dans le système de fichiers ou un socket réseau, donc il n'a pas d'effets secondaires. Il peut simplement être supprimé.

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

Enfin, le premier const-string assigne une valeur à un registre, mais cette valeur n'est jamais utilisée, c'est-à-dire que l'affectation est morte. Elle peut également être supprimée.

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

Huzzah !

Désréflexion

L'un des principaux défis de l'analyse statique de Java est la réflexion. Il n'est tout simplement pas possible de connaître les arguments des méthodes de réflexion sans effectuer une analyse minutieuse du flux de données. Il existe des moyens intelligents et astucieux de le faire, mais smalivm le fait en exécutant simplement le code. Lorsqu'il trouve une invocation de méthode réfléchie telle que :

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

Il peut connaître les valeurs de v0, v1 et v2. S'il est sûr de ces valeurs, il peut remplacer l'appel à Method.invoke() par une invocation de méthode non réfléchie réelle. Il en va de même pour les recherches de champs et de classes réfléchies.

Peephole

Pour tout ce qui ne rentre pas proprement dans une catégorie particulière, il y a les optimisations de type peephole. Cela inclut la suppression des opérations check-cast inutiles, le remplacement des appels Ljava/lang/String;-><init> par const-string, etc.

Exemple de désobfuscation

Avant optimisation

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

Tout cela fait v0 = 1.

Après propagation de constantes

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

Le move-result v0 est remplacé par const/4 v0, 0x1. Cela est dû au fait qu'il n'y a qu'une seule valeur de retour possible pour intValue()I et que le type de retour peut être transformé en constante. Les arguments v0 et v1 sont sans ambiguïté et ne changent pas. Autrement dit, il y a un consensus de valeurs pour chaque chemin d'exécution possible au niveau de intValue()I.

Autres types de valeurs pouvant être transformées en constantes :

  • nombres - const/4, const/16, etc.
  • chaînes - const-string
  • classes - const-class

Après suppression de code mort

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

    const/4 v0, 0x1

    return v0
.end method

Parce que le code au-dessus de const/4 v0, 0x1 n'affecte pas l'état en dehors de la méthode (aucun effet secondaire), il peut être supprimé sans changer le comportement. S'il y avait un appel de méthode qui écrivait quelque chose dans le système de fichiers ou le réseau, il ne pourrait pas être supprimé car il affecte l'état en dehors de la méthode. Ou si test()I prenait un argument mutable, comme un LinkedList, toute instruction qui y accédait ne pourrait pas être considérée comme morte.

Autres exemples de code mort :

  • affectations non référencées - assigner des registres sans les utiliser
  • instructions non atteintes / inaccessibles - if (false) { dead_code(); }

Licence

Cet outil est disponible sous une double licence : une licence commerciale adaptée aux projets à source fermée et une licence GPL pouvant être utilisée dans les logiciels open source.

Selon vos besoins, vous devez en choisir une et suivre ses politiques. Le détail des politiques et accords pour chaque type de licence est disponible dans les fichiers LICENSE.COMMERCIAL et LICENSE.GPL.

Lectures complémentaires

  • 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"
  • Témoignages de réussite :
    • Chargement dynamique de classes Android avec chiffrement "AES/CFB/NoPadding". Jetez un œil avant et après. Outil utilisé : #simplify. #Android #obfuscation #classencryption #dex
    • Déchiffrement du chiffrement de chaînes de malware
Télécharger l’outil