(TAOMF) Windows Executive Objects

L'ensemble des articles tagués TAOMF ont été écrit à partir d'un ensemble de notes prises suite à la lecture du livre "The Art Of Memory Forensic" écrit par Michael Hale Ligh, Andrew Case, Jamie Levy et Aaron Walters.

Tout les crédits de ces articles leur reviennent donc de droits. Par ailleurs je vous invite vraiment à lire ce livre qui est une mine colossale d'informations.


Windows est un OS qui utilise énormément le concept de structures. Ces structures lui permettent de gérer les données, les processus, les fichiers ouverts... Bref, toutes les informations nécessaires au bon fonctionnement de l'OS.

La plupart de ces structures sont appelées des "executive objects" puisqu'ils sont gérés par le Windows Object Manager qui est un composant du kernel Windows. Pour être plus précis, une structure devient un executive object dès lors que l'OS y ajoute des headers supplémentaires utilisés dans le but de gérer ces structures.

Il existe plusieurs executive objects différents suivant l'OS et la version de l'OS que vous utilisez. Pour les lister on pourra ce servir de l'outil Winobj de la suite SysInternals:

Les executive objects les plus courants sont les:

  • fichiers qui contiennent toutes les informations relatives à l'ouverture d'un fichier (les permissions, la région mémoire où est mappé le contenu du fichier ainsi que son nom)
  • processus: un container qui permet aux threads de s'exécuter au sein d'un adressage virtuel et qui maintient la liste des handlers ouverts vers diverses ressources.
  • tokens qui contiennent l'ensemble des informations relatives au contexte de sécurité  d'exécution d'un processus/thread.
  • threads qui représentent le thread d'un processus
  • drivers qui représentent les drivers mappés en mémoire et contient les adresses des handlers d'input/output.

Tous ces executive objects sont constitués d'au moins une structure _OBJECT_HEADER qui, comme nous le disions plus tôt, nous permet de distinguer une structure d'un executive object. Cette structure _OBJECT_HEADER contient notament le type d'objet de l'executive object:

En plus de cette _OBJECT_HEADER, on peut aussi trouver des headers optionnels qui seront toujours situés avant la structure _OBJECT_HEADER. Ces headers optionnels contiennent les valeurs suivantes::

  • _OBJECT_HEADER_CREATOR_INFO_: Le nom du créateur de l'objet
  • _OBJECT_HEADER_NAME_INFO: Le nom de l'objet
  • _OBJECT_HEADER_HANDLE_INFO_: La liste des processus qui détiennent un handler sur cet objet
  • _OBJECT_HEADER_QUOTA_INFO: Les informations de quota (indique le nombre de ressources utilisées par l'executive object)
  • _OBJECT_HEADER_PROCESS_INFO: Le processus qui détient cet objet.​

Etant donné que la structure d'un executive object suit un pattern bien défini, il devient assez simple de les détecter dans un dump mémoire.


Avant de créer un executive object, une plage mémoire va lui être alloué. Cette plage s'appelle un kernel pool et chaque kernel pool contient une structure _POOL_HEADER:

Cette structure _POOL_HEADER contient notamment un PoolTag (une valeur codée sur 4 octets) qui indique quel est le type de structure d'objet utilisé contenu au sein de cette allocation:

Crédit image: The Art of Memory Forensic

A noter que ces pool tags sont susceptibles de changer en fonction des OS/versions utilisés. On pourra d'ailleurs lister en live les les pool tags activement utilisés en utilisant PoolMon disponible dans la suite de développement pour drivers de Microsoft.

Au cours d'une analyse forensic il faudra cependant être prudent lorsque l'on analyse des executive objects et notamment les pooltags. Tout d'abord un executive object peut ne pas avoir de pool tag. En effet, Microsoft recommande d'utiliser la fonction ExAllocatePoolWithTag de l'API Windows pour associer un pool tag à un pool header mais on peut tout à fait utiliser la fonction ExAllocatePool qui, elle, n'associe pas de pool tag au pool header.

Par ailleurs il existe plusieurs techniques d'anti forensics comme par exemple l'utilisation de tag arbitraire. En effet, un driver peut tout à fait allouer un espace mémoire en utilisant un pool tag générique. Par exemple le tag "Ddk " est le tag utilisé par défaut lorsque aucun tag n'est spécifié. L'utilisation d'un tag générique rendra plus compliqué l'analyse du dump mémoire.

Enfin, nous avons vu plus tôt qu'à chaque création d'executive object, une plage mémoire lui est alloué. En réalité ce n'est pas totalement vrai puisque si la taille de l'executive object est trop importante (i.e si l'objet est plus volumineux que la taille d'une page soit 4096 octets, celui-ci sera alloué dans ce que l'on appelle une "Big Page Pool". Dans ce cas là, le _POOL_HEADER n'est tout simplement pas utilisé. En revanche les informations qu'il aurait du contenir sont stockées dans la Big Page Track Tables que l'on pourra très facilement crawler (via le plugin bigpools fournis avec volatility)  puisque celle-ci se situe toujours au même endroit.