6 façons de masquer des données dans une application Android

Bonjour, cher lecteur, j'étudie les applications mobiles depuis un certain temps. La plupart des applications n'essaient pas de me cacher en quelque sorte leur fonctionnalité "secrète". Et je suis heureux en ce moment, car je n'ai pas à étudier le code obscurci de quelqu'un.


image


Dans cet article, je voudrais partager ma vision de l'obscurcissement, ainsi que parler d'une méthode intéressante pour masquer la logique métier dans les applications avec NDK, que j'ai trouvée relativement récemment. Donc, si vous êtes intéressé par des exemples en direct de code obscurci dans Android - je demande chat.


Sous l'obscurcissement dans le cadre de cet article, on comprend la réduction du code exécutable d'une application Android à un formulaire difficile à analyser. Il y a plusieurs raisons pour rendre l'analyse de code difficile:


  1. Aucune entreprise ne veut se faire fourrer dans ses «entrailles».
  2. Même si vous avez une application factice, vous pouvez toujours y trouver des choses intéressantes (un exemple avec instagram ).

De nombreux développeurs résolvent le problème en forçant simplement la configuration ProGuard. Ce n'est pas la meilleure façon de protéger les données (si c'est la première fois que vous en entendez parler, consultez le wiki ).


Je veux donner un exemple, pourquoi la prétendue «protection» avec ProGuard ne fonctionne pas. Prenez un exemple simple de Google Samples.


image


Après avoir connecté ProGuard à une configuration standard, nous obtenons un code décompilé:


image


«Ohhh, rien n'est clair», disons-nous et nous calmes. Mais après quelques minutes de basculement entre les fichiers, nous trouvons des morceaux de code similaires:


image


Dans cet exemple, le code d'application semble plutôt faible (enregistrement des données, création de capture vidéo), donc certaines des méthodes utilisées dans le code d'origine sont facilement comprises même après le traitement avec la configuration ProGuard.


De plus, jetez un œil aux classes de données dans Kotlin. La classe de données par défaut crée la méthode «toString», qui contient les noms des variables d'instance et le nom de la classe elle-même.


Classe de données source:


image


Il peut se transformer en friandise pour un revers:


image
(génération automatique de la méthode toString dans Kotlin)


Il s'avère que ProGuard se cache loin de tout le code source du projet.


Si je ne vous ai toujours pas convaincu de l'inefficacité de la protection du code de cette manière, essayons de laisser l'attribut «.source» dans notre projet.


-keepattributes SourceFile 

Cette ligne est dans de nombreux projets open source. Il vous permet de visualiser StackTrace lorsque l'application se bloque. Cependant, en tirant «.source» du code smali, nous obtenons la hiérarchie entière du projet avec les noms de classe complets.


Par définition, l'obscurcissement consiste à «mettre le code source sous une forme illisible afin de contrecarrer différents types de réception». Cependant, ProGuard (lorsqu'il est utilisé avec une configuration standard) ne rend pas le code illisible - il fonctionne comme un minifieur, compressant les noms et jetant des classes supplémentaires hors du projet.


Une telle utilisation de ProGuard est une solution facile mais pas tout à fait appropriée pour une bonne solution d'obscurcissement. Un bon développeur doit faire en sorte que le revendeur (ou l'attaquant) ait peur des «caractères chinois», qui sont difficiles à désobfusquer.


Si vous souhaitez en savoir plus sur ProGuard, je vous propose l' article informatif suivant.


Que cachons-nous


Voyons maintenant ce qui est généralement caché dans les applications.


  • Clés de chiffrement:

image


  • Logique d'application spécifique:

image


Quelque chose de plus inattendu peut souvent être caché dans le code (observations de l'expérience personnelle), par exemple:


  • Noms des développeurs de projets
  • Chemin complet vers le projet
  • Client_secret pour le protocole Oauth2
  • Livre PDF «Comment développer pour Android» (probablement à portée de main)

Maintenant, nous savons ce qui peut se cacher dans les applications Android et pouvons passer à l'essentiel, à savoir comment masquer ces données.


Façons de masquer les données


Option 1: ne cachez rien, laissez tout en vue


Dans ce cas, je vous montre juste cette photo :)


