lundi, janvier 22, 2007

Au-delà de l'écran bleu


L'examen de la mémoire physique reste, à l'heure actuelle, une pratique marginale du forensique numérique. Pourtant, nous pouvons constater chaque jour que les codes malveillants utilisent de plus en plus de techniques, dites anti-forensiques, afin de ne laisser aucune trace sur les disques durs... Au grand malheur des investigateurs forensiques !

Les équipes de réponse aux incidents ont récemment intégré le recueil de la mémoire physique des systèmes Microsoft Windows dans leur procédure de réponse immédiate. Mais les informations obtenues par ce recueil semblent bien dérisoires, face à la somme de données que détient cette mémoire.

Nous sommes actuellement dans une situation similaire à celle des premiers égyptologues qui essayèrent de déchiffrer des milliers d'idéogrammes dont la logique leur échappait. La seule différence est, peut être, que leur auteurs (les développeurs Microsoft) sont bien vivants, mais tenus par des clauses de non divulgation draconiennes. Pour obtenir des brides de savoir, il nous reste à écouter les petits malins qui ont, par exemple, la chance d'avoir sous la main un développeur millionnaire retraité (non, ce n'est pas vrai ! Je ne parle pas de David Cutler) qui adore s'épancher le soir autour d'un verre...

Gestion de la mémoire virtuelle sous Windows

L'une des raisons pour lesquelles il est actuellement extrêmement difficile d'analyser la mémoire physique de tout système d'exploitation moderne est l'incroyable complexité de l'abstraction utilisée pour gérer cette mémoire. La plupart du temps, les données appartenant à un processus sont distribuées de manière complètement aléatoire sur la totalité de la mémoire physique, et également sur le disque dur. Ce qui rend extrêmement difficile la restauration des informations utiles.

En fait, il faut savoir que la gestion de la mémoire est un problème aussi vieux que l'informatique. Depuis plus de quarante ans, les systèmes d'exploitation s'escriment à résoudre le problème de l'allocation de la mémoire physique. Nous allons donc nous concentrer sur les meilleures usines à gaz du moment : les systèmes Microsoft Windows.

Outre leur effroyable complexité interne, les systèmes MS Windows ont l'avantage de constituer l'écrasante majorité des systèmes étudiés durant une investigation forensique. Le véritable challenge dans leur étude réside dans la volonté évidente de leurs développeurs de ne rien documenter sur leur fonctionnement interne. Est-ce d'ailleurs vraiment un bon calcul au niveau sécurité ? Vous n'êtes pas sans savoir que les véritables hackers adorent s'acharner sur ce qui leur résiste !

L'objet \Device\PhysicalMemory a été révélé pour la première fois à la face du monde par Mark Russinovich de Sysinternals (un type qui adore écouter les vieux développeurs autour d'un verre :-)) dans le code source de Physmem. La solution de Microsoft consiste à diviser cette mémoire en un série de pages à taille constante. Cette taille est fixée à 4KB sur les architectures x86 de moins de 4GB de mémoire physique (variable PAGE_SIZE).

La meilleure analogie que je connaisse pour la gestion de la mémoire sous Windows consiste à la comparer à un livre dans lequel chaque page contient un nombre limité de caractères. Dans ce livre, chaque processus possède sa propre table des matières (appelée registre CR3) qui lui permet de consulter les pages qui le concerne. De plus, deux processus possèdent une lecture du livre entièrement différente, chacun d'entre eux croyant être son unique lecteur. Enfin, si un processus peut lire l'adresse mémoire 0x00422211 et y lire le mot "eric", un autre processus y lira le mot "alex".

Chaque processus possède ainsi donc sa propre lecture de l'espace mémoire. Il s'agit du processus de translation de la mémoire virtuelle dans la mémoire physique et le fichier de pagination. Cette translation est possible grâce à la tenue d'une multitude de tables et de registres. Pour simplifier, on peut affirmer que toute l'habileté d'un cheval de Troie réside dans sa capacité à modifier ces tables sans provoquer un écran bleu de la mort (un BSoD pour les anglophiles) !

