fix the french

This commit is contained in:
Jean-Marie 'Histausse' Mineau 2025-11-25 21:22:45 +01:00
parent d4af44a0d8
commit 42b7d7db64
Signed by: histausse
GPG key ID: B66AEEDA9B645AD2

View file

@ -37,14 +37,14 @@ Chacune a ses forces et ses faiblesses, et certains problèmes d'analyse sont tr
L'un de ces problème est le chargement dynamique de code. L'un de ces problème est le chargement dynamique de code.
Les applications Android sont initiallement prévues pour être codées en Java, Android a donc a hérité de nombreuses fonctionnalités de Java. Les applications Android sont initiallement prévues pour être codées en Java, Android a donc a hérité de nombreuses fonctionnalités de Java.
En l'occurence, Android a un système de chargeur de classes similaire à celui de Java, qui peut être utilisé pour charger, en cour d'exécution, du code extérieur à l'application. En l'occurence, Android a un système de chargeur de classes similaire à celui de Java, qui peut être utilisé pour charger, en cour d'exécution, du code extérieur à l'application.
Etant donné que ce code chargé dynamiquement n'est pas nécessairement disponible dans l'application initialement, ce problème est relégé à l'analyse dynamique. Etant donné que ce code chargé dynamiquement n'est pas nécessairement disponible dans l'application initialement, ce problème est relégué à l'analyse dynamique.
Toutefois, il semblerait qu'une généralisation hâtive soit souvent faite, et que le système de chargement de classe dans son ensemble soit relégé à l'analyse dynamique. Toutefois, il semblerait qu'une généralisation hâtive soit souvent faite, et que le système de chargement de classe dans son ensemble soit relégué à l'analyse dynamique.
L'absence d'étude détaillée de ce mecanisme nous amène à notre seconde problématique: #pb2-text-fr L'absence d'étude détaillée de ce mecanisme nous amène à notre seconde problématique: #pb2-text-fr
Un autre problème usuellement associé à l'analyse dynamique est la réflexion. Un autre problème usuellement associé à l'analyse dynamique est la réflexion.
Android permet à une application de manipuler les classes et méthodes sous forme d'objet. Android permet à une application de manipuler les classes et méthodes sous forme d'objet.
En utilisant cette fonctionnalité, il est donc possible d'appeler une méthode en utilisant son nom sous forme de chaine de caractère au lieu d'utiliser une instruction Dalvik avec une référence vers la méthode appelée. En utilisant cette fonctionnalité, il est donc possible d'appeler une méthode en utilisant son nom sous forme de chaîne de caractère au lieu d'utiliser une instruction Dalvik avec une référence vers la méthode appelée.
Ce cas est déjà compliqué à analyser statiquement quand la chaine de caractère est lisible dans l'application, mais il devient imposible quand elle ne l'est pas (#eg la chaine est envoyée par un serveur externe lors de l'exécution, ou elle est stockée chiffrée et n'est déchiffrée qu'au dernier moment). Ce cas est déjà compliqué à analyser statiquement quand la chaîne de caractère est lisible dans l'application, mais il devient imposible quand elle ne l'est pas (#eg la chaîne est envoyée par un serveur externe lors de l'exécution, ou elle est stockée chiffrée et n'est déchiffrée qu'au dernier moment).
L'analyse dynamique permet de capturer à la fois le code chargé dynamiquement et les méthodes appelées par réflexion. L'analyse dynamique permet de capturer à la fois le code chargé dynamiquement et les méthodes appelées par réflexion.
Toutefois, obtenir ces instructions est insuffisant. Toutefois, obtenir ces instructions est insuffisant.
Il n'existe pas de solution standard pour transmettre ces données aux outils d'analyse statique, qui pourtant peuvent en avoir besoin pour analyser l'application dans son entièreté. Il n'existe pas de solution standard pour transmettre ces données aux outils d'analyse statique, qui pourtant peuvent en avoir besoin pour analyser l'application dans son entièreté.
@ -221,9 +221,9 @@ Après avoir lancé les outils, nous avons collecté les différents résultats
@fig:rasta-exit-drebin-fr et @fig:rasta-exit-fr montrent les résultas des analyses sur les applications de Drebin et RASTA. @fig:rasta-exit-drebin-fr et @fig:rasta-exit-fr montrent les résultas des analyses sur les applications de Drebin et RASTA.
L'analyse est considérée comme réussie (vert) si un résultat est obtenu, sinon elle a échoué (rouge). L'analyse est considérée comme réussie (vert) si un résultat est obtenu, sinon elle a échoué (rouge).
Quand l'analyse met plus d'une heure à finir, elle est avortée (bleue). Quand l'analyse met plus d'une heure à finir, elle est avortée (bleue).
On peut voir que les outils ont d'assez bon résultats sur Drebin, avec 11 outils qui ont un taux de finition au dessus de 85%. On peut voir que les outils ont d'assez bon résultats sur Drebin, avec 11 outils qui ont un taux de terminaison au dessus de 85%.
Sur RASTA par contre, #resultunusablenb outils (#resultunusable) ont un taux de finition en dessous de 50%. Sur RASTA par contre, #resultunusablenb outils (#resultunusable) ont un taux de terminaison en dessous de 50%.
Les outils qui avaient des difficultés avec Drebin ont aussi de mauvais résultats sur RASTA, mais d'autre outils avec des résultats acceptables sur Drebin chutent avec RASTA. Les outils qui avaient des difficultés avec Drebin ont aussi de mauvais résultats sur RASTA, mais d'autres outils avec des résultats acceptables sur Drebin voient leur résultats chuter avec RASTA.
Ces résultats nous permettent de répondre à notre première question *QR1*: Ces résultats nous permettent de répondre à notre première question *QR1*:
@ -265,7 +265,7 @@ De plus pour les outils que nous avons pu lancer, #resultratio des analyses ont
wognsen_et_al: 75% finies, 1% échoues, le reste dépasse la limite de temps." wognsen_et_al: 75% finies, 1% échoues, le reste dépasse la limite de temps."
).join() ).join()
), ),
caption: [Taux de finition pour le jeu d'applications Drebin], caption: [Taux de terminaison pour le jeu d'applications Drebin],
) <fig:rasta-exit-drebin-fr> ) <fig:rasta-exit-drebin-fr>
#figure( #figure(
@ -306,27 +306,27 @@ De plus pour les outils que nous avons pu lancer, #resultratio des analyses ont
"dépasse la limite de temps." "dépasse la limite de temps."
).join() ).join()
), ),
caption: [Taux de finition pour le jeu d'application RASTA], caption: [Taux de terminaison pour le jeu d'application RASTA],
) <fig:rasta-exit-fr> ) <fig:rasta-exit-fr>
Nous avons ensuite étudié l'évolution du taux de finition des outils au cours des ans. Nous avons ensuite étudié l'évolution du taux de terminaison des outils au cours des ans.
La @fig:rasta-exit-evolution-java-fr montre cette évolution pour les outils codés en Java. La @fig:rasta-exit-evolution-java-fr montre cette évolution pour les outils codés en Java.
On peut noter une tendance générale le taux de finition diminue avec le temps. On peut noter une tendance générale le taux de terminaison diminue avec le temps.
Plusieurs facteurs peuvent être responsables. Plusieurs facteurs peuvent être responsables.
Par exemple, la librairie standard d'Android et le format des applications ont évolué avec les versions d'Android. Par exemple, la librairie standard d'Android et le format des applications ont évolué avec les versions d'Android.
Un autre changement notable est la taille du code à octets des applications. Un autre changement notable est la taille du code à octets des applications.
Les applications les plus récentes ont notablement plus de code. Les applications les plus récentes ont notablement plus de code.
Pour déterminer le facteur qui influence le plus le taux de finitions, nous avons étudié des sous-ensembles de RASTA avec certains de ces paramètres fixés. Pour déterminer le facteur qui influence le plus le taux de terminaison, nous avons étudié des sous-ensembles de RASTA avec certains de ces paramètres fixés.
Par exemple, nous avons tracé l'évolution du taux de finition en fonction de l'année de publication des applications sur l'ensemble des applications dont le code à octets fait entre 4.08 et 5.2 Mo. Par exemple, nous avons tracé l'évolution du taux de terminaison en fonction de l'année de publication des applications sur l'ensemble des applications dont le code à octets fait entre 4.08 et 5.2 Mo.
#figure( #figure(
image( image(
"../3_rasta/figs/finishing-rate-by-year-of-java-based-tools.svg", "../3_rasta/figs/finishing-rate-by-year-of-java-based-tools.svg",
width: 90%, width: 90%,
alt: ( alt: (
"Graphe montrant le taux de finition en ordonées (de 0 à 100%) ", "Graphe montrant le taux de terminaison en ordonées (de 0 à 100%) ",
"et l'année les applications ont été découvertes pour la première ", "et l'année les applications ont été découvertes pour la première ",
"fois en abscisse (de 2010 à 2023). ", "fois en abscisse (de 2010 à 2023). ",
"Il y a une courbe pour chacun des outils suivant: anadroid, blueseal ", "Il y a une courbe pour chacun des outils suivant: anadroid, blueseal ",
@ -343,24 +343,24 @@ Par exemple, nous avons tracé l'évolution du taux de finition en fonction de l
"et ic3_fork commence a chutter après 2017." "et ic3_fork commence a chutter après 2017."
).join() ).join()
), ),
caption: [Taux de finition des outils basé sur Java au cours des ans], caption: [Taux de terminaison des outils basé sur Java au cours des ans],
) <fig:rasta-exit-evolution-java-fr> ) <fig:rasta-exit-evolution-java-fr>
Nous en avons conlu la réponse à notre question de recherche *QR2*: Nous en avons conlu la réponse à notre question de recherche *QR2*:
Au cour du temps, le taux de finition des outils diminue, allant de 78% à 61% cinq ans plus tard, à 45% dix ans plus tard. Au cour du temps, le taux de terminaison des outils diminue, allant de 78% à 61% cinq ans plus tard, à 45% dix ans plus tard.
Ce taux varie en fonction de la taille du code à octet, et, dans de moindre mesure, la version d'Android. Ce taux varie en fonction de la taille du code à octet, et, dans de moindre mesure, la version d'Android.
Pour répondre à notre dernière recherche question, nous avons comparé le taux de finition entre les applications bénignes et les maliciels. Pour répondre à notre dernière recherche question, nous avons comparé le taux de terminaison entre les applications bénignes et les maliciels.
Les résultats semblent indiquer que les maliciels sont plus facilement analysés. Les résultats semblent indiquer que les maliciels sont plus facilement analysés.
Pour vérifier cette affirmation, nous avons comparé le taux de finition mais aussi la taille du code à octets des applications et effectivement, il semblerait que ce résultat soit vrai, y compris à taille égale. Pour vérifier cette affirmation, nous avons comparé le taux de terminaison mais aussi la taille du code à octets des applications et effectivement, il semblerait que ce résultat soit vrai, y compris à taille égale.
Nous avons donc une réponse à notre *RQ3*: Les maliciels causent moins d'erreurs lors de leur analyse par des outils d'analyse statique. Nous avons donc une réponse à notre *RQ3*: Les maliciels causent moins d'erreurs lors de leur analyse par des outils d'analyse statique.
Finalement, nous avons une réponse à notre première problématique: Finalement, nous avons une réponse à notre première problématique:
Plus de la moitié des outils sélectionnés ne sont plus utilisables. Plus de la moitié des outils sélectionnés ne sont plus utilisables.
Dans certains cas, cela est à notre incapacité à les installer correctement, mais majoritairement, cela est au faible taux de finition des outils lors de l'analyse des applications. Dans certains cas, cela est à notre incapacité à les installer correctement, mais majoritairement, cela est au faible taux de terminaison des outils lors de l'analyse des applications.
Nos résultats montrent que les applications avec beaucoup de code sont plus difficiles à analyser, et, en moindre mesure, la version d'Android ainsi que la malignité de l'application peut avoir un impact. Nos résultats montrent que les applications avec beaucoup de code sont plus difficiles à analyser, et, en moindre mesure, la version d'Android ainsi que la malignité de l'application peut avoir un impact.
] #[ ] #[
@ -370,7 +370,7 @@ Nos résultats montrent que les applications avec beaucoup de code sont plus dif
#import "../lib.typ": MWE #import "../lib.typ": MWE
#import "../4_class_loader/X_var.typ": * #import "../4_class_loader/X_var.typ": *
Dans ce chapitre, nous étudions comment Android gère le chargement de classe en présence de mutliples versions de la même classe. Dans ce chapitre, nous étudions comment Android gère le chargement de classe en présence de multiples versions de la même classe.
Nous modélisons l'algorithme de chargement de classe d'Android, et l'utilisons comme base pour une nouvelle famille de brouillage de code que nous appelons _masquage de classes_. Nous modélisons l'algorithme de chargement de classe d'Android, et l'utilisons comme base pour une nouvelle famille de brouillage de code que nous appelons _masquage de classes_.
Nous analysons ensuite des applications publiés en 2023 pour déterminer si cette technique de brouillage est actuellement utilisée. Nous analysons ensuite des applications publiés en 2023 pour déterminer si cette technique de brouillage est actuellement utilisée.
@ -394,15 +394,15 @@ Le premier `ClassLoader` utilisé par Android est `BootClassLoader`.
Cette classe est une classe singleton, ce qui signifie qu'il ne peut y avoir qu'une seule instance de la classe par application. Cette classe est une classe singleton, ce qui signifie qu'il ne peut y avoir qu'une seule instance de la classe par application.
Elle est utilisée pour charger les classes de plateforme. Elle est utilisée pour charger les classes de plateforme.
Ces classes sont les classes implémentées par Android et qui peuvent être utilisées par une application sans qu'elles ne soient présentes dans l'application. Ces classes sont les classes implémentées par Android et qui peuvent être utilisées par une application sans qu'elles ne soient présentes dans l'application.
Elles peuvent être séparées en deux catégories, les classes du KDL (Kit de Développement Logiciel) Android, et les classes de l'IPA cachée. Elles peuvent être séparées en deux catégories, les classes du KDL (Kit de Développement Logiciel) Android, et les classes de l'IPA (Interface de Programmation d'Application) cachée.
Les premières forment la librairie standard d'Android. Les premières forment la librairie standard d'Android.
Elles sont documentées et couramment utilisées par les développeurs. Elles sont documentées et couramment utilisées par les développeurs.
Les secondes sont des classes utilisées par Android en interne, mais que les applications ne sont pas supposées utiliser. Les secondes sont des classes utilisées par Android en interne, mais que les applications ne sont pas supposées utiliser.
Elles ne sont pas documentées, et depuis quelques années Android commence a faire des efforts pour empêcher les dévelopeurs de les utiliser. Elles ne sont pas documentées, et depuis quelques années Android commence à faire des efforts pour empêcher les dévelopeurs de les utiliser.
Elles sont toutefois encore utilisées, et, au moins jusqu'à présent, les mesures d'Android ne suffisent pas à les rendre innaccessibles. Elles sont toutefois encore utilisées, et, au moins jusqu'à présent, les mesures d'Android ne suffisent pas à les rendre inaccessibles.
Ce `BootClassLoader` est utilisé comme le parent par défaut par tous les `ClassLoader` définis dans les classes plateforme d'Android. Ce `BootClassLoader` est utilisé comme le parent par défaut par tous les `ClassLoader` définis dans les classes plateforme d'Android.
Quand le parent d'un `ClassLoader` n'est pas défini (quand sa valeur est nulle), les `ClassLoader` vont déléguer au `BootClassLoader` à la place. Quand le parent d'un `ClassLoader` n'est pas défini (quand sa valeur est nulle), les `ClassLoader` vont déléguer le chargement au `BootClassLoader` à la place.
L'autre type de `ClassLoader` utilisé par Android par défaut est le `PathClassLoader`. L'autre type de `ClassLoader` utilisé par Android par défaut est le `PathClassLoader`.
Cette classe est utilisée pour charger des classes stockées dans des fichiers. Cette classe est utilisée pour charger des classes stockées dans des fichiers.
Android en définit deux par défaut, un `PathClassLoader` "système", et un `PathClassLoader` pour l'application. Android en définit deux par défaut, un `PathClassLoader` "système", et un `PathClassLoader` pour l'application.
@ -425,7 +425,7 @@ Ensuite, les classes sont sélectionnées parmis les fichiers #DEX dans un ordre
Le premier fichier testé est `classes.dex`, suivi de `classes2.dex`, puis `classes3.dex` et ainsi de suite, jusqu'à ce qu'un fichier `classesX.dex` n'existe pas. Le premier fichier testé est `classes.dex`, suivi de `classes2.dex`, puis `classes3.dex` et ainsi de suite, jusqu'à ce qu'un fichier `classesX.dex` n'existe pas.
La limite au nombre de fichiers #DEX est très élevée ($2^64$ sur les téléphones actuels), tant que le fichier suivant existe et que la classe n'est pas trouvée, Android va continuer. La limite au nombre de fichiers #DEX est très élevée ($2^64$ sur les téléphones actuels), tant que le fichier suivant existe et que la classe n'est pas trouvée, Android va continuer.
Aussi, le code contenu fichier `classes100.dex` peut être utilisé par Android, ou non, par exemple si `classes99.dex` n'existe pas. Aussi, le code contenu fichier `classes100.dex` peut être utilisé par Android, ou non, par exemple si `classes99.dex` n'existe pas.
Plus surprenant, de code contenu dans un fichier `classes1.dex` ou `classes02.dex` ne serra pas utilisé. Plus surprenant, le code contenu dans un fichier `classes1.dex` ou `classes02.dex` ne sera pas utilisé.
Lors de l'analyse statique d'applications, ces deux points peuvent mener à des complications que nous allons maintenant explorer. Lors de l'analyse statique d'applications, ces deux points peuvent mener à des complications que nous allons maintenant explorer.
#figure( #figure(
@ -454,12 +454,12 @@ Lors de l'analyse statique d'applications, ces deux points peuvent mener à des
) <lst:algo-cl> ) <lst:algo-cl>
A partir de cet algorithme, nous avons mis au point plusieurs méthodes de brouillage de code que nous appelons _masquage de classe_: la classe utilisée est masquée par une autre implémentation fournie par le développeur. A partir de cet algorithme, nous avons mis au point plusieurs méthodes de brouillage de code que nous appelons _masquage de classe_: la classe utilisée est masquée par une autre implémentation fournie par le développeur.
Nous nous concentrons sur l'obfuscation statique, mais cette stratégie peut être étendue à une approche dynamiquement en utilsant différents chargeurs de classes. Nous nous concentrons sur l'obfuscation statique, mais cette stratégie peut être étendue à une approche dynamiquement en utilisant différents chargeurs de classes.
Nous proposons trois techniques dans cette catégorie: Nous proposons trois techniques dans cette catégorie:
/ Auto masquage: Ici, le développeur utilise le format multi-dex pour mettre plusieur implémentations différentes dans la même application. / Auto masquage: Ici, le développeur utilise le format multi-dex pour mettre plusieurs implémentations différentes dans la même application.
L'objectif est d'exploiter les divergences entre l'algorithme de chargement de classes d'Android et la façon dont les outils d'analyse selectionnent l'implémentation à utiliser. L'objectif est d'exploiter les divergences entre l'algorithme de chargement de classes d'Android et la façon dont les outils d'analyse selectionnent l'implémentation à utiliser.
De cette façon, la classe utlisée par Android ne sera pas celle analysée. De cette façon, la classe utilisée par Android ne sera pas celle analysée.
/ Masquage de KDL: Cette fois, le développeur inclut une implémentation pour une classe du KDL dans l'application. / Masquage de KDL: Cette fois, le développeur inclut une implémentation pour une classe du KDL dans l'application.
Un outil qui ne priorise pas les classes plateformes, ou ne les connaît pas, va alors utiliser une implémentation invalide de la classe pour son analyse. Un outil qui ne priorise pas les classes plateformes, ou ne les connaît pas, va alors utiliser une implémentation invalide de la classe pour son analyse.
/ Masquage d'IPA Cachée: L'idée est la même que pour la technique précédente, mais cette fois pour une classe de l'IPA caché. / Masquage d'IPA Cachée: L'idée est la même que pour la technique précédente, mais cette fois pour une classe de l'IPA caché.
@ -470,12 +470,12 @@ Le @tab:cl-resultats résume nos conclusions.
Jadx est un décompilateur d'application. Jadx est un décompilateur d'application.
Lorsqu'il est utilisé pour décompiler une application usant d'auto-masquage, il va sélectionner la mauvaise classe, mais indiquer en commentaire la liste des fichiers de code à octet contenant une implementation de la classe. Lorsqu'il est utilisé pour décompiler une application usant d'auto-masquage, il va sélectionner la mauvaise classe, mais indiquer en commentaire la liste des fichiers de code à octet contenant une implementation de la classe.
Apktool et Androguard listent toutes les classes de l'application, il revient donc à l'analyste de choisir la bonne implémentation, et pour les analyses plus poussées d'Androguard, Androguard choisit la mauvaise classe. Apktool et Androguard listent toutes les classes de l'application, il revient donc à l'analyste de choisir la bonne implémentation, et pour les analyses plus poussées d'Androguard, Androguard choisit la mauvaise classe.
Aucun de ces trois outils n'indiquent en aucune façon qu'une classes est déjà définie dans le KDL ou les IPA cachés. Aucun de ces trois outils n'indiquent en aucune façon qu'une classe est déjà définie dans le KDL ou les IPA cachés.
Flowdroid en revanche est capable de détecter les flux de données passant par des classes du KDL, y compris en présence d'une réimplémentation dans l'application. Flowdroid en revanche est capable de détecter les flux de données passant par des classes du KDL, y compris en présence d'une réimplémentation dans l'application.
Ce n'est par contre pas le cas pour les classes d'IPA cachées. Ce n'est par contre pas le cas pour les classes d'IPA cachées.
Il est intéressant de noter que Soot, la librairie sur laquelle est basé Flowdroid, a bien un algorithme qui priorise les fichers #DEX, et que cet algorithme est très proche de celui d'Android. Il est intéressant de noter que Soot, la librairie sur laquelle est basé Flowdroid, a bien un algorithme qui priorise les fichers #DEX, et que cet algorithme est très proche de celui d'Android.
Toutefois, les fichiers commençant par `classes` sont ensuite priorisés par ordre alphabétique. Toutefois, les fichiers commençant par `classes` sont ensuite priorisés par ordre alphabétique.
Cela signifie que les classes contenuent dans `classes0.dex`, `classes02.dex` ou `classes10.dex` sont priorisées sur celles de `classes2.dex`. Cela signifie que les classes contenues dans `classes0.dex`, `classes02.dex` ou `classes10.dex` sont priorisées sur celles de `classes2.dex`.
Ce problème est hérité par Flowdroid, ce qui le rend sensible à la technique d'auto-masquage. Ce problème est hérité par Flowdroid, ce qui le rend sensible à la technique d'auto-masquage.
#figure({ #figure({
@ -510,14 +510,14 @@ Ce problème est hérité par Flowdroid, ce qui le rend sensible à la technique
caption: [Résultats des techniques de masquage contre des outils d'analyse statique] caption: [Résultats des techniques de masquage contre des outils d'analyse statique]
) <tab:cl-resultats> ) <tab:cl-resultats>
Pour savoir si ces techniques sont utilisées dans la nature, nous avont scanné #nbapk applications publiées entre janvier 2023 et 2024. Pour savoir si ces techniques sont utilisées dans la nature, nous avons scanné #nbapk applications publiées entre janvier 2023 et 2024.
Pour vérifier que les différentes implémentations sont bien distinctes, nous comparons la représentation smali du code à octets des méthodes. Pour vérifier que les différentes implémentations sont bien distinctes, nous comparons la représentation smali (le langage assembleur pour le format Dalvik) du code à octets des méthodes.
Le @tab:cl-masquage résume ces résultats. La @tab:cl-masquage résume ces résultats.
Il est notable qu'un nombre important d'applications (#scan_only_shadow.at(1).ratioapp%) ont au moins un cas de masquage. Il est notable qu'un nombre important d'applications (#scan_only_shadow.at(1).ratioapp%) ont au moins un cas de masquage.
En étudiant en détail, nous avons noté que la majorité des classes concernées sont des classes introduites entre la version minimale et la version cible d'Android pour l'application. En étudiant en détail, nous avons noté que la majorité des classes concernées sont des classes introduites entre la version minimale et la version cible d'Android pour l'application.
Cela laisse entendre que ces classes ont été rajoutées pour permettre à l'application de fonctionner avec les versions d'Android ces classes n'existent pas. Cela laisse entendre que ces classes ont été rajoutées pour permettre à l'application de fonctionner avec les versions d'Android ces classes n'existent pas.
Le taux élevé de code identique pour les cas d'auto-masquage semble également pointer vers des erreurs lors de la compilation de l'application. Le taux élevé de code identique pour les cas d'auto-masquage semble également pointer vers des erreurs lors de la compilation de l'application.
De plus, l'analyse manuelle des cas le smali diffère montre que les différences viennent de détails lors de la compilation (par exemple, l'inversion de deux registres, ce qui n'as aucun effet sur l'exécution du code). De plus, l'analyse manuelle des cas le smali diffère montre que les différences viennent de détails lors de la compilation (par exemple, l'inversion de deux registres, ce qui n'a aucun effet sur l'exécution du code).
#figure({ #figure({
show table: set text(size: 0.80em) show table: set text(size: 0.80em)
@ -594,16 +594,16 @@ Avec l'algorithme décrit par le @lst:algo-cl, cela répond à notre seconde pro
#import "../5_theseus/X_var.typ": * #import "../5_theseus/X_var.typ": *
Dans ce dernier chapitre, nous nous penchons sur la question de comment permettre aux outils d'analyse statique d'accéder à des résultats dynamiques. Dans ce dernier chapitre, nous nous penchons sur la question de comment permettre aux outils d'analyse statique d'accéder à des résultats dynamiques.
Des contributions précédentes ont encodé leur résulat dans l'application elle-même pour transmettre leurs résultats à d'autres outils. Des contributions précédentes ont encodé leur résulats dans l'application elle-même pour transmettre leurs résultats à d'autres outils.
Nous allons utiliser cette approche pour permettre à des outils d'analyse statique d'analyser le comportement d'applications utilisant de la réflexion ou du chargement de code dynamique. Nous allons utiliser cette approche pour permettre à des outils d'analyse statique d'analyser le comportement d'applications utilisant de la réflexion ou du chargement de code dynamique.
Premièrement, il nous faut définir la transformation que nous voulons effectuer. Premièrement, il nous faut définir la transformation que nous voulons effectuer.
Concernant la réflexion, il y a 3 méthodes permettant d'appeler des méthodes arbitraires dans Android. Concernant la réflexion, il y a 3 méthodes permettant d'appeler des méthodes arbitraires dans Android.
`Class.newInstance()` et `Constructor.newInstance()` permettent d'instancier un nouvel object et d'appeler l'un des ses constructeurs, tandis que `Method.invoke()` permet d'appeler une méthode. `Class.newInstance()` et `Constructor.newInstance()` permettent d'instancier un nouvel object et d'appeler l'un des ses constructeurs, tandis que `Method.invoke()` permet d'appeler une méthode.
Les objects `Class`, `Constructor` ou `Method` utilisés pour appeler ces méthodes peuvent être obtenus de multiples façons différentes. Les objects `Class`, `Constructor` ou `Method` utilisés pour appeler ces méthodes peuvent être obtenus de multiples façons.
Nous n'allons donc pas chercher à modifier le code obtenant ces objets. Nous n'allons donc pas chercher à modifier le code obtenant ces objets.
#à-maj la place, nous allons nous concentrer sur l'appel des méthodes. #à-maj la place, nous allons nous concentrer sur l'appel des méthodes.
#à-maj différents moments de l'exécution, un même site peut appeler différentes méthodes. #à-maj différents moments de l'exécution, une même instruction appelant `Method.invoke()` peut appeler différentes méthodes.
De plus, la collection des informations de réflexion ne sera jamais parfaite: il y a des situations on ne peut jamais être certain d'avoir la liste complète des méthodes appelées. De plus, la collection des informations de réflexion ne sera jamais parfaite: il y a des situations on ne peut jamais être certain d'avoir la liste complète des méthodes appelées.
Par exemple, on peut imaginer une application qui appelle par réflexion une méthode dont le nom est obtenu depuis un serveur distant. Par exemple, on peut imaginer une application qui appelle par réflexion une méthode dont le nom est obtenu depuis un serveur distant.
Dans ce cas, sans accès au code du serveur il est impossible d'avoir la liste exhaustive des méthodes qui peuvent être utilisées. Dans ce cas, sans accès au code du serveur il est impossible d'avoir la liste exhaustive des méthodes qui peuvent être utilisées.
@ -615,10 +615,10 @@ Ainsi, le comportement de l'application est conservé.
Pour le chargement de code dynamique, nous avons conclu qu'il n'est pas nécessaire de modifier le code. Pour le chargement de code dynamique, nous avons conclu qu'il n'est pas nécessaire de modifier le code.
A la place, nous pouvons directement ajouter à l'application le ficher #DEX en utilisant le format multi-dex. A la place, nous pouvons directement ajouter à l'application le ficher #DEX en utilisant le format multi-dex.
Toutefois, si jamais certaines classes contenues dans le code que nous injectons sont déja présentes dans l'application, nous renommons la classes et ses références de sorte à reproduire statiquement le comportement de l'algorithme de chargement de classe d'Android. Toutefois, si jamais certaines classes contenues dans le code que nous injectons sont déja présentes dans l'application, nous renommons la classe et ses références de sorte à reproduire statiquement le comportement de l'algorithme de chargement de classe d'Android.
Cette approche a des limites, en particulier lors d'appel réflexifs, car il n'existe pas de solutions pour comparer les chargeurs de classes avec une valeur statique. Cette approche a des limites, en particulier lors d'appel réflexifs, car il n'existe pas de solutions pour comparer les chargeurs de classes avec une valeur statique.
Si un même site d'appel réflexif appelle deux méthodes avec des signatures et noms identiques mais associées à des classes provenant de chargeurs de classes différents, nous ne sommes pas en messure de reproduire exactement le même comportement statiquement. Si un même site d'appel réflexif appelle deux méthodes avec des signatures et noms identiques mais associées à des classes provenant de chargeurs de classes différents, nous ne sommes pas en mesure de reproduire exactement le même comportement statiquement.
Toutefois, les appels aux deux différentes méthodes apparaissent bien dans la nouvelle application, ce qui devrait permettre aux outils d'analyse statique de considérer les deux cas possible. Toutefois, les appels aux deux différentes méthodes apparaissent bien dans la nouvelle application, ce qui devrait permettre aux outils d'analyse statique de considérer les deux cas possibles.
Pour pouvoir effectuer ces transformations, il nous faut certaines informations. Pour pouvoir effectuer ces transformations, il nous faut certaines informations.
Les noms, signature et chargeur de classes des méthodes appelées par réflexion, ainsi que la position exacte du site de l'appel réflexif, et le code à octets chargé dynamiquement. Les noms, signature et chargeur de classes des méthodes appelées par réflexion, ainsi que la position exacte du site de l'appel réflexif, et le code à octets chargé dynamiquement.
@ -630,16 +630,16 @@ Ces méthodes sont les dernières méthodes appelées dans l'environement Java a
Pour aider à l'exploration des applications, nous avons réutilisé une partie de GroddDroid, un outil dédié à l'exploration dynamique d'applications. Pour aider à l'exploration des applications, nous avons réutilisé une partie de GroddDroid, un outil dédié à l'exploration dynamique d'applications.
Nous avons lancé notre analyse statique sur les #num(5000) applications publiées en 2023 du jeu d'applications RASTA. Nous avons lancé notre analyse statique sur les #num(5000) applications publiées en 2023 du jeu d'applications RASTA.
Malheureusement, les résultats semble indiquer que notre environnement d'exécution est insuffisant et que beaucoup d'applications n'ont pas été visitées correctement. Malheureusement, les résultats semblent indiquer que notre environnement d'exécution est insuffisant et que beaucoup d'applications n'ont pas été visitées correctement.
Malgrés tout, nous avons collecté #nb_bytecode_collected fichiers de code à octets. Malgré tout, nous avons collecté #nb_bytecode_collected fichiers de code à octets.
Toutefois, une fois comparé, nous remarquons que parmi ces fichiers, il n'y a que #num(bytecode_hashes.len()) fichiers distincts. Toutefois, une fois comparé, nous remarquons que parmi ces fichiers, il n'y a que #num(bytecode_hashes.len()) fichiers distincts.
L'inspection du contenu montre que ces fichiers sont principalement des librairies de code publicitaire ou analytiques. L'inspection du contenu montre que ces fichiers sont principalement des librairies de code publicitaire ou analytiques.
Seuls #num(nb_bytecode_collected - nb_google - nb_appsflyer - nb_facebook) fichiers parmi les #nb_bytecode_collected collectés ne proviennent ni de Google, ni de Facebook, ni de AppsFlyer. Seuls #num(nb_bytecode_collected - nb_google - nb_appsflyer - nb_facebook) fichiers parmi les #nb_bytecode_collected collectés ne proviennent ni de Google, ni de Facebook, ni de AppsFlyer.
Ces fichiers restants contiennent du code spécifique aux applications les utilisant, principalement des applications exigeant un niveau important de sécurité comme des applications banquaires ou d'assurance santé. Ces fichiers restants contiennent du code spécifique aux applications les utilisant, principalement des applications exigeant un niveau important de sécurité comme des applications bancaires ou d'assurance santé.
La @tab:th-comparaison-graph-appel montre le nombre d'arcs du graphe d'appel de fonction de ces quelques applications qui chargent du code spécifique à leurs usage dynamiquement. La @tab:th-comparaison-graph-appel montre le nombre d'arcs du graphe d'appel de fonction de ces quelques applications qui chargent du code spécifique à leur usage dynamiquement.
La colonne "Réflection Ajoutées" correspond au nombre d'appels reflectifs ajoutés a l'application. La colonne "Réflexion Ajoutées" correspond au nombre d'appels réflexifs ajoutés à l'application.
Les autres arcs ajoutés sont soit des fonctions "colle" que nous avont ajoutées a l'application pour choisir la bonne méthode à appeler reflectivement, soit des méthodes appelées par du code chargé dynamiquement auquel Androguard n'avait pas accès avant l'instrumentation. Les autres arcs ajoutés sont soit des fonctions "colle" que nous avons ajoutées à l'application pour choisir la bonne méthode à appeler reflexivement, soit des méthodes appelées par du code chargé dynamiquement auquel Androguard n'avait pas accès avant l'instrumentation.
On peut voir que notre méthode permet à Androguard de calculer un plus grand graphe. On peut voir que notre méthode permet à Androguard de calculer un plus grand graphe.
#figure({ #figure({
@ -651,7 +651,7 @@ On peut voir que notre méthode permet à Androguard de calculer un plus grand g
table.hline(), table.hline(),
table.header( table.header(
//[SHA 256], [Original CG edges], [New CG edges], [Edges added], [Reflection edges added], //[SHA 256], [Original CG edges], [New CG edges], [Edges added], [Reflection edges added],
table.cell(rowspan: 2)[#APK SHA 256], table.cell(colspan: nb_col - 1)[Nombre d'arcs du graphe d'appel], [Avant], [Après], [Différences], [Réflection Ajoutées], table.cell(rowspan: 2)[#APK SHA 256], table.cell(colspan: nb_col - 1)[Nombre d'arcs du graphe d'appel], [Avant], [Après], [Différences], [Réflexion Ajoutées],
), ),
table.hline(), table.hline(),
..compared_callgraph.map( ..compared_callgraph.map(
@ -669,12 +669,12 @@ On peut voir que notre méthode permet à Androguard de calculer un plus grand g
caption: [Arcs ajoutés aux graphes d'appel de fonctions des applications instrumentées, calculé par Androguard] caption: [Arcs ajoutés aux graphes d'appel de fonctions des applications instrumentées, calculé par Androguard]
) <tab:th-comparaison-graph-appel> ) <tab:th-comparaison-graph-appel>
Nous avons ensuite modifié les applications comme décrit précédemment, puis relancé les outils de notre première contribution sur les applications modifiées pour comparer leur taux de finition au taux sur les applications initiales. Nous avons ensuite modifié les applications comme décrit précédemment, puis relancé les outils de notre première contribution sur les applications modifiées pour comparer leur taux de terminaison au taux sur les applications initiales.
En fonction des outils, le taux de finition est soit inchangé, soit légèrement plus faible pour les applications modifiées. En fonction des outils, le taux de terminaison est soit inchangé, soit légèrement plus faible pour les applications modifiées.
Pour vérifier que notre approche fonctionne, nous avons créé une petite application de test utilisant du chargement dynamique et des appels réflexifs. Pour vérifier que notre approche fonctionne, nous avons créé une petite application de test utilisant du chargement dynamique et des appels réflexifs.
@fig:th-demo-avant montre la classe principale de l'application. @fig:th-demo-avant montre la classe principale de l'application.
On peut voir par exemple que l'application utilise des chaines de caractères chiffrées pour stocker le nom des méthodes à appeler. On peut voir par exemple que l'application utilise des chaînes de caractères chiffrées pour stocker le nom des méthodes à appeler.
#figure( #figure(
```java ```java
@ -731,11 +731,11 @@ De plus, la classe `Malicious` qui n'était pas présente dans l'application ori
)<fig:th-demo-apres> )<fig:th-demo-apres>
Dans le code de `Malicious`, `get_data()` retourne des données d'une source d'information sensible, et `send_data()` exfiltre les données qui lui sont passées. Dans le code de `Malicious`, `get_data()` retourne des données d'une source d'information sensible, et `send_data()` exfiltre les données qui lui sont passées.
Une fuite d'information devrait donc être détecté par Flowdroid. Une fuite d'information devrait donc être détectée par Flowdroid.
Lancé sur l'application originale, Flowdroid calcule un graphe d'appel de méthodes contenant 43 arcs, et ne détecte aucune fuite. Lancé sur l'application originale, Flowdroid calcule un graphe d'appel de méthodes contenant 43 arcs, et ne détecte aucune fuite.
En revanche, lancé sur l'application modifiée, Flowdroid calcule cette fois un graphe de 76 arsc, et détecte bien la fuite de données. En revanche, lancé sur l'application modifiée, Flowdroid calcule cette fois un graphe de 76 arsc, et détecte bien la fuite de données.
Bien que nous n'ayons pas pu tester notre approche correctement à grande échelle aux limites de notre environnement d'analyse statique, nous avons bien montré qu'il est possible de transmettre des informations dynamiques à des outils d'analyse statique pour améliorer leurs résultat. Bien que nous n'ayons pas pu tester notre approche correctement à grande échelle aux limites de notre environnement d'analyse statique, nous avons bien montré qu'il est possible de transmettre des informations dynamiques à des outils d'analyse statique pour améliorer leurs résultats.
] /*#[ ] /*#[