«Aidez Dasha à trouver la logique métier»


image


Cette solution économique et totalement gratuite convient pour:


  • Applications simples qui n'interagissent pas avec le réseau et ne stockent pas d'informations sensibles sur les utilisateurs;
  • Applications qui utilisent uniquement l'API publique.

Option 2: utilisez ProGuard avec les paramètres corrects


Cette décision a toujours droit à la vie, car avant tout elle est simple et gratuite. Malgré les inconvénients susmentionnés, il présente un avantage considérable: si les règles ProGuard sont correctement configurées, l'application peut vraiment devenir obscurcie.


Cependant, vous devez comprendre qu'une telle solution après chaque assemblage nécessite que le développeur décompile et vérifie si tout va bien. Après avoir passé plusieurs minutes à étudier le fichier APK, le développeur (et son entreprise) peuvent avoir plus confiance en la sécurité de leur produit.


Comment étudier le fichier APK

La vérification de l'application pour l'obscurcissement est assez simple.


Afin d'obtenir le fichier APK du projet, il existe plusieurs façons:


  • prendre à partir du répertoire du projet (dans Android Studio, le nom du dossier est généralement «build»);
  • installez l'application sur votre smartphone et obtenez l'APK en utilisant l'application «Apk Extractor».

Après cela, en utilisant l'utilitaire Apktool, nous obtenons le code Smali (instructions pour arriver ici https://ibotpeaches.imtqy.com/Apktool/documentation ) et essayons de trouver quelque chose de suspect dans les lignes du projet. Soit dit en passant, pour rechercher des codes lisibles, vous pouvez faire le plein de commandes bash prédéfinies.


Cette solution convient pour:


  • Applications de jouets, applications de boutique en ligne, etc.
  • Les applications qui sont vraiment des clients légers et toutes les données proviennent exclusivement du côté serveur;
  • Les applications qui n'écrivent pas sur toutes leurs bannières «Safe Application No. 1».

Option 3: utiliser l'Obfuscateur Open Source


Malheureusement, je ne connais pas les très bons masqueurs gratuits pour les applications mobiles. Et les obscurcisseurs qui peuvent être trouvés sur le réseau peuvent vous apporter beaucoup de maux de tête, car il sera trop difficile d'assembler un tel projet pour de nouvelles versions de l'API.


Historiquement, les obfuscateurs sympas existants sont fabriqués sous le code machine (pour C / C ++). De bons exemples:



Par exemple, Movfuscator remplace tous les opcodes par movs, rend le code linéaire, supprimant toutes les branches. Cependant, il est fortement déconseillé d'utiliser cette méthode d'obscurcissement dans un projet de combat, car alors le code risque de devenir très lent et lourd.


Cette solution convient aux applications où la partie principale du code est NDK.


Option 4: utilisez une solution propriétaire


C'est le choix le plus compétent pour les applications sérieuses, en tant que logiciel propriétaire:
a) pris en charge;
b) sera toujours pertinent.


Un exemple de code obscurci lors de l'utilisation de telles solutions:


image


Dans cet extrait de code, vous pouvez voir:


  1. Les noms de variables les plus incompréhensibles (avec la présence de lettres russes);
  2. Caractères chinois dans les lignes qui ne précisent pas ce qui se passe réellement dans le projet;
  3. Il y a beaucoup de pièges ajoutés au projet («switch», «goto»), qui changent considérablement le flux de code de l'application.

Cette solution convient pour:


  • Les banques
  • Compagnies d'assurance;
  • Opérateurs mobiles, applications de stockage de mots de passe, etc.

Option 5: utiliser React-Native


J'ai décidé de souligner ce point, car l'écriture d'applications multiplateformes est devenue une activité très populaire.


En plus d'une très grande communauté, JS possède un très grand nombre d'obscurcisseurs ouverts. Par exemple, ils peuvent transformer votre application en émoticônes:


image


Je voudrais vraiment vous conseiller sur cette solution, mais alors votre projet fonctionnera très peu plus vite qu'une tortue.


