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é
Trackback this post