XP 핸들 테이블을 추적해 주어진 핸들값에 해당하는 오브젝트를 찾아내는 과정을 정리해 본다.
1: kd> !process 885fcba0
PROCESS 885fcba0 SessionId: 0 Cid: 04cc Peb: 7ffd5000 ParentCid: 06d4
DirBase: 0a380460 ObjectTable: e3297918 HandleCount: 321.
Image: MyApp.exe
...
1: kd> dt _HANDLE_TABLE e3297918
nt!_HANDLE_TABLE
+0x000 TableCode : 0xe7794000
+0x004 QuotaProcess : 0x885fcba0 _EPROCESS
+0x008 UniqueProcessId : 0x000004cc Void
+0x00c HandleTableLock : [4] _EX_PUSH_LOCK
+0x01c HandleTableList : _LIST_ENTRY [ 0x80566ba8 - 0xe1141c8c ]
+0x024 HandleContentionEvent : _EX_PUSH_LOCK
+0x028 DebugInfo : (null)
+0x02c ExtraInfoPages : 0n0
+0x030 FirstFree : 0x544
+0x034 LastFree : 0x5d0
+0x038 NextHandleNeedingPool : 0x800
+0x03c HandleCount : 0n321
+0x040 Flags : 0
+0x040 StrictFIFO : 0y0
이중에서 실제 핸들 테이블 내용에 해당하는 부분이 TableCode다.
1: kd> dc 0xe7794000
e7794000 00000000 fffffffe e1009529 000f0003 ........).......
e7794010 e19a61a9 00000003 87b87a31 00100020 .a......1z.. ...
e7794020 8878d951 00100020 e1aad391 000f000f Q.x. ...........
e7794030 e6b9f4c9 021f0001 89af54f1 000f037f .........T......
e7794040 87d192c1 00100020 87ce43a9 00100020 .... ....C.. ...
e7794050 87c6a171 021f0003 89b00601 000f01ff q...............
e7794060 89af54f1 000f037f 890726d1 00100003 .T.......&......
e7794070 8852d911 00100003 e6197e81 020f003f ..R......~..?...
잘 보면 8바이트 단위로 규칙적인 모양을 가지고 있는 것을 알 수 있다.
첫번째 8바이트가 핸들 0의 오브젝트, 두번째 8바이트가 핸들 4의 오브젝트 이런 식이다. (핸들값이 4씩 증가하므로...)
이 8바이트는 _HANDLE_TABLE_ENTRY이고 아래와 같은 구조다.
1: kd> dt _HANDLE_TABLE_ENTRY
nt!_HANDLE_TABLE_ENTRY
+0x000 Object : Ptr32 Void
+0x004 GrantedAccess : Uint4B
(사실 UNION 구조체인데 설명에 불필요한 필드는 생략했다)
따라서 이 프로세스 안에서의 핸들 180의 오브젝트 위치는 아래와 같이 구할 수 있다.
1: kd> dd 0xe7794000 + (180/4) * 8
e7794300 899fcac1 001f0003 8844c241 00100003
e7794310 8819b139 001f0001 884d5229 001f0003
e7794320 88675781 021f01ff 87cce699 00100003
e7794330 88104831 001f0001 87da1459 001f0001
e7794340 87cea2b9 00000a84 87cc5b51 001f03ff
e7794350 89a49199 001f0003 89b2e251 001f0003
e7794360 e30433d9 000f01ff 87cc5b51 001f03ff
e7794370 e7675639 0002001f 87d47961 021f0003
899fcac1가 오브젝트인데 딱 보니 최하위 비트를 어떤 플래그로 사용하고 있는 것 같다.
어떤 플래그인지는 찾아보지 않았는데 오브젝트 포인터를 사용하려면 이 플래그를 제거해서 899fcac0를 사용해야 한다.
이 포인터 주소는 사실 오브젝트 헤더의 포인터다.
1: kd> dt _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
오브젝트 헤더 + 18이 실제 오브젝트의 포인터이므로 아래와 같이 오브젝트를 확인할 수 있다.
1: kd> !object 899fcac0+18
Object: 899fcad8 Type: (89bea6f0) Event
ObjectHeader: 899fcac0 (old version)
HandleCount: 1 PointerCount: 2
MyApp.exe에서 핸들 0x180은 이벤트 오브젝트라는 것을 확인할 수 있다.