Got the Handle

juin 22nd, 2007 at 10:04 admin

Réveil tardif et difficile aujourd’hui, nous sommes le lendemain de la fête de musique et je ne me suis toujours pas remit de mon concert d’éclatage de tympans avec Korn. Ma tête me fait mal et mes oreilles sifflent toujours à cause de la basse de Fieldy mais j’arrive encore à penser correctement (du moins à faire semblant). Je vais profiter de mon état comateux larvaire pour vous faire découvrir le rôle des handles dans l’Object Manager de Windows. Vous l’avez surement déjà expérimenté, pour pouvoir injecter du code dans un process, il vous faut obtenir un handle sur celui ci, alors vous faites un OpenProcess, comme vous curieux vous regardez la valeur du handle et vous tombez sur un 0xC1 qui ne vous parle absolument pas :], aucun rapport avec le PID du process, si vous regardez le winNT.h vous remarquez qu’un handle est définit par un void*, or la valeur que vous avez trouvé ne pointe vers rien, bref le handle est un objet vraiment mystérieux.


Après un peu de lecture des Windows Internals sur l’Object Manager, on apprend que chaque process possède sa propre table de handles, celle-ci se situe à l’offet 0xC4 de la structure EPROCESS et porte le nom de ObjectTable. Prennons celle du process explorer.exe

kd> !process 0 0
[...]
PROCESS ffb45030  SessionId: 0  Cid: 0488    Peb: 7ffdb000  ParentCid: 0468
    DirBase: 00ed1000  ObjectTable: e1552f50  HandleCount: 307.
    Image: explorer.exe
[...]

Ok, on y va tranquillement l’ObjectTabble de explorer.exe se trouve en 0xe1552f50, la structure situé à cette adresse est de type HANDLE_TABLE, dumpons tout cela.

kd> dt nt!_HANDLE_TABLE e1552f50
   +0x000 TableCode        : 0xe1558000
   +0x004 QuotaProcess     : 0xffb45030 _EPROCESS
   +0x008 UniqueProcessId  : 0x00000488
   +0x00c HandleTableLock  : [4] _EX_PUSH_LOCK
   +0x01c HandleTableList  : _LIST_ENTRY [ 0xe1426fd4 - 0xe152fcb4 ]
   +0x024 HandleContentionEvent : _EX_PUSH_LOCK
   +0x028 DebugInfo        : (null)
   +0x02c ExtraInfoPages   : 0
   +0x030 FirstFree        : 0x4d0
   +0x034 LastFree         : 0
   +0x038 NextHandleNeedingPool : 0x800
   +0x03c HandleCount      : 307
   +0x040 Flags            : 0
   +0x040 StrictFIFO       : 0y0

Déjà plusieurs choses intéressantes, on voit que explorer.exe à ouvert 307 handles, on retrouve son PID de 0×488, l’EPROCESS qui correspond à cette ObjectTable, HandleTableList est une double liste chaînée pointant sur les ObjectTable des autres process, permettant ainsi au kernel de calculer plus rapidement par exemple le nombre de handles ouvert, enfin le champ HandleTableLock permet de verrouiller la structure, évitant ainsi que plusieurs thread manipulent cette structure en même temps, c’est l’équivalent d’un mécanisme de type Mutex. Le champ TableCode est celui qui nous intéresse le plus mais on jouera avec plus tard.

Pour l’instant on fait mumuse tranquillement (on est toujours la phase de réveil post gueule de bois). On va demander au KD de dumper tout les handles ouvert de explorer.exe, on utilise !handle en lui balançant en premier paramètre, la valeur du handle, nous on veut tous les voir alors on met 0, ensuite le type d’info qu’on veut obtenir, en mettant la valeur 3 on aura des infos sur le nom et le type du handle et enfin le PID du process à analyser :

kd> !handle 0 3 488
processor number 0, process 00000488
Searching for Process with Cid == 488
PROCESS ffb45030  SessionId: 0  Cid: 0488    Peb: 7ffdb000  ParentCid: 0468
    DirBase: 00ed1000  ObjectTable: e1552f50  HandleCount: 307.
    Image: explorer.exe

