Question:
Code d'octet Java équivalent aux signatures de fonction IDA
Dr Deo
2016-04-15 14:30:38 UTC
view on stackexchange narkive permalink

Je me souviens que IDA (Interactive Disassembler) a une fonctionnalité très intéressante de signatures de fonction où vous n'avez pas à faire de l'ingénierie inverse du code trouvé dans les bibliothèques standard.
Existe-t-il une fonctionnalité similaire pour le code d'octet Java, en particulier pour le code obscurci ?

La fonction IDA utilise des signatures binaires réelles. Aucune approche de ce type ne fonctionnera pour le code obscurci car il n'y aura pas de signature binaire.
[JEB Decompiler] (https://www.pnfsoftware.com/blog/jeb-1-3-how-to-sign-and-match-third-party-library-code/) a une fonction de signature pour le bytecode java.
@ExtremeCoders mais je ne pense pas que cela fonctionnera pour les fonctions obscurcies.
@LucaD'Amico Ofcourse. Les signatures ne fonctionneront pas pour les fonctions obscurcies.
Deux réponses:
Guntram Blohm supports Monica
2016-04-18 23:19:47 UTC
view on stackexchange narkive permalink

Il n'y a pas de fonctionnalité similaire pour le code d'octet Java.

Lorsque vous compilez un programme C, et le liez statiquement à une bibliothèque standard, le code de la bibliothèque sera présent, plus ou moins non modifié, dans le binaire (sauf pour les adresses qui changeront), mais il n'y aura aucun indice qu'une fonction particulière avait un nom particulier avant d'être compilée (sauf si le débogage est activé lors de la compilation / liaison). Mais, toute fonction donnée a un modèle d'octets plus ou moins fixe, et en reconnaissant ces octets, IDA peut attribuer le nom d'origine à la fonction.

Dans le bytecode Java, il n'est pas nécessaire de le faire. Les noms de fonctions, les noms de variables et des informations similaires sont de toute façon présents dans le bytecode compilé. La "bibliothèque standard", rt.jar , n'est pas non plus intégrée dans le bytecode, donc si une classe utilise une ArrayList , la classe aura une référence à java.util.ArrayList même après le processus d'obfuscation. Donc, rien à faire ici pour un analyseur de signature.

Si l'application choisit de masquer également la bibliothèque standard, elle doit inclure cette bibliothèque obscurcie dans ses propres fichiers jar. Cela soulèvera probablement des problèmes de licence, mais à part cela, comme l'obfuscateur renommera les méthodes et les champs, le code d'octet de cette bibliothèque obscurcie sera trop différent du code d'octet d'origine pour être reconnaissable par une fonctionnalité comme FLIRT d'IDA. De plus, vous ne pouvez pas simplement renommer la méthode dans IDA, car vous devrez également modifier toutes les références.

Cependant, il y a au moins un projet open source qui a un problème similaire au vôtre, et ils semblent l'avoir assez bien résolu. Minecraft est un jeu populaire qui comprend un serveur écrit en Java (et obscurci); le projet Spigot décompile ce serveur, change certaines choses, ajoute une API et distribue le résultat. Plus précisément, pour éviter les problèmes de licence, ils distribuent un système de construction qui télécharge, décompile, corrige et recompile le serveur Minecraft sur la machine de l'utilisateur.

Ils utilisent le décompilateur fernflower, qui a une option pour renommer les symboles lors de la décompilation, et inclure une carte complète de noms de symboles obscurcis à lisibles. Exemple:

  AttributeInstance a () LIAttribute; getAttributeAttributeInstance a (D) V setValueAttributeInstance e () D getValueAttributeMapServer b () Ljava / util / Set; getAttributesAxisAlignedBB b (DDD) LAxisAlignedBB; grow  

Le code source, qui est généré à l'aide de ces cartes, est évidemment bien plus lisible que l'original. Et, au moins pour le projet spigot, recompiler cette source (après avoir ajouté quelques correctifs pour créer une API) donne un serveur Minecraft fonctionnel.

Donc, peut-être, cela pourrait être un moyen pour vous de continuer - utilisez fernflower pour décompiler vos classes, les charger dans un éditeur pour trouver du code utile et attribuer des noms de classe lisibles, écrire un fichier de mappage et répéter ceci plusieurs fois. Ensuite, lorsque vous souhaitez effectuer une analyse dynamique, recompilez le code Java décompilé et chargez-le dans IDA.

Bien sûr, cette approche pose encore quelques problèmes:

  • vous devra toujours identifier chaque fonction manuellement - mais comme je l'ai dit, vous ne trouverez probablement aucune fonction de bibliothèque standard dans votre code de toute façon. Et, il n'y a pas de bibliothèques de signatures existantes pour la méthode que vous utilisez, donc il n'y a probablement aucun moyen de contourner cela.
  • le code décompilé / recompilé peut ne pas fonctionner, en raison de bogues / lacunes dans le décompilateur Java lui-même
  • le code décompilé / recompilé peut ne pas fonctionner à cause de l'obfuscateur; par exemple, l'obfuscator peut remplacer toutes les constantes de chaîne par quelque chose comme Obfuscator :: decode ("some_crypted_stuff") , où la fonction decode utilise le nom de la classe appelante comme son clé de déchiffrement, ce qui signifie que le déchiffrement échoue lorsque la classe est renommée
  • l'obfuscateur peut apporter son propre chargeur de classe, qui modifie le nom de la classe avant de la charger; par exemple, il peut savoir qu'il faut transformer une classe com.obfuscate.SOME_BASE_64_STRING en chaîne base64 décodée, donc com.obfuscate.amF2YS51dGlsLkFycmF5TGlzdAo.something () appellerait java.util.ArrayList.something () . Cela rompt la connexion visible entre l'appelant et l'appelé (mais le mappage de nom pourrait très bien résoudre ce problème et vous pourriez en automatiser beaucoup)

Même si vous ne pouvez pas obtenir un fichier décompilé, recompilable, version de votre binaire, vous pouvez probablement écrire du code qui fonctionne sur la source décompilée pour identifier les fonctions par leur comportement, en utilisant des heuristiques, Ensuite, demandez à votre code d'écrire une table de mappage et d'écrire un plugin python pour importer cette table de mappage dans votre code sous forme de commentaires.

Il est douteux que ces approches battent l'ingénierie inverse manuelle dans IDA, mais comme IDA n'a pas cette fonctionnalité, et comme il n'y a pas de bibliothèques de signatures génériques (et elles ne fonctionneraient pas de toute façon, voir ci-dessus), c'est le meilleur que j'ai à offrir.

Modifier le 17/04/2016

Il s'avère que j'ai un petit projet où je pourrais utiliser moi-même une cartographie de désobfuscation, et j'ai vérifié dans le processus de désobfuscation de l'étape de décompilation de Minecraft un peu plus.

Il s'avère qu'ils n'utilisent même pas de fleurs de fougère r fonction d'émappage. Au lieu de cela, ils ont leur propre ensemble d'outils. Celles-ci sont lamentablement sous-documentées, mais il semble y avoir un dépôt GitHub.

Le premier, SpecialSource.jar, compare un fichier jar masqué avec une version non masquée et génère une table de mappage. Cela semble permettre de construire rapidement de nouvelles tables lorsqu'une nouvelle version de l'original masqué sort. Il n'y a cependant aucune documentation sur ce qui est exactement comparé.

Le second, SpecialSource-2.jar, remappe les références et noms de classes et de méthodes directement jar , sans étape de décompilation / compilation, ce qui évite tous les problèmes qui viennent avec. Donc, une fois que vous avez un fichier de mappage, vous pouvez l'appliquer au fichier jar pour obtenir un fichier jar de sortie, que vous pouvez ensuite alimenter dans IDA, ou un décompilateur de votre choix.L'utilisation est

  java - jar /chemin/vers/SpecialSource-2.jar map -m mapping.csrg \ -i obfuscated.jar -o readable.jar  

avec le fichier de mappage ressemblant à ceci

  # Ceci renomme une classe, étant donné le nom obscurci et le onecom lisible / exemple / ab / a MyNiceClassName # Cela renomme une méthode, étant donné la classe, la méthode, la signature et le nom lisible.MyNiceClassName a (D) Je doubleToInt  
douggard
2016-04-19 23:01:19 UTC
view on stackexchange narkive permalink

Si le graphe de flux de contrôle n'a pas été obscurci, vous pouvez les utiliser pour faire correspondre les méthodes. Le plus gros obstacle à cela est de constituer la base de données des signatures de bibliothèque.

Les graphiques de flux de contrôle sont la structure que forment les blocs de base lorsqu'ils sont vus comme un graphique dirigé. [1] Ceux-ci représentent les chemins possibles d'exécution dans une méthode. Ils sont relativement faciles à analyser et à récupérer à partir d'une application compilée. La plupart des obfuscations Android et Java se concentrent sur les noms de méthodes et non sur le flux de contrôle. De plus, le bytecode Java / Dalvik peut changer entre les compilations si les méthodes sont modifiées ou déplacées. C'est là que la comparaison de la structure est utile, à moins que de sérieux changements ne soient apportés, le flux de contrôle restera probablement le même.

J'ai travaillé avec la correspondance des graphiques de flux de contrôle dans les applications Android. [2] [3] La véritable force du projet s'est avérée être le regroupement de souches de logiciels malveillants. Cela correspondrait à des méthodes qui étaient de structure similaire et vous pourriez voir que certaines applications partageaient des méthodes avec d'autres applications, et comment les souches ont évolué.

Si vous cherchez à créer une signature de fonction Java, une combinaison entre structurelle et la correspondance de base d'octets serait très puissante.

  1. https://en.wikipedia.org/wiki/Control_flow_graph
  2. https: //github.com/douggard/CFGScanDroid
  3. http://www.irongeek.com/i.php?page=videos/derbycon4/t420-control-flow-graph -based-virus-scanning-douglas-goddard
D'après les 3 minutes que j'ai passées à jeter un coup d'œil sur le dépôt, cela semble très intéressant, surtout dans le but de "mettre à jour" une carte obscurcie à lisible vers une version plus récente du binaire obscurci. Votre projet fonctionnera-t-il également avec les fichiers .jar, ou uniquement avec les fichiers dex?
Seuls les fichiers dex, une grande partie du code pourrait être réutilisée, il s'agirait simplement d'obtenir le bytecode des fichiers de classe et d'analyser les méthodes. Je suis sûr qu'il existe une bibliothèque Java faite pour cela. L'extraction CFG peut être un peu différente de Dalvik à Java, mais probablement rien d'énorme.


Ce Q&R a été automatiquement traduit de la langue anglaise.Le contenu original est disponible sur stackexchange, que nous remercions pour la licence cc by-sa 3.0 sous laquelle il est distribué.
Loading...