Premier élément d'analyse de la mémoire : les objets _EPROCESS

Chaque programme tournant sur un système MS Windows se voit assigner un "processus" qui maintient l'état de ses données en mémoire. MS Windows stocke dans la mémoire virtuelle les informations relatives à chacun de ses processus dans une structure du noyau appelée _EPROCESS.

Le gestionnaire de la mémoire des systèmes Microsoft prédéfinit un intervalle de l'espace d'adressage de la mémoire virtuelle au profit des objets du noyau (adresses supérieures à 0x80000000 pour les architectures Intel x86 de moins de 4GB de RAM et supérieures à 0xC0000000 si l'option /3GB a été utilisée lors de l'installation du système).

Nous savons que tous les blocs _EPROCESS de l'ensemble des processus tournant sur un système MS Windows sont liés entre eux dans une double-liste dans laquelle le champ ActiveProcessLinks contient l'adresse virtuelle du prochain _EPROCESS à l'offset +0x088 et le précédent _EPROCESS à l'offset +0x08C.

Malheureusement, trouver l'adresse virtuelle d'un _EPROCESS constitue l'une des difficultés de l'analyse de la mémoire physique. En s'appuyant sur de la recherche de motifs (patterns matching), les outils mem_parser et KnTList réussissent à retrouver l'adresse du _EPROCESS System, bien que celle-ci soit modifiée à chaque redémarrage de la machine. A partir de cette adresse, et grâce à la double liste, nous sommes alors en mesure de retrouver tous les processus qui tournaient sur une machine MS Windows dont on a recueilli une image de la mémoire physique. A l'exception des codes malveillants qui manipulent leurs voisins dans la double liste pour rester invisibles (technique de camouflage DKOM, pour Direct Kernel Object Manipulation).

Deuxième élément d'analyse de la mémoire :la BPD et le PEB d'un _EPROCESS


Une fois tous les processus, qui étaient en fonctionnement lorsque l'image de la mémoire physique a été prise, sont retrouvés par l'adresse de leur _EPROCESS respectif, nous pouvons nous intéresser à chacun d'entre eux en particulier.