Handle table at e1558000 with 307 Entries in use
0004: Object: e1007e38  GrantedAccess: 000f0003 Entry: e1558008
Object: e1007e38  Type: (80e6be70) KeyedEvent
    ObjectHeader: e1007e20 (old version)
        HandleCount: 14  PointerCount: 15
        Directory Object: e1004d10  Name: CritSecOutOfMemoryEvent

0008: Object: e149baa8  GrantedAccess: 00000003 Entry: e1558010
Object: e149baa8  Type: (80e99b68) Directory
    ObjectHeader: e149ba90 (old version)
        HandleCount: 14  PointerCount: 49
        Directory Object: e1004ec8  Name: KnownDlls
[...]

J’ai arrêté le dump aux 2 premiers handles, mais déjà je peux vous dire que la valeur d’un handle est forcément un multiple de 4. Le premier handle, de valeur 4, fait référence à un objet de type KeyedEvent dont l’ObjectHeader se trouve en 0xe1007e38. En fait, en mémoire, chaque objet est précédent d’une structure OBJECT_HEADER, permettant au noyau de connaître le nombre de handles et de pointeurs faisant référence à l’objet (handle!=pointeur). Dans le cas d’un thread, qui est lui aussi un objet, on retrouve juste au dessus de l’ETHREAD une structure OBJECT_HEADER.

Il temps de comprendre à quoi correspondent les valeurs 4 et 8 des handles. En fait c’est simple, ce sont tout simplement des indices dans un tableau de structures HANDLE_TABLE_ENTRY et ce tableau est pointé par le champ TableCode de la structure HANDLE_TABLE.

On est toujours avec notre petit explorer.exe, chez lui TableCode vaut 0xe1558000, un petit dump pour voir à quoi ressemble le bordel.

kd> dd e1558000
e1558000  00000000 fffffffe e1007e21 000f0003
e1558010  e149ba91 00000003 ffb50313 00100020
e1558020  80cd3019 021f0003 e125ed81 000f000f
e1558030  e1552d29 021f0001 e1533679 020f003f
e1558040  80ca5031 000f037f e13696b1 0002000f
e1558050  80e3c411 000f01ff 80ca5031 000f037f
e1558060  80db7fd1 001f0003 80da6369 00100001
e1558070  80cb6eb1 00100020 80cda919 00100000

On observe des valeurs qui pourraient être des pointeurs valides dans le kernel space mais aussi d’autres qui nous parraissent un peu étranges. Bref il faut savoir que les symbols du KD nous donnent la définition suivante d’une HANDLE_TABLE_ENTRY :

kd> dt nt!_HANDLE_TABLE_ENTRY
   +0x000 Object           : Ptr32 Void
   +0x000 ObAttributes     : Uint4B
   +0x000 InfoTable        : Ptr32 _HANDLE_TABLE_ENTRY_INFO
   +0x000 Value            : Uint4B
   +0x004 GrantedAccess    : Uint4B
   +0x004 GrantedAccessIndex : Uint2B
   +0x006 CreatorBackTraceIndex : Uint2B
   +0x004 NextFreeTableEntry : Int4B

De cette définition on déduit qu’une HANDLE_TABLE_ENTRY est une structure avec 2 unions (regardez les offets des différents champs), la première pointant sur l’objet et la seconde contenant les droits d’accès du handle. Cette définition est légèrement inexacte et le schéma suivant montre ce qu’il en est vraiment :

lol

La première union ne pointe pas directement sur l’objet. Ce qui se passe c’est que, comme les kernel développeurs de chez MS ne sont pas trop des buses, ils se sont dit que comme un objet est forcément définit dans le noyau, son adresse sera donc supérieure à 0×80000000 et qu’ainsi le MSB du champ Object serait forcément à 1. Le champ lock mit à 0 permet en gros de dire que le handle de ce process n’est pas manipulé par un thread. De plus les 3 derniers bits ne sont pas prit en compte dans le calcul de l’adresse, ce qui donne l’opération suivant pour passer de valeur du champ Object à un pointeur valide :

pObject=(Object|=0×80000000)&=0xfffffff8