Mais en réduisant l'exigence d'obscurcissement du code, nous pouvons créer un projet vraiment bien protégé. Alors google "js obfuscator" et obscurcissez notre fichier de bundle de sortie.


Cette solution convient à ceux qui sont prêts à écrire une application multiplateforme sur React Native.


Xamarin

Il serait très intéressant de connaître les obfuscateurs sur Xamarin, si vous avez de l'expérience avec eux, veuillez nous en parler dans les commentaires.


Option 6: utilisez NDK


J'ai moi-même souvent dû utiliser NDK dans mon code. Et je sais que certains développeurs pensent que l'utilisation de NDK sauve leur application des inverseurs. Ce n'est pas tout à fait vrai. Vous devez d'abord comprendre comment fonctionne le masquage avec le NDK.


image


Cela s'avère très simple. Il existe une convention JNI dans le code selon laquelle lorsque vous appelez du code C / C ++ dans un projet, il sera converti comme suit.


Native Native Class:


image


Implémentation de la méthode de somme native:


image


Implémentation de la méthode native de somme statique:


image


Il devient clair que pour appeler la méthode native, vous utilisez la recherche de fonction Java_<package name>_<Static?><class>_<method> dans la bibliothèque dynamique.


Si vous regardez le code Dalvik / ART, nous trouverons les lignes suivantes:


image


( source )


Tout d'abord, nous allons générer la ligne suivante Java_<package name>_<class>_<method> partir de l'objet Java, puis essayer de résoudre la méthode dans la bibliothèque dynamique à l'aide de l'appel "dlsym", qui tentera de trouver la fonction dont nous avons besoin dans le NDK.


C'est ainsi que fonctionne JNI. Son principal problème est qu'en décompilant la bibliothèque dynamique, nous verrons toutes les méthodes en pleine vue:


image


Donc, nous devons trouver une telle solution pour que l'adresse de la fonction soit obscurcie.


Au début, j'ai essayé d'écrire des données directement dans notre table JNI, mais j'ai réalisé que les mécanismes ASLR et les différentes versions d'Android ne me permettraient tout simplement pas de faire fonctionner cette méthode sur tous les appareils. J'ai alors décidé de découvrir quelles méthodes le NDK fournit aux développeurs.


Et, voilà , il y avait une méthode «RegisterNatives» qui fait exactement ce dont nous avons besoin (appelle la fonction interne dvmRegisterJNIMethod ).


Nous définissons un tableau qui décrit notre méthode native:


image


Et nous enregistrons notre méthode déclarée dans la fonction JNI_OnLoad (la méthode est appelée après l'initialisation de la bibliothèque dynamique, en milliers ):


image


Hourra, nous avons nous-mêmes caché la fonction «hideFunc». Appliquez maintenant notre obfuscateur llvm préféré et profitez de la sécurité du code dans sa forme finale.


Cette solution convient aux applications qui utilisent déjà NDK (la connexion de NDK apporte beaucoup de difficultés au projet, donc cette solution n'est pas si pertinente pour les applications non NDK).


Conclusion


En fait, l'application ne devrait pas stocker de données sensibles, ou elles devraient être accessibles uniquement après l'authentification de l'utilisateur. Cependant, il arrive que la logique métier oblige les développeurs à stocker des jetons, des clés et des éléments spécifiques de la logique du code dans l'application. J'espère que cet article vous aidera si vous ne voulez pas partager de telles données sensibles et être un «livre ouvert» pour les scribes.


Je crois que l'obscurcissement est un élément structurel important de toute application moderne.


Réfléchissez bien aux problèmes de masquage de code et ne cherchez pas de moyens faciles! :)


Soit dit en passant, merci à l'utilisateur miproblema pour l'aide dans certains problèmes. Abonnez-vous à sa chaîne de télégramme, c'est intéressant là-bas.


Et merci également aux utilisateurs de sverkunchik et SCaptainCAP pour leur aide dans l'édition de l'article.

Source: https://habr.com/ru/post/fr436908/


All Articles