Packer sans ta mère, Level II, Prérequis III : LoaderDATA

On va voir aujourd’hui un grand classique des packer et aussi des shellcodes; Comment trouver et parser la liste des DLL afin de trouver le début d’une DLL mappée en mémoire;

Désormais on sait que grace au PEB + 0xC on peut trouver l’emplacement de la structure Loader Data.

Screen Shot 2014-05-24 at 9.43.52

 

Loader Data nommé aussi PEB_LDR_DATA va contenir la liste des DLL et a quel offset mémoire trouver les DLL de notre process. Mais si on regarde à cet emplacement on tombe sur une structure fort déroutante (Moi je vous jure, j’ai mis du temps à comprendre et avec le livre de  Sir Russinovich sur les genoux !). Cette structure ne propose pas une seul liste de DLL chargée mais 3 listes. Ces listes utilisent un format de liste chainée.  Ce que chez M. Windows on nomme des LIST_ENTRY.

Il y a 3 listes disponible concernant les DLL en mémoire ;

  • La liste de DLL chargée par windows au démarrage de l’exécutable (InLoadOrderModuleList)
  • La liste de DLL actuellement en mémoire. (InMemoryOrderModuleList)
  • La liste de DLL initialisée (InInitialisationOrderModuleList)

Je vous l’accorde pour l’instant c’est pas trop parlant;  Autant les deux premier on comprend bien la différence, si un exécutable après initialisation charge avec la fonctions LoadLibrary une nouvelle DLL on ne la retrouvera pas dans la première liste. La 3eme liste en fait ne comprend pas notre exécutable lui même. C’est donc équivalent à la seconde option sans notre propre process, car oui le listing des DLL en mémoire contient notre propre process.

Bon ça c’était la partie facile. Voyons ces listes chainées. Une liste chainée utilise deux pointeurs FLINK (Forward Link) et BLINK (BackWard link). Et c’est à partir de là qu’il faut sortir un schéma. Voici un petit exemple de cette structure. Cet exemple contient 3 records.

list_entry

Personne est tombé dans les pommes ? J’ai un ancien collègue qui aurait probablement éructé un “C’est quoi c’te structure de Nazi”. Alors petite explication. Chaque Flink donne l’adresse du Flink suivant, idem pour le Blink qui donne lui l’adresse du Blink précédent. Les deux premiers records sont les header il n’ont pas de data, seul le prochain Flink vous permettra d’arriver à la structure qui nous intéresse.

Donc si on veut voir la structure 2, il faut lire le 1re Flink, puis le Second, et enfin sous le Flink on trouvera le record qui vous intéresse.Mais il reste une petite subtilitée… Dans notre cas, Il y a 3 listes, donc chaque entrée comporte en header 3 couples de flink/blink. Donc en fait pour une entrée la structure est :

Diagram2

Donc si on suis les flink de InLoadOrderModuleList notre structure sera 0X18 bytes plus loin. Si on suit les Flink de InInitialisationOrderModuleList, la structure n’est qu’a 0x8 bytes plus loin. Funny n’est-ce pas.

Ha ! Et en plus quand on cherche quelque chose, il faut retenir l’offset du premier Flink des headers sous peine de tourner en boucle Ad Vitam. Donc pour aider à la comprenette, prenons un exemple. Dans cet exemple 32 bits, le Loader data d’après le PEB est situé en 0x211EA0. Le format de loader data au final c’est :

  • 0x0 Dword Lenght (Bullshit, on s’en sert pas)
  • 0x4 Dword Unused
  • 0x8 Dword SSHandle (On s’en fout aussi)

Et on attaque les fameuses list entry.

  • 0x0C List_Entry (Donc 2 Dword, le Flink et le Blink) InLoadOrderModuleList
  • 0x14 List_Entry InMemoryOrderModuleList
  • 0x1C List_Entry InInitialisationOrderModuleList

blinkheader

Ok donc admettons que l’on souhaite voir la première entrée de  la liste InInitialisationOrderModuleList, le Flink de ce header nous informe d’allez voir le premier record en 0x241F58 (regardez en 0x1c). Je suis en train de suivre le flink de la 3eme liste donc j’ai ma structure si chèrement désirée en flink + 0x8. Et devinez  ce qu’on y trouve…

Victoire enfin une structure tant recherchée. En 241F58 j’ai bien le flink suivant, mais surtout ;

module

On trouve en 0X241f60 l’offset en mémoire de notre image PE loadée de ntdll.dll. Je sais que c’est ntdll.dll car en 0x241F78 j’ai l’offset d’une string unicode donnant de nom de la DLL.

cette structure, Qui démarre au flink de la 1ere listes se nomme LDR_MODULE. En deux mots pour les packers il y a deux trucs juteux

  • En 0x18 la base adresse, ici en 0x24160 qui nous dit que cette dll est loadée en 0x7C900000
  • En 0x30 un pointeur sur la chaine unicode du nom de la DLL (ici en 0x241f78 qui pointe vers 0x7C92040c)

Alors après il est rare que les packers testent le nom de la dll directement. Soit certains savent que kernel32.dll c’est toujours la seconde et que la 1ere c’est toujours ntdll.dll. Soit ils utilisent un genre de hash du pauvre pour retrouver le nom de la DLL.

Petit exemple de “Use the force luke” tiré d’un malware quelconque..

Un autre générique et chiadé a moi :) (Oui je t’ai vu toi dans le fond ricaner, on peut faire mieux)

et un autre petit exemple “Use the force en 64 Bits”. Tout est pareil, sauf la taille des adresse évidemment ce qui décale toute notre affaire.

Et voila, la structure est bien chelou mais désormais vous êtes aptes à retrouver l’offset de n’importe quelle DLL mappée en mémoire et/ou détecter cette action dans le packer de votre choix.

a+

This entry was posted in Asm, Malware, Reverse, Windows and tagged , , , , , . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *

Please Do the Math