Aussi, comme je l’ai déjà dit, les handles sont forcément multiple de 4, je ne sais pas du tout pourquoi MS à implémenté de cette façon, il doit y avoir une bonne raison mais elle m’échappe encore. Bref, si on regarde notre handle de valeur 4 du process explorer.exe, cela ne veut justement pas dire que la structure HANDLE_TABLE_ENTRY est l’indice 3 de la liste, mais bien à l’indice 1. Sachant que ces structures font 8 bytes, on arrive en 0xe1558000+8 et la valeur Object est de 0xe1007e21. On effectue le petit calcul pour translater, (0xe1007e21|=0×80000000)&=0xfffffff8 = 0xe1007e20. Cette valeur pointe directement sur l’OBJECT_HEADER précédent le process, mais la commande !object du KD prennant en argument un pointeur sur un objet, on ajoute donc à notre pointeur la taille d’une struct OBJECT_HEADER, 0×18:

kd> !object 0xe1007e20+18
Object: e1007e38  Type: (80e6be70) KeyedEvent
    ObjectHeader: e1007e20 (old version)
    HandleCount: 14  PointerCount: 15
    Directory Object: e1004d10  Name: CritSecOutOfMemoryEvent

Cool on retrouvé notre KeyedEvent :}

On continue, l’exemple que j’ai prit avec explorer.exe ne possédait qu’un faible nombre de handles ouvert (307). Le problème c’est que la granularité d’allocation (je kiff cette expression) est par pages, chaque page fait 0×1000 bytes, c’est à dire que si vous avez besoin d’allouer 0×1024 et bien le système vous filera 0×2000. Dans le cas de notre table de handles, celle-ci fait au départ la taille d’une page, ce qui nous fait 0×1000/sizeof(HANDLE_TABLE_ENTRY)=512 handles dans la table. Evidemment vous vous doutez bien qu’un process peut ouvrir plus de 512 handles et qu’il existe donc un mécanisme sous-jacent à l’allocation des handles que je n’ai point encore développé (ca aussi je kiff à donf :p).
Alors on va se trouver à process avec plus de 512 handles et on va disséquer son ObjectTable.
kd> !process 0 0
[...]
PROCESS 80d19ab8 SessionId: 0 Cid: 03b0 Peb: 7ffd5000 ParentCid: 0224
DirBase: 026ae000 ObjectTable: e1679128 HandleCount: 955.
Image: svchost.exe
[...]

Cool notre ami svchost.exe est volontaire, regardons sa HANDLE_TABLE :

kd> dt nt!_HANDLE_TABLE e1679128
   +0x000 TableCode        : 0xe162a001
   +0x004 QuotaProcess     : 0x80d19ab8 _EPROCESS
   +0x008 UniqueProcessId  : 0x000003b0
   +0x00c HandleTableLock  : [4] _EX_PUSH_LOCK
   +0x01c HandleTableList  : _LIST_ENTRY [ 0xe152fcb4 - 0xe166516c ]
   +0x024 HandleContentionEvent : _EX_PUSH_LOCK
   +0x028 DebugInfo        : (null)
   +0x02c ExtraInfoPages   : 0
   +0x030 FirstFree        : 0xaa8
   +0x034 LastFree         : 0
   +0x038 NextHandleNeedingPool : 0x1000
   +0x03c HandleCount      : 955
   +0x040 Flags            : 0
   +0x040 StrictFIFO       : 0y0

svchost.exe à ouvert 955 handles, comment donc est foutu sa table des handles ?! He bien le champ TableCode n’est pas définit comme un pointeur direct sur un tableau de structures HANDLE_TABLE_ENTRY. En fait comme on alloue par pages, les adresses des tables sont des multiples de 0×1000. Ainsi on est sur de trouvé des adresses finissant par 000, cependant pour notre svchost, la valeur de Tablecode est 0xe162a001, WTF ?! Après avoir un peu lu les Windows Internals, on se rend compte de la magnificence de la chose, en fait TableCode ne pointe plus sur un tableau de HANDLE_TABLE_ENTRY mais sur un tableau de pointeurs qui pointent sur nos HANDLE_TABLE_ENTRY … Et justement le fameux 1 permet de dire que nous avons une table de niveau 1, un tableau de pointeurs sur des tables d’HANDLE_TABLE_ENTRY. Mais je crois qu’un exemple est plus parlant.