La BPD (pour Basic Process Details) fournit un certain nombre d'information sur le processus, dont les plus intéressantes sont les suivantes, classées par Offset :
- +0x018 : DirectoryTableBase qui constitue l'adresse physique de la table des matières de ce processus (Page Directory)
- +0x084 : le PID (l'identifiant) du processus
- +0x088 et +0x08C : les adresses des processus voisins dans la double-liste
- +0x14C : le PPID (PID du processus parent). C'est là que l'on recherche en particulier les processus ayant comme parent cmd.exe
- +0x174 : le nom du fichier binaire (.EXE, .DLL, ...)

Le _PEB (pour Process Environment Block) fait partie des principaux éléments de description d'un processus. Il stocke les données d'environnement du processus en mémoire. Pour accéder au _PEB, une translation doit être réalisée en utilisant son adresse virtuelle stockée dans son objet parent : _EPROCESS. Les informations intéressantes à recueillir dans cet objet sont les suivantes, classées également par Offset :
- +0x008 : adresse virtuelle de l'image de l'exécutable. Une fois sauvegardée, cette image peut être lancée et étudiée à loisir. (il existe des offsets permettant de calculer la taille de cet exécutable)
- +0x00c : adresse virtuelle de la liste des DLL (modules) utilisées par le processus
- +0x018 : adresse virtuelle du tas (Heap) du processus. (une bonne excuse pour se replonger dans les affres de l'assembleur et du reverse engineering...)

La guerre sombre et cruelle du Kernelland

Les rootkits les plus difficiles à détecter sont ceux résidant uniquement dans la partie de la mémoire physique réservée au noyau. Il s'agit d'un terrain de jeu extrêmement dangereux où le moindre faux pas provoque le terrible BSoD.

Afin de rester invisibles aux yeux des logiciels de détection qui scrutent les accès en écriture sur le disque dur, les codes malveillants de dernière génération font en sorte de se faire passer pour un pilote de matériel ou un thread appartenant à un processus noyau qui nécessite de la mémoire virtuelle non-paginable. Pour la dernière solution, il lui faut appeler la fonction ExAllocatePool avec le paramètre NonPagedPool, mais ceci est une autre histoire..

La principale faiblesse des rootkits est qu'ils doivent restés vivants ! S'ils ont été développés pour ne rien écrire sur le disque dur, ils sont donc inévitablement présents en mémoire physique.

Les méthodes d'analyse les plus simples que j'utilise actuellement pour détecter un rootkit dans l'image de la mémoire physique d'une machine suspecte sont les suivantes :
- repérer les processus ayant comme PPID cmd.exe ou explorer.exe
- référencer les adresses inhabituelles de module dans l'Offset +0x00c du PEB. En particulier, les librairies Kernel32.dll et NTDLL.dll. (rootkit utilisant les IAT Hooks)
- faire du reverse sur l'image de l'exécutable et examiner les données du tas du processus (bon là j'avoue que j'ai du mal. Mais je me documente à fond :-)).

6 commentaires:

  1. Très intéressant ce post, je vois que tu t'y es mis sérieusement ;)

    2 précisions :

    - Pour ceux qui se posent la question "comment trouver le PEB ?", il est référencé par _EPROCESS (offset +0x1b0 sous Windows 2000).

    - Tous les process utilisateur ont pour PPID "explorer.exe" :( En plus tu dois rater les process démarrés depuis SVCHOST ou LSASS (au pif :) avec cette méthode.

    RépondreSupprimer
  2. -1. même offset +0x1b0 pour le PEB dans Windows XP
    -2. je vais vérifier.

    RépondreSupprimer
  3. Je ne sais pas comment vous joindre (pas de form de contact de l'auteur sur ce blog?), alors je me permets d'utiliser le champs commentaire de votre dernier article...

    Passionné de secinfo, je suis tombé ce soir, par hasard, sur votre blog.
    Je m'y suis régalé. On y sent beaucoup de vécu et de recul sur les sujets traités. J'ai beaucoup appris.
    Je regrette juste que le blog ne dispose pas d'une fonction "generer un pdf" qui m'aurait permis de "mettre à l'abris" tout ce pain bénis...

    Merci, merci et encore merci.
    Et surtout n'arrétez pas! De tels articles et surtout en français; je cours donner l'adresse de votre blog à tous mes étudiants!

    RépondreSupprimer
  4. Woah !! Avec un commentaire comme celui-là, je ne peux que reprendre ma plume. :-)

    Il est vrai que j'ai délaissé l'écriture ces derniers temps (pas d'article pour le mois de février).

    Le fait est que j'ai quitté mon poste, il y a quelques semaines et ne pratique donc plus ni le forensique ni la réponse aux incidents.

    Je suit actuellement en recherche active d'un nouvel employeur. Ce dernier devra me permettre, entre autres, d'écrire de manière non-anonyme !

    RépondreSupprimer
  5. Pas mieux que le dernier post anonyme :
    ce blog est tout simplement excellent, on y trouve des infos techniques croustillante, en français, le tout saupoudrer d'un "humour" original.

    J'apprends également bcp de choses en parcourant ce blog qui pointe vers d'autres sites qui valent également le coup.

    Surtout ne pas s'arreter en si bon chemin !!!!!

    Je classe ce blog dans "les perles rares" et fais tourner le lien aussi vite que possible.

    RépondreSupprimer
  6. Bon,
    ok c'est promis, la semaine prochaine je reprends le flambeau. Il faut dire que je n'aurai pas le choix, vu que je reprends également le boulot !

    Un nouvel employeur, de nouvelles missions... Adieu, SCADA, vive le pentest...

    Mais dans quel carton de déménagement ais-je pu ranger mon pc portable ???

    RépondreSupprimer