ObpRootDirectoryObject

février 28th, 2007 at 11:06 admin

Parfois, à force de regarder dans les entrailles de Win on tombe sur des trucs on sait pas ce que c’est, ni à quoi ca sert, mais c’est là, alors on regarde le peu de doc sur le sujet et on découvre au final que c’est pas con de l’avoir foutu :} Il s’agit en fait d’une arborescence appelée ObpRootDirectoryObject maintenue par l’object manager de Win et qui contient les objets utilisés par le noyau. Comme vous le savez les drivers sont des objets du noyau ainsi si on load un driver un objet le référençant sera ajouté et DONC un anti-totokit pourrait aller lire cette struture et découvrir notre driver, ouin :-(


Commençons par essayer de lire cette table à partir du UserLand, pour cela on va utiliser les API native qui nous fournissent de plus grandes possibilitées, on à besoin de jouer avec NtOpenDirectoryObject() pour obtenir un handle sur l’ObjectDirectory puis de NtQueryDirectoryObject pour pouvoir « lire » sont contenu. Les prototypes des fonctions sont :

NtOpenDirectoryObject(
OUT PHANDLE DirectoryHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes
);

NtQueryDirectoryObject(
IN HANDLE DirectoryHandle,
OUT PVOID Buffer,
IN ULONG BufferLength,
IN BOOLEAN ReturnSingleEntry,
IN BOOLEAN RestartScan,
IN OUT PULONG Context,
OUT PULONG ReturnLength OPTIONAL
);

Ces API sont documentées dans le « WIN 2000 Native API reference » de Gary Nebbett (dispo dans le dossier ebooks/ de mon repo, mais shuuuut!). Ce qui nous intéresse est l’ObjectDirectory maintenu par le noyau qui porte le nom de ObpRootDirectoryObject, on la dénome tout simplement ‘\’ :} On lit l’arborescence de façon récursive en réappelant la fonction dès qu’on trouve un nouveau « dossier », un nouvel objet de type ObjetDirectory en fait et puis on admire le résultat défiler pendant 10 mins. A noter que si vous voulez pas vous peter les yeux le tool WinObj de sysinternals réalise très bien cela et possède surtout une GUI, mon code est juste là pour montrer comment utiliser ces API.

http://www.microsoft.com/technet/sysinternals/SystemInformation/WinObj.mspx

Alors à l’exécution on voit un dossier Driver qui contient tout nos objets sur les drivers :

Newpath : Driver
ObjectName : NDIS
ObjectType : Driver

ObjectName : KSecDD
ObjectType : Driver

ObjectName : Beep
ObjectType : Driver

ObjectName : Raspti
ObjectType : Driver

ObjectName : Mouclass
ObjectType : Driver

ObjectName : Kbdclass
ObjectType : Driver

[...]

Maintenant qu’on sait manipuler ces API, regardons à quoi ressemble une structure OBJECT_DIRECTORY, hop straff bunny on lance le kernel debugger et on examine les symbols :

lkd> dt nt!_OBJECT_DIRECTORY
+0x000 HashBuckets      : [37] Ptr32 _OBJECT_DIRECTORY_ENTRY
+0x094 Lock             : _EX_PUSH_LOCK
+0x098 DeviceMap        : Ptr32 _DEVICE_MAP
+0x09c SessionId        : Uint4B
+0x0a0 Reserved         : Uint2B
+0x0a2 SymbolicLinkUsageCount : Uint2B

Le premier champ est un tableau de 37 pointeurs sur des _OBJECT_DIRECTORY_ENTRY :

lkd> dt nt!_OBJECT_DIRECTORY_ENTRY
+0x000 ChainLink        : Ptr32 _OBJECT_DIRECTORY_ENTRY
+0x004 Object           : Ptr32 Void

Une structure OBJECT_DIRECTORY_ENTRY contient un pointeur sur la structure OBJECT_DIRECTORY_ENTRY suivante (ChainLink) et un champ contenant un pointeur sur l’objet quelle référence (Object).

Maintenant qu’on connaît les structures on choppe l’adresse de l’ObpRootDirectoryObject et on la dump :

lkd> dd nt!ObpRootDirectoryObject l 1
8055fb58  e1001588 00000000 00000001 00000000
lkd> dt nt!_OBJECT_DIRECTORY e1001588
+0x000 HashBuckets      : [37] 0xe10078a0 _OBJECT_DIRECTORY_ENTRY
+0x094 Lock             : _EX_PUSH_LOCK
+0x098 DeviceMap        : (null)
+0x09c SessionId        : 0xffffffff
+0x0a0 Reserved         : 0
+0x0a2 SymbolicLinkUsageCount : 0x82

Dumpons ce qui nous intéresse, le tableau de pointeurs sur les _OBJECT_DIRECTORY_ENTRY :

lkd> dd e1001588 l 25 //(0x25=37)
e1001588  e10078a0 e171f518 00000000 e1007150
e1001598  00000000 00000000 e15c3600 00000000
e10015a8  00000000 e14971b8 e10000d0 00000000
e10015b8  00000000 e133dd20 e1747970 00000000
e10015c8  e133c750 00000000 00000000 e1007890
e10015d8  e15be088 e15ad5d0 e15be0f8 e148a118
e10015e8  e133c658 e1b5ca28 e10004b8 e1007738
e10015f8  00000000 00000000 00000000 e1007880
e1001608  e1000060 e15cb688 00000000 e1680d80
e1001618  00000000