Si on dump à l’adresse du TableCode, en mettant le 1 à 0 on peut voir :

kd> dd 0xe162a000
e162a000  e167d000 e162b000 00000000 00000000
e162a010  00000000 00000000 00000000 00000000
e162a020  00000000 00000000 00000000 00000000
e162a030  00000000 00000000 00000000 00000000
e162a040  00000000 00000000 00000000 00000000
e162a050  00000000 00000000 00000000 00000000
e162a060  00000000 00000000 00000000 00000000
e162a070  00000000 00000000 00000000 00000000
kd> dd e167d000
e167d000  00000000 fffffffe e1007e21 000f0003
e167d010  e149ba91 00000003 80cc713b 00100020
e167d020  80cc4af9 021f0003 e125ed81 000f000f
e167d030  e167b499 021f0001 e167b871 020f003f
e167d040  e13696b1 0002000f 80db8469 001f0001
e167d050  80e2de79 000f016e 80cc2ad9 000f00cf
e167d060  80e2de79 000f016e 80cc9669 001f0003
e167d070  80cc9621 00100003 80cb59b9 00100003

On a bien 2 pointeurs, 0xe167d000 et 0xe162b000, chacun pointant ainsi sur un tableau d’HANDLE_TABLE_ENTRY (regardez le dd e167d000). On peut vérifier en mattant la position du premier handle de valeur 4.

kd> !handle 4 3 03b0
processor number 0, process 000003b0
Searching for Process with Cid == 3b0
PROCESS 80d19ab8  SessionId: 0  Cid: 03b0    Peb: 7ffd5000  ParentCid: 0224
    DirBase: 026ae000  ObjectTable: e1679128  HandleCount: 955.
    Image: svchost.exe

Handle table at e162a000 with 955 Entries in use
0004: Object: e1007e38  GrantedAccess: 000f0003 Entry: e167d008
Object: e1007e38  Type: (80e6be70) KeyedEvent
    ObjectHeader: e1007e20 (old version)
        HandleCount: 14  PointerCount: 15
        Directory Object: e1004d10  Name: CritSecOutOfMemoryEvent

L’adresse de sa HANDLE_TABLE_ENTRY est bien e167d000+8. J’ajoute que le premier pointeur (0xe167d000) pointe sur une table remplie de 512 HANDLE_TABLE_ENTRY et que le second pointeur (e162b000) vise une table avec 443 structures.

Ce que je n’ai pas dit c’est qu’avant explorer.exe était un process avec un ObjectTable de niveau 0, ici svchost à une ObjectTable de niveau 1 mais il peut exister des tables de niveau 2 ! Ce qui permet d’avoir 1024*1024*512=536 870 912 de handles ouvert par process, ca laisse de la marge :]

Résumons un peu, chaque process possède sa propre handle table, celle-ci peut être organisé de manière hiérarchique en fonction du nombre de handles. Au sein d’un process les handles ne sont que des indices (à divisé par 4) de structures HANDLE_TABLE_ENTRY contenant un pointeur sur l’objet référencé et les droits que possède l’handle sur l’objet. Lorsqu’on ouvre un handle sur un objet, le système va donc crée une entré dans la table des handles et nous renvoyé l’indice de celle ci. Quand on ferme un handle, l’entré est effacée.

Par contre je n’ai vu aucune API exportées par le kernel permettant de manipuler cette table directement, ce qui veut dire que si vous codez un rootkit, soit vous vous débrouillez à récup les différentes adresses des fonctions suivantes :

