diff --git a/0_preamble/french_summary.typ b/0_preamble/french_summary.typ index e531239..d0672bb 100644 --- a/0_preamble/french_summary.typ +++ b/0_preamble/french_summary.typ @@ -1,5 +1,6 @@ -#import "../lib.typ": epigraph, APK, pb1-text-fr, pb2-text-fr, pb3-text-fr, eg, etal, APKs, DEX, todo +#import "../lib.typ": epigraph, APK, pb1-text-fr, pb2-text-fr, pb3-text-fr, eg, etal, APKs, DEX, todo, num +#show figure.where(kind: raw): set figure(supplement: [Code]) #let mp = text(font: "libertinus serif", sym.dot.c) = Résumé en Français @@ -15,14 +16,14 @@ Ce processus est appelé l'ingénierie inverse. Beaucoup de travail à été fait dans ce domaine pour les programmes d'ordinateur. Toutefois, les applications Android présentent leur propres difficultés. -Par example, les applications sont distribué dans leur format spécifique, le format #APK, et le code des applications est lui même compilé dans un format de code à octets spécifique à Android: Dalvik. +Par exemple, les applications sont distribué dans leur format spécifique, le format #APK, et le code des applications est lui même compilé dans un format de code à octets spécifique à Android: Dalvik. La première difficulté pour l'ingénieur#mp;e inverse est donc d'avoir des outils qui comprennent les formats utilisés par Android. Dans le processus d'analyse, une première étape serait alors de lire le contenu de l'application. Des outils comme Apktool peuvent être utilisé pour convertir les fichiers binaire de l'application dans une version lisible par un#mp;e humain#mp;e. D'autres comme Jadx essaient de générer le code source Java depuis le code à octets. Toutefois, les applications Android peuvent être trés grossent et il n'est pas toujours possible de les analyser manuellement. D'autres outils ont été développer pour extraire une représentation plus haut niveau du contenu de l'application. -Par example, Flowdroid a pour objectif de détecter les fuites d'informations: l'utilisateur#mp;ice définit une liste de méthodes qui génèrent des informations sensbiles, et une liste de méthodes qui exfiltrent des informations vers l'extérieur. +Par exemple, Flowdroid a pour objectif de détecter les fuites d'informations: l'utilisateur#mp;ice définit une liste de méthodes qui génèrent des informations sensbiles, et une liste de méthodes qui exfiltrent des informations vers l'extérieur. Flowdroid va alors calculer si il existe des chemins dans l'application permettant de relier des méthodes de la première catégorie avec des méthodes de la seconde. Malheureusement, ces outils sont difficile a utiliser, et même si ils fonctionnent sur des applications simples construitent dans le but de tester les outils, il n'est pas rare que ces outils échouent sur de vrais applications. @@ -257,7 +258,7 @@ De plus pour les outils que nous avons peu lancer, #resultratio des analyses ont wognsen_et_al: 75% finished, 1% failed, the rest timed out " ), - caption: [Taux de Finition pour le jeu d'applications Drebin], + caption: [Taux de finition pour le jeu d'applications Drebin], ) #figure( @@ -298,17 +299,17 @@ Le @fig:rasta-exit-evolution-java-fr montre cette évolution pour les outils cod On peut noter une tendance général où le taux de finition diminu avec le temps. Plusieurs facteurs peuvent être responsable. -Par example, la librairie standard d'Android et le format des applications à évolué avec les versions d'Android. +Par exemple, la librairie standard d'Android et le format des applications à évolué avec les versions d'Android. Un autre changement notable est la taille du code à octets des applications. Les applications les plus récentes ont notablement plus de code. Plusieurs facteurs peuvent être responsable. -Par example, la librairie standard d'Android et le format des applications à évolué avec les versions d'Android. +Par exemple, la librairie standard d'Android et le format des applications à évolué avec les versions d'Android. Un autre changement notable est la taille du code à octets des applications. Les applications les plus récentes ont notablement plus de code. Pour déterminer le facteur qui influence le plus le taux de finitions, selectionné des sous-ensembles de Rasta avec certains de ces paramètres fixés. -Par example, nous avons tracé l'évolution du taux de finition en fonction de l'année de plublication 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 finition en fonction de l'année de plublication des applications sur l'ensemble des applications dont le code à octets fait entre 4.08 et 5.2 Mo. #figure( image( @@ -330,16 +331,14 @@ Pour vérifier cette affirmation, nous avons comparé le taux de finition mais a Nous avons donc une réponse a notre *RQ3*: Les Maliciels cause moins d'erreures lors de leur analyse par des outils d'analyse statique. -Finalement, nous avons une réponde à notre première problématique. - -#pb1-text-fr +Finalement, nous avons une réponde à notre première problématique: Plus de la moitié des outils sélectionnés ne sont plus utilisables. Dans certains cas, c'est due à notre incapicibilité à les installer correctement, mais majoritairement, c'est due au failbe taux de finition des outils lors de l'analyse des applications. Nos résultats montre que les applications avec beaucoup de code sont plus difficile a analyser, et, en moindre mesure, la version d'Android ainsi que la malignité de l'application peut avoir un impact. -] -#[ +] #[ + == Chargeurs de classes au milieu: Dérouter les analyseur static pour Android #import "../lib.typ": MWE @@ -400,7 +399,7 @@ Cela peut sembler évidant pour les classes courantes comme `String`, mais il f Ensuite, les classes sont sélectionné parmis les fichiers #DEX dans un ordre non triviale, et s'arrête a la première implémentation trouvé. Le premier fichier testé est `classes.dex`, suivit 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é ($2^64$ sur les téléphones actuels), tant que le fichier suivant existe et que la classe n'est pas trouvé, Android va continuer. -Aussi, le code contenu fichier `classes100.dex` peut être utilisé par Android, ou non, par example 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é. Lors de l'analyse statique d'applications, ces deux points peuvent mener à des complications que nous allons maintenant explorer. @@ -429,12 +428,267 @@ Lors de l'analyse statique d'applications, ces deux points peuvent mener à des ```, caption: [Algorithme de chargement de class par défaut pour les applications Android], ) -] +A partir de cette algorithme, nous avons mis au point plusieur méthodes de brouillage de code que nous appelons _masquage de classe_: la classe utilisé est masqué par une autre implémentation fournis par le dévellopeur. +Nous nous concentrons sur l'obfuscation statique, mais cette stratégie peut être étendu a une approche dynamiquement en utilsant différent chargeur de classes. +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. + 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 selection l'implémentation à utiliser. + De cette façon, la classe utlisé par Android ne sera pas celle analysé. +/ Masquage de KDL: Cette fois, le déveloippeur inclus une implémentation pour une classe de du KDL dans l'application. + Un outils qui ne priorise pas les classes platformes, ou ne les connais 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é. + Nous distingons masquage de KDL et masquage d'IPA caché car les IPA cachés n'étant pas documenté, il est possible que des outils soient capable de résoudre la première technique mais pas la deuxième. + +Nous avons vérifié l'impacte de ses techniques sur 4 outils d'analyse Android courant: Jadx, Apktool, Androguard et Flowdroid. +Le @tab:cl-resultats résume nos conclusions. +Jadx est un décompillateur d'application. +Lorsqu'il est utilisé pour décompiler une application usant d'auto-masquage, il va selectionner 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'analiste de choisir la bonne implémentation, et pour les analyses plus poussé d'Androguard, Androguard choisit la mauvaise classe. +Aucun de ses trois outils n'indiquent en aucune façon qu'une classes est déjà définit dans le KDL ou les IPA cachées. +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. +Il est intérescant de noter est que Soot, la librairie sur laquelle est basé Flowdroid, à bien un algorithme qui priorise les fichers #DEX, et que cette algorithme est très proche de celuis d'Android. +Toutefois, les fichiers commancant par `classes` sont ensuite priorisé par ordre alpha-numérique. +Cela signifie que les classes contenuent dans `classses0.dex`, `classes02.dex` ou `classes10.dex` sont priorisé sur celles de `classes2.dex`. +Ce problème est hérité par Flowdroid, ce qui le rend sensible a la technique d'auto-masquage. + +#figure({ + table( + columns: 5, + stroke: none, + align:(left+horizon, center+horizon, center+horizon, center+horizon, center+horizon), + table.hline(), + table.header( + table.cell(colspan: 5, inset: 3pt)[], + table.cell(rowspan: 2)[Outil], + table.cell(rowspan: 2)[Version], + table.vline(end: 3), + table.vline(start: 4), + table.cell(colspan: 3)[Masquage], + [Auto], [KDL], [Cachée], + ), + table.cell(colspan: 5, inset: 3pt)[], + table.hline(), + table.cell(colspan: 5, inset: 3pt)[], + + [Jadx], [1.5.0], [#warn], [#ok], [#ok], + [Apktool], [2.9.3], [#warn], [#ok], [#ok], + [Androguard], [4.1.2], [#warn], [#ok], [#ok], + [Flowdroid], [2.13.0], [#ok], [#ko], [#ok], + + table.cell(colspan: 5, inset: 3pt)[], + table.hline(), + ) + [#ok: Le masquage fonctionne \ #warn: Le masquage fonctionne, mais un avertissement est émis ou les plusieurs classes sont visibles \ #ko: Le masquage ne marche pas] + }, + caption: [Résultats des techniques de masquage contre des outils d'analyse statique] +) + +Pour savoir si ces techniques sont utilisées dans la nature, nous avont scanné #nbapk applications publiées entre janvier 2023 et 2024. +Pour vérifier que les différentes implémentations sont bien distinctes, nous comparont la représentation smali du code à octets des méthodes. +Le @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. +En étudiant en détail, nous avons noté que la majorité des classes consernées sont des classes introduit entre la version minimal et la version cible d'Android pour l'application. +Cela laisse entendre que ces classes ont été rajouté pour permettre a l'application de fonctionner avec les version d'Android où ces classes n'existe pas. +Le taux élevé de code identique pour les cas d'auto masquage semble également pointé vers des erreures lors de la compilation de l'application. +De plus, l'analyse manuelle des cas où le smalli diffère montre que les différences vienne des détails lors de la compilation (par exemple, l'inversion de deux registre, ce qui n'as aucune impacte sur l'execution du code). + +#figure({ + show table: set text(size: 0.80em) + + show "Self": "Auto" + show "Sdk": "KDL" + show "Hidden": "Cachées" + show "Total": "Totale" + + table( + columns: 9, + stroke: none, + align: center+horizon, + inset: (x: 0% + 5pt, y: 0% + 2pt), + table.hline(), + table.header( + table.cell(colspan: 9, inset: 3pt)[], + [], + table.vline(end: 3), + table.vline(start: 4), + table.cell(colspan: 3)[*Nombre d'app*], + table.vline(end: 3), + table.vline(start: 4), + table.cell(colspan: 4)[*Moyenne*], + table.vline(end: 3), + table.vline(start: 4), + table.cell(rowspan: 2)[*Code \ Identique*], + + [], + [], [*%*], [*% maliciel*], + [*Classes Masqués*], [*Médianne*], [*KDL*], [*Min KDL*], + + ), + table.cell(colspan: 9, inset: 3pt)[], + table.hline(), + table.cell(colspan: 9)[Pour toutes les applications du jeu], + table.hline(), + table.cell(colspan: 9, inset: 3pt)[], + + ..scan_50k.map(e => ( + [*#e.method*], + num(e.nbapp), [#e.ratioapp%], [#e.ratiomal%], + num(e.avgshadow), num(e.median), num(e.avgtargetsdk), num(e.avgminsdk), + [#e.id%] + )).flatten(), + + table.cell(colspan: 9, inset: 3pt)[], + table.hline(), + table.cell(colspan: 9)[Pour les applications avec au moins 1 cas de masquage], + table.hline(), + table.cell(colspan: 9, inset: 3pt)[], + + ..scan_only_shadow.map(e => ( + [*#e.method*], + num(e.nbapp), [#e.ratioapp%], [#e.ratiomal%], + num(e.avgshadow), num(e.median), num(e.avgtargetsdk), num(e.avgminsdk), + [#e.id%] + )).flatten(), + + table.cell(colspan: 9, inset: 3pt)[], + table.hline(), + )}, + caption: [Classes masqués comparées aux classes platform d'Android IPA 34 pour un jeu de #nbapk applications] +) + +Notre conclusion est que le masquage de classes n'est pas activement exploité pour le brouillage de code. +En revenche, cette situation occure naturellement dans les applications. +Il est donc important pour les outils d'analyses de modéliser correctement le processus de chargement de classes. +Avec l'algorithme décrit par le @lst:algo-cl, cela réponde a notre seconde problématique. + +] #[ == L'Application de Thésée: Même après avoir ajouté les informations d'exécution, c'est toujours votre application +#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. +Des contributions précédentes ont encodé leur résulat dans l'application elle même pour transmétre leurs résultats à d'autres outils. +Nous allons utiliser cette approche pour permétre à des applications d'analyse statique d'analyser le comportement d'application utilisant de la reflection ou du chargement de code dynamique. + +Premièrement, il nous faut définir la transformation que nous voulons effectuer. +Concernant la réflection, il y a 3 méthodes permettant d'appeler des méthodes arbitraire 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. +Les objects `Class`, `Constructor` ou `Method` utilisés pour appeler ces méthodes peuvent être obtenu de multiple façon différente. +Nous n'allons donc pas chercher à modifier le code obtenant ces objects. +A la place, nous allons nous concentrer sur l'appel des méthodes. +A différent moment de l'exécution, un même site peut appeler différentes méthode. +De plus, la collection des informations de reflection sera toujours au meilleur effort, il y a des situations où on ne peut jamais être certain d'avoir la liste complète des méthodes appelés. +Par exemple, on peut imaginer une application qui appel par réflection une méthode don le nom est obtenue depuis un serveur distant. +Dans ce cas, sans accès au code du serveur il est impossible d'avoir la liste exaustive des méthodes qui peuvent être utilisé. +Pour prendre en compte ces deux cas, nous allons remplacer les appels par des blocs conditionnels. +Pour chaque méthode dont on sait qu'elle peut être appelé, nous testons si l'object `Method ` correspond a cette méthode en comparant son nom et sa signature. +Si c'est le cas, la méthode est appelé dans le bloc avec l'instruction Dalvik approrié. +Si la méthode ne correspond à aucune méthodes connus, alors l'appel est fait par reflection. +Ainsi, le comportement de l'application est conservé. + +Pour le chargement de code dynamique, nous avons conclus qu'il n'est pas nécessaire de modifier le code. +A la place, nous pouvons directement ajouter a l'application le ficher #DEX en utilisant le format multi-dex. +Toutefois, si jamais certaines classes contenus dans le code que nous injecton sont déja présent dans l'application, nous renommons la classes et ses références de sorte a reproduire statiquement le comportement de l'algorithme de chargement de classe d'Android. +Cette approche a des limites, en particulier lors d'appel reflexifs, car il n'existe pas de solutions pour comparer les chargeurs de classes avec une valeur statique. +Si un même site d'appel reflexif appel deux méthodes avec des signatures et nom identiques mais associées à des classes provenant de chargeurs de classes différent, nous ne somme pas en messure de reproduire exactement le même comportement statiquement. +Toutefois, les deux l'appels aux méthodes apparaissent bien dans la nouvelle application, ce qui devrais permettre aux outils d'analyse statique de considérer les deux cas possible. + +Pour pouvois effectuer ces transformations, il nous faut certaines information. +Les noms, signature et chargeur de classes des méthodes appelés par reflections, ainsi la position exacte du site de l'appel reflexif, et le code à octets chargé dynamiquement. +Pour obtenir ces informations, nous utilison Frida, un outils permettant d'injectet des scripts dans les méthodes exécuter pendant l'exécution d'une application Android. +Nous avons choisis d'injected nos scripts dans les méthodes de classes platformes d'Android. +Pour la reflection, nous avons bien entendu instrumenté `Class.newInstance()`, `Cconstructor.newInstance()` et `Method.invoke()`. +Pour le chargement de code, le choix est un peu moins évidant, car il existe de multiples façon de charger du code à octets. +Nous avons finalement choisit `DexFile.openInMemoryDexFileNative()` et `DexFile.openDexFileNative()`, des méthodes de l'IPA cachée. +Ces méthodes sont les dernières méthodes appelé dans l'environement Java avant de passer en native pour charger analyser en charger le code à octets. +Pour aider à l'exploration des applications, nous avons réutiliser une parti de GroddDroid, un outils dédier a l'exploration dynamique d'applications. + +Nous avons lancé notre analyse statique sur les #num(5000) applications de jeu d'application Rasta publiés en 2023. +Malheureusement, les résultats semble indiquer que notre environment d'exécution est insufisant et que beaucoup d'applications n'on pas été visité correctement. +Malgrés tout, nous avons collecté #nb_bytecode_collected fichiers de code à octets. +Toutefois, une fois comparé, nous remarquons que parmis 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 analitiques. +Seul #num(nb_bytecode_collected - nb_google - nb_appsflyer - nb_facebook) fichiers parmis les #nb_bytecode_collected collectés ne proviennent ni de Google, ni de Facebook, ni de AppsFlyer. +Ces fichiers restant contiennent du code spécifique aux applications les utilisants, principalement des applications exigeant un niveau important de sécurité comme des applications banquaire ou d'assurance santé. + +Nous avons ensuite relancé les outils de notre première contribution sur les applications modifiés pour comparer leur taux de finition comparé à taux sur les applications initials. +En fonction des outils, le taux de finition est soit inchangé, soit légèrement plus faible pour les applications modifiées (a l'exeption de Saaf #todo[expliquer saaf] +) + +Pour vérifier que notre approche fonctionne, nous avons créé une petite application de test utilsant du chargement dynamique et des appels réflexifs. +@fig:th-demo-avant montre la classe principale de l'application. +On peut voir par exemple que que l'application utilise des chaines de caractères chiffrés pour stocker le noms des méthodes à appeler. + +#figure( + ```java +package com.example.theseus; + +public class Main { + private static final String DEX = "ZGV4CjA [...] EAAABEAwAA"; + Activity ac; + private Key key = new SecretKeySpec("_-_Secret Key_-_".getBytes(), "AES"); + ClassLoader cl = new InMemoryDexClassLoader(ByteBuffer.wrap(Base64.decode(DEX, 2)), Main.class.getClassLoader()); + + public void main() throws Exception { + String[] strArr = {"n6WGYJzjDrUvR9cYljlNlw==", "dapES0wl/iFIPuMnH3fh7g=="}; + Class loadClass = this.cl.loadClass(decrypt("W5f3xRf3wCSYcYG7ckYGR5xuuESDZ2NcDUzGxsq3sls=")); + Object obj = "imei"; + for (int i = 0; i < 2; i++) { + obj = loadClass.getMethod(decrypt(strArr[i]), String.class, Activity.class).invoke(null, obj, this.ac); + } + } + public String decrypt(String str) throws Exception { + Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding"); + cipher.init(2, this.key); + return new String(cipher.doFinal(Base64.decode(str, 2))); + } + + ... +} + ```, + caption: [Code de la classe principale de l'application calculé par Jadx, avant modification], +) + +Après avoir lancer notre analyse statique et instrumenté l'application pour y ajouter les informations dynamique, Jadx montre maintenant le @fig:th-demo-apres. +On peut voir que les méthodes `Malicious.get_data()` et `Malicious.send_data()` sont appelées. +De plus, la classe `Malicious` qui n'était pas présente dans l'application originale est maintenant visible dans l'application modifié. + +#figure( + ```java + public void main() throws Exception { + String[] strArr = {"n6WGYJzjDrUvR9cYljlNlw==", "dapES0wl/iFIPuMnH3fh7g=="}; + Class loadClass = this.cl.loadClass(decrypt("W5f3xRf3wCSYcYG7ckYGR5xuuESDZ2NcDUzGxsq3sls=")); + Object obj = "imei"; + for (int i = 0; i < 2; i++) { + Method method = loadClass.getMethod(decrypt(strArr[i]), String.class, Activity.class); + Object[] objArr = {obj, this.ac}; + obj = T.check_is_Malicious_get_data_fe2fa96eab371e46(method) ? + Malicious.get_data((String) objArr[0], (Activity) objArr[1]) : + T.check_is_Malicious_send_data_ca50fd7916476073(method) ? + Malicious.send_data((String) objArr[0], (Activity) objArr[1]) : + method.invoke(null, objArr); + } + } + ```, + caption: [Code de `Main.main()` calculé par Jadx, après modifications], +) + +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é. +Une fuite d'information devrais donc être détecté par Flowdroid. +Lancé sur l'application originale, Flowdroid calcul un graphe d'appel de méthodes contenant 43 arcs, et ne détecte aucune fuite. +En revanche, lancé sur l'application modifié, Flowdroid calcul cette fois un graphe de 76 arsc, et détecte bien la fuite de donné. + +Bien que nous n'aillons pas peu tester notre approche correctement à grande échelle du aux limites de notre environnement d'analyse statique, nous avons bien montré qu'il est possible de transmètre des informations dynamiques a des outils d'analyse statique pour améliorer leurs résultat. + + +] /*#[ == Conclusion +]*/ + /* * Vocabulaire: * - Obfuscation: brouillage, Reverse Engineering: Ingénierie Inverse, jofr 1 jav 2013 https://www.legifrance.gouv.fr/jorf/jo/id/JORFCONT000026871045 diff --git a/4_class_loader/3_obfuscation.typ b/4_class_loader/3_obfuscation.typ index fca7eda..aefe459 100644 --- a/4_class_loader/3_obfuscation.typ +++ b/4_class_loader/3_obfuscation.typ @@ -94,16 +94,16 @@ To evaluate the tools, we designed a single application that we can customize fo We used 4 versions of this application: -* A control application that does not do anything special: `Obfuscation.hide_flow(String personal_data)` simply return `personal_data`. ++ A control application that does not do anything special: `Obfuscation.hide_flow(String personal_data)` simply return `personal_data`. It will be used for checking the expecting result of tools. -* A version that implements self shadowing: the class `Obfuscation` is duplicated: one is the same as the in the control app (`Obfuscation.hide_flow(String)` returns its arguments), and the other version returns a constant string. ++ A version that implements self shadowing: the class `Obfuscation` is duplicated: one is the same as the in the control app (`Obfuscation.hide_flow(String)` returns its arguments), and the other version returns a constant string. These two versions are embedded in several #DEX of a multi-dex application. -* The third version implement #SDK shadowing and needs an existing class of the #SDK. ++ The third version implement #SDK shadowing and needs an existing class of the #SDK. We used the #SDK class `Pair` that we try to shadow. We put data in a new `Pair` instance and reread the data from the `Pair`. The colliding `Pair` class we created discards the data at the initialisation and stores `null` instead of the argument values. This decoy class break the flow of information: Flowdroid will detect the information flow if it uses the actuall #SDK implementation of `Pair` to compute the #DFG, but not if it uses the decoy. -* The last version tests for Hidden #API shadowing. ++ The last version tests for Hidden #API shadowing. Like for the third one, we similarly store data in `com.android.okhttp.Request` and then retrieve it. Again, the shadowing implementation discards the data. diff --git a/4_class_loader/6_conclusion.typ b/4_class_loader/6_conclusion.typ index 0c41dc6..6c2bc17 100644 --- a/4_class_loader/6_conclusion.typ +++ b/4_class_loader/6_conclusion.typ @@ -1,4 +1,4 @@ -#import "../lib.typ": SDK, pb2, pb2-text, highlight-block, ie +#import "../lib.typ": SDK, pb2, pb2-text, highlight-block, ie, todo #import "X_var.typ": * == Conclusion diff --git a/main_french.typ b/main_french.typ index 62ea2ba..4644ae2 100644 --- a/main_french.typ +++ b/main_french.typ @@ -8,7 +8,7 @@ author: "Jean-Marie MINEAU", affiliation: "IRISA", defense-place: "Rennes", - draft: false, + draft: true, defense-date: datetime( year: 2025, month: 12, @@ -20,6 +20,7 @@ show_cover: true, show_body: true, show_abstracts: false, + preliminary: true, ) #set heading(numbering: none, outlined: true)