
Machine virtuelle Android et désobfuscateur
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.
Le code à gauche est une décompilation d'une application obfusquée, et le code à droite a été désobfusqué.
Le projet comporte trois parties : smalivm, simplify et l'application de démonstration.
if ou switch avec une valeur inconnue conduit à la prise des deux branches.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
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 :
git clone --recursive https://github.com/CalebFenton/simplify.git
Ou mettez à jour les sous-modules à tout moment avec :
git submodule update --init --recursive
Ensuite, pour construire un jar unique contenant toutes les dépendances :
./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) :
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.
Si Simplify échoue, essayez ces recommandations, dans l'ordre :
-it.--max-address-visits, --max-call-depth et --max-method-visits.-v ou -v 2 et signalez le problème avec les logs et un hachage du DEX ou APK.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.
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.
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.).
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 :
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 :