ExInitializeHandleTablePackage
ExSetHandleTableStrictFIFO
ExUnlockHandleTableEntry
ExCreateHandleTable
ExRemoveHandleTable
ExDestroyHandleTable
ExEnumHandleTable
ExDupHandleTable
ExSnapShotHandleTables
ExCreateHandle
ExDestroyHandle
ExChangeHandle
ExMapHandleToPointer
ExMapHandleToPointerEx
ExpAllocateHandleTable
ExpFreeHandleTable
ExpAllocateHandleTableEntry
ExpAllocateHandleTableEntrySlow
ExpFreeHandleTableEntry
ExpLookupHandleTableEntry
ExSweepHandleTable
ExpAllocateMidLevelTable
ExpAllocateTablePagedPool
ExpAllocateTablePagedPoolNoZero
ExpFreeTablePagedPool
ExpAllocateLowLevelTable
ExSetHandleInfo
ExpGetHandleInfo
ExSnapShotHandleTablesEx
ExpFreeLowLevelTable
ExpBlockOnLockedHandleEntry
ExpMoveFreeHandles
ExEnableHandleTracing
ExDereferenceHandleDebugInfo
ExReferenceHandleDebugInfo
ExpUpdateDebugInfo

Ou soit vous codez vous même votre propre gestionnaire de handles et je peux vous dire que c’est funny ;)

Pour finir, un petit bonus, n’avez vous jamais remarqué vous aussi que les PID et TID (Thread ID) étaient des multiples de 4 ? :] Moi perso, j’aimerais savoir, comment fait le noyau, à partir d’un PID (ou TID), pour retrouver l’objet EPROCESS (ou ETHREAD). Allay soyons fous, désassemblons NtOpenProcess :

kd> uf nt!NtOpenProcess
[...]
nt!NtOpenProcess+0x1fb:
80579196 8d45dc          lea     eax,[ebp-24h]
80579199 50              push    eax
8057919a ff75d4          push    dword ptr [ebp-2Ch]
8057919d e867feffff      call    nt!PsLookupProcessByProcessId (80579009)
[...]

Bon c’est assez parlant comme appel, NtOpenProcess fait appel à PsLookupProcessByProcessId (fonction documentée en plus) en pushant en premier le PID du process puis un pointeur vers la variable qui va récup l’adresse de l’EPROCESS.

Continuons avec PsLookupProcessByProcessId :

kd> uf nt!PsLookupProcessByProcessId
nt!PsLookupProcessByProcessId:
8057436d 8bff            mov     edi,edi
8057436f 55              push    ebp
80574370 8bec            mov     ebp,esp
80574372 53              push    ebx
80574373 56              push    esi
80574374 64a124010000    mov     eax,dword ptr fs:[00000124h]
8057437a ff7508          push    dword ptr [ebp+8] ; PID
8057437d 8bf0            mov     esi,eax
8057437f ff8ed4000000    dec     dword ptr [esi+0D4h]
80574385 ff35400a5680    push    dword ptr [nt!PspCidTable (80560a40)]
8057438b e84b1cffff      call    nt!ExMapHandleToPointer (80565fdb)
80574390 8bd8            mov     ebx,eax
80574392 85db            test    ebx,ebx
[...]

Ok, on est IN, on est HYPE, on lâche rien !, on voit un superbe ExMapHandleToPointer qui prend en arg, une table (devinez de quel type …) et le PID tu process. Bien sur, la PspCidTable est une HANDLE_TABLE, explorons la :)

kd> dd nt!PspCidTable l 1
80560a40  e1000198    

kd> dt nt!_HANDLE_TABLE e1000198
   +0x000 TableCode        : 0xe1003000
   +0x004 QuotaProcess     : (null)
   +0x008 UniqueProcessId  : (null)
   +0x00c HandleTableLock  : [4] _EX_PUSH_LOCK
   +0x01c HandleTableList  : _LIST_ENTRY [ 0xe10001b4 - 0xe10001b4 ]
   +0x024 HandleContentionEvent : _EX_PUSH_LOCK
   +0x028 DebugInfo        : (null)
   +0x02c ExtraInfoPages   : 0
   +0x030 FirstFree        : 0x764
   +0x034 LastFree         : 0x754
   +0x038 NextHandleNeedingPool : 0x800
   +0x03c HandleCount      : 252
   +0x040 Flags            : 1
   +0x040 StrictFIFO       : 0y1

Cette table sert à la fois pour les PID et les TID, ici il y a 252 valeurs, ce qui signifie qu’on a 252 objets de type process et thread tournant à ce moment là avec chacun leur PID et TID. Dumpons la TableCode :