Après on peut lire la liste chainée, la fin est déterminé par un ChainLink à nul. Ici j’ai prit la liste qui correspondait à l’ObjectDirectory référençant les drivers :

lkd> dt  nt!_OBJECT_DIRECTORY_ENTRY e133c750  -l ChainLink
ChainLink at 0xe133c750
---------------------------------------------
+0x000 ChainLink        : (null)
+0x004 Object           : 0xe133c798
lkd> !object 0xe133c798
Object: e133c798  Type: (81ff04f0) Directory
ObjectHeader: e133c780
HandleCount: 0  PointerCount: 79
Directory Object: e1001588  Name: Driver

Hash Address  Type          Name
---- -------  ----          ----
00  81f29d30 Driver        NDIS
81f2a658 Driver        KSecDD
81dc8318 Driver        Beep
01  81e04738 Driver        Raspti
81ec3a80 Driver        Mouclass
03  81e16bf8 Driver        Kbdclass
[...]

Evidemment on peut directement utilisé la commande !object du kernel debugger pour dumper l’ObpRootDirectoryObject :

lkd> !object e1001588
Object: e1001588  Type: (81ff04f0) Directory
ObjectHeader: e1001570
HandleCount: 0  PointerCount: 35
Directory Object: 00000000  Name:
130 symbolic links snapped through this directory

Hash Address  Type          Name
---- -------  ----          ----
00  81f2a300 Device        Ntfs
e1007688 Directory     ArcName
01  e170d2c0 Port          SeLsaCommandPort
03  e1001718 Key           REGISTRY
06  e19c3330 Port          XactSrvLpcPort
09  e1497200 Directory     NLS
10  e1007fc0 SymbolicLink  DosDevices
13  e168b2e0 Port          SeRmCommandPort
14  e17207d0 Port          LsaAuthenticationPort
81d99d48 Event         LanmanServerAnnounceEvent
81f29750 Device        Dfs
16  e133c798 Directory     Driver
19  e10075a0 Directory     Device
20  e163e208 Directory     Windows
21  81df5be8 Event         SAM_SERVICE_STARTED
e1340040 Directory     Sessions
22  e168f0d0 Directory     RPC Control
e168f5b8 Port          SmApiPort
23  e1495900 Directory     BaseNamedObjects
e10005f8 Directory     KernelObjects
24  e133c6a0 Directory     FileSystem
e1001128 Directory     GLOBAL??
25  81cef718 WaitablePort  NLAPublicPort
26  e1000500 Directory     ObjectTypes
27  e1007780 Directory     Security
e174f040 Port          ErrorLogPort
31  e1007c38 SymbolicLink  SystemRoot
81d8d490 Device        Cdfs
32  81cc9768 WaitablePort  NLAPrivatePort
e1007e78 Directory     Callback
33  81e15470 Event         UniqueSessionIdEvent
81f6ede0 Event         SeLsaInitEvent
35  e1340550 Directory     KnownDlls

Je reviens sur les valeur prise par le champ Object de la structure OBJECT_DIRECTORY_ENTRY, il s’agit d’un pointeur sur l’objet, lorsque qu’on utilise la commande !object du kernel debugger celle ci va aller lire à l’adresse demandé moins
0×18, voyez avec l’exemple :
lkd> !object e1001588
Object: e1001588 Type: (81ff04f0) Directory
ObjectHeader: e1001570=e1001588 – 0×18
Pour en fait retrouver une structure OBJECT_HEADER qui va nous dire à quoi correspond l’objet:

lkd> dt nt!_OBJECT_HEADER
+0x000 PointerCount     : Int4B
+0x004 HandleCount      : Int4B
+0x004 NextToFree       : Ptr32 Void
+0x008 Type             : Ptr32 _OBJECT_TYPE
+0x00c NameInfoOffset   : UChar
+0x00d HandleInfoOffset : UChar
+0x00e QuotaInfoOffset  : UChar
+0x00f Flags            : UChar
+0x010 ObjectCreateInfo : Ptr32 _OBJECT_CREATE_INFORMATION
+0x010 QuotaBlockCharged : Ptr32 Void
+0x014 SecurityDescriptor : Ptr32 Void
+0x018 Body             : _QUAD

Dans le cas d’un driver on à :

lkd> !object 81f29d30
Object: 81f29d30  Type: (81fb5900) Driver
ObjectHeader: 81f29d18
HandleCount: 0  PointerCount: 20
Directory Object: e133c798  Name: NDIS

Voilà maintenant qu’on sait comment tout cela fonctionne, on comprend mieux comment fonctionne les anti-rootkits qui utilisent cette techniques pour retrouver les drivers.

Mais un rootkit à déjà contourner la chose, un prototype poster sur rooktit.com et portant le nom de unreal.a
http://rootkit.com/newsread.php?newsid=647

En fait je viens de m’apercevoir qu’ils ont release le code, j’expliquerais son fonctionnement plus tard afin de montrer comme le rootkit se cache dans l’ObpRootDirectoryObject.

Le code vu plus haut :
http://ivanlef0u.fr/repo/ObjectDir.rar

Enjoy.

Entry Filed under: Non classé


Calendar

novembre 2019
L Ma Me J V S D
« fév    
 123
45678910
11121314151617
18192021222324
252627282930  

Most Recent Posts