kd> dd e1003000
e1003000  00000000 fffffffe 80e6fa01 00000000
e1003010  80e6f779 00000000 80e6f321 00000000
e1003020  80e6e031 00000000 80e6eda9 00000000
e1003030  80e6eb21 00000000 80e6e899 00000000
e1003040  80e6e611 00000000 80e6e389 00000000
e1003050  80e6d031 00000000 80e6dda9 00000000
e1003060  80e6db21 00000000 80e6d899 00000000
e1003070  80e6d611 00000000 80e6d389 00000000

On retrouve bien le même schéma que précédemment, sauf qu’ici les access mask sont tous NULL, normal on veut juste récup l’adresse de l’objet. Si on prend par exemple, le process de PID 4 (system), on tombe sur l’entrée à 0xe1003000+8 dont la valeur est 0x80e6fa01.

kd> ?? (0x80e6fa01|0x80000000)&0xfffffff8
unsigned int 0x80e6fa00
kd> !object 0x80e6fa00
Object: 80e6fa00  Type: (80e6f040) Process
    ObjectHeader: 80e6f9e8 (old version)
    HandleCount: 2  PointerCount: 57

W00T on a bien notre pointeur sur le processus, à noté qu’ici on ne pointe par sur l’OBJECT_HEADER mais directement sur le corps de l’objet, c’est à dire l’EPROCESS ou l’ETHREAD.
Ensuite on peut s’amuser à regarder ce que vaut l’entrée suivante :

kd> ?? (0x80e6f779|0x80000000)&0xfffffff8
unsigned int 0x80e6f778
kd> !object  0x80e6f778
Object: 80e6f778  Type: (80e6fe70) Thread
    ObjectHeader: 80e6f760 (old version)
    HandleCount: 0  PointerCount: 2

Cool on est tombé sur le thread primaire du process system (TID=8) :] Il suffit juste de vérif :

kd> !process 80e6fa00 4
PROCESS 80e6fa00  SessionId: none  Cid: 0004    Peb: 00000000  ParentCid: 0000
    DirBase: 00039000  ObjectTable: e1000b78  HandleCount: 214.
    Image: System

        THREAD 80e6f778  Cid 0004.0008  Teb: 00000000 Win32Thread: 00000000 WAIT
        THREAD 80e6e030  Cid 0004.0010  Teb: 00000000 Win32Thread: 00000000 WAIT
        THREAD 80e6eda8  Cid 0004.0014  Teb: 00000000 Win32Thread: 00000000 WAIT
        THREAD 80e6eb20  Cid 0004.0018  Teb: 00000000 Win32Thread: 00000000 WAIT
[...]

Nickel tout correspond parfaitement.

Cette table permet aussi à un anti-rookit de detecter les process dont on a retiré l’EPROCESS de la double liste PsActiveProcessHead. Il suffit de recherché dedans en comparant les PID et TID à ceux des processes/threads existant.

Ouf, j’ai finit, j’espère que vous avez kiffer et que vous comprenez vraiment maintenant ce qu’est un handle. Evidemment si vous codez des softs « normaux » connaître se mécanisme ne vous apportera pas grand chose. Par contre si vous être rootkit designer ca peut servir :p

Références :

Windows Internals Fourth Edition : Chapter 3. System Mechanisms -> Object Manager
Rootkit Futo :
http://www.uninformed.org/?v=3&a=7&t=sumry

Entry Filed under: Non classé

6 Comments

  • 1. Baboon  |  juin 23rd, 2007 at 13:08

    Eheh
    Tres simpa :D
    J’avais failli explorer NtOpenProcess mais ayant effacés toutes mes VM sur un coup de tete ….
    Sinon eh bien bravo , article clair avec des zoulis n’exemple , que demander de plus ;)
    Et en plus un lendemain de fete de la musique ….
    Moi qui ce jour la me suis levé a 16h30 …
    Chapeau ;)


  • 2. overdose  |  juin 30th, 2007 at 11:03

    si j’ai bien comprit les pid/tips ont juste des aoffset dans une table de pointeur.

    Est ce que ca veut dire ke les pid et tId sont completement previsible ?


  • 3. admin  |  juin 30th, 2007 at 14:54

    En effet les PID/TID sont prévisibles. Ils seront crée s dans les entrées libres de la table, cependant pour connaitre ces entrées il faut regarder le champ FirstFree de la PspCidTable. Par exemple, quand on crée un process :

    nt!ExCreateHandle+0x12:
    805671ca 50              push    eax
    kd> p
    nt!ExCreateHandle+0x13:
    805671cb 56              push    esi
    kd> p
    nt!ExCreateHandle+0x14:
    805671cc e8e5feffff      call    nt!ExpAllocateHandleTableEntry (805670b6)
    
    PHANDLE_TABLE_ENTRY
    ExpAllocateHandleTableEntry (
        IN PHANDLE_TABLE HandleTable,
        OUT PEXHANDLE pHandle
        )
    
    kd> dt nt!_HANDLE_TABLE e1000198
       +0x000 TableCode        : 0xe1003000
       +0x004 QuotaProcess     : (null) 
       +0x008 UniqueProcessId  : (null) 
       +0x00c HandleTableLock  : [4] _EX_PUSH_LOCK
       +0x01c HandleTableList  : _LIST_ENTRY [ 0xe10001b4 - 0xe10001b4 ]
       +0x024 HandleContentionEvent : _EX_PUSH_LOCK
       +0x028 DebugInfo        : (null) 
       +0x02c ExtraInfoPages   : 0
       +0x030 FirstFree        : 0x414
       +0x034 LastFree         : 0x3e0
       +0x038 NextHandleNeedingPool : 0x800
       +0x03c HandleCount      : 260
       +0x040 Flags            : 1
       +0x040 StrictFIFO       : 0y1
    kd> dd fce89b98 l 1
    fce89b98  00000000
    kd> p
    nt!ExCreateHandle+0x19:
    805671d1 8bd8            mov     ebx,eax
    kd> dd fce89b98 l 1
    fce89b98  00000414 
    

    Le parametre pHandle pushé est un pointeur qui va recevoir la valeur du PID. Si on regarde son contenu après le call, on voit bien que c’est la valeur du champ FirstFree. Après l’appel, la valeur est mise a jour :

    kd> dt nt!_HANDLE_TABLE e1000198
       +0x000 TableCode        : 0xe1003000
       +0x004 QuotaProcess     : (null) 
       +0x008 UniqueProcessId  : (null) 
       +0x00c HandleTableLock  : [4] _EX_PUSH_LOCK
       +0x01c HandleTableList  : _LIST_ENTRY [ 0xe10001b4 - 0xe10001b4 ]
       +0x024 HandleContentionEvent : _EX_PUSH_LOCK
       +0x028 DebugInfo        : (null) 
       +0x02c ExtraInfoPages   : 0
       +0x030 FirstFree        : 0x408
       +0x034 LastFree         : 0x3e0
       +0x038 NextHandleNeedingPool : 0x800
       +0x03c HandleCount      : 261
       +0x040 Flags            : 1
       +0x040 StrictFIFO       : 0y1
    

  • 4. philou  |  juillet 10th, 2007 at 11:59

    Hum… je crois que je suis très loin du sujet du billet mais…. Korn, à la fête de la musique, tu viens de la ville où on fait du bon vin toi aussi :p ?

    (Non, non, je suis pas tombé ici par hasard XD)


  • 5. Ivanlef0u’s Blog &r&hellip  |  novembre 24th, 2007 at 16:24

    [...] temps. On va ruser comme des renards, sachant qu’un handle n’est qu’au final un indice dans une table, il suffit de crée un handle, de récup sa valeur puis de le ferme, en théorie le handle suivant [...]


  • 6. Geo  |  septembre 23rd, 2010 at 20:43

    Hello, Ivan.

    Je sais pas si tout ça c’est encore frais dans ta tête, mais que se passe-t-il lorsqu’un handle est ouvert par une DLL ? La table est gérée par la DLL elle-même – une fois mappée en mémoire – ou c’est le processus qui importe la DLL – IAT, LoadLibrary, … – qui s’occupe de tout ça ?

    Merci !

    Geo


Trackback this post


Calendar

septembre 2024
L Ma Me J V S D
« fév    
 1
2345678
9101112131415
16171819202122
23242526272829
30  

Most Recent Posts