Win2k에서 커널 핸들 테이블을 사용해야 하는데 이게 XP와 달라서 삽질한 내용이다.
요즘 세상에 Win2k를 위한 정보가 쓸모 있을까 싶지만 다른 데는 없는 정보이니 그냥 적어둔다. ^^
[XP의 커널 핸들 테이블 주소]
XP에서는 커널 핸들 테이블은 시스템 프로세스의 핸들 테이블을 의미한다.
다음과 같이 확인 할수 있다.
80561e38 e1001d28
ObpKernelHandleTable 내부 변수에 저장된 e1001d28이 커널 핸들 테이블 주소다.
이제 시스템 프로세스의 핸들 테이블을 찾아 보자.
PROCESS 8133e7f8 SessionId: none Cid: 0004 Peb: 00000000 ParentCid: 0000
DirBase: 00039000 ObjectTable: e1001d28 HandleCount: 230.
Image: System
kd> dt 8133e7f8 _EPROCESS
nt!_EPROCESS
+0x000 Pcb : _KPROCESS
+0x06c ProcessLock : _EX_PUSH_LOCK
+0x070 CreateTime : _LARGE_INTEGER 0x0
+0x078 ExitTime : _LARGE_INTEGER 0x0
+0x080 RundownProtect : _EX_RUNDOWN_REF
+0x084 UniqueProcessId : 0x00000004
+0x088 ActiveProcessLinks : _LIST_ENTRY [ 0x81193b48 - 0x80562758 ]
+0x090 QuotaUsage : [3] 0
+0x09c QuotaPeak : [3] 0
+0x0a8 CommitCharge : 7
+0x0ac PeakVirtualSize : 0x371000
+0x0b0 VirtualSize : 0x1d2000
+0x0b4 SessionProcessLinks : _LIST_ENTRY [ 0x0 - 0x0 ]
+0x0bc DebugPort : (null)
+0x0c0 ExceptionPort : (null)
+0x0c4 ObjectTable : 0xe1001d28 _HANDLE_TABLE
...
시스템 프로세스의 ObjectTable 필드에 같은 값이 들어 있는 것을 볼 수 있다.
따라서 코드를 작성할 때는 간단히 다음과 같은 형식으로 구해도 된다.
[2K의 커널 핸들 테이블 주소]
2K에서는 커널 핸들 테이블은 시스템 프로세스의 핸들 테이블을 의미하지 않는다.
위과 같은 방법으로 확인 할 수 있다.
8046e438 820b7608
ObpKernelHandleTable 내부 변수에 저장된 820b7608이 커널 핸들 테이블 주소다.
이제 시스템 프로세스의 핸들 테이블을 찾아 보자.
PROCESS 82083be0 SessionId: 0 Cid: 0008 Peb: 00000000 ParentCid: 0000
DirBase: 00030000 ObjectTable: 820b7688 TableSize: 132.
Image: System
nt!_EPROCESS
+0x000 Pcb : _KPROCESS
+0x06c ExitStatus : 0x103
+0x070 LockEvent : _KEVENT
+0x080 LockCount : 1
+0x088 CreateTime : _LARGE_INTEGER 0x0
+0x090 ExitTime : _LARGE_INTEGER 0x0
+0x098 LockOwner : (null)
+0x09c UniqueProcessId : 0x00000008
+0x0a0 ActiveProcessLinks : _LIST_ENTRY [ 0x81f96780 - 0x8046e460 ]
+0x0a8 QuotaPeakPoolUsage : [2] 0
+0x0b0 QuotaPoolUsage : [2] 0
+0x0b8 PagefileUsage : 6
+0x0bc CommitCharge : 6
+0x0c0 PeakPagefileUsage : 0x27
+0x0c4 PeakVirtualSize : 0x1d3000
+0x0c8 VirtualSize : 0x1b0000
+0x0d0 Vm : _MMSUPPORT
+0x118 SessionProcessLinks : _LIST_ENTRY [ 0x0 - 0x0 ]
+0x120 DebugPort : (null)
+0x124 ExceptionPort : (null)
+0x128 ObjectTable : 0x820b7688 _HANDLE_TABLE
...
시스템 프로세스의 ObjectTable 필드에 다른 값이 들어 있는 것을 볼 수 있다.
이것이 의미하는 바는...
2K에서는 시스템 프로세스의 핸들 테이블은 그냥 시스템 프로세스의 핸들 테이블이고,
커널 핸들 테이블은 시스템 프로세스와 직접 연결되어 있지 않다는 것이다.
[2K 에서 커널 핸들 테이블을 사용하려면 어떻게 해야 하나?]
몇 시간의 구글링 끝에 단서를 하나 찾을 수 있었다.
커널 내부 변수중 하나인 핸들 테이블 리스트였다.
프로세스마다 존재하는 핸들 테이블은 리스트로 연결되어 있다.
커널 핸들 테이블이 직접 시스템 프로세스에 존재하지는 않지만 이것도 핸들 테이블이므로 저 리스트에 연결되어 있을 것이라는 생각이 들었다.
핸들 테이블을 리스트를 쭉 살펴보면 다음과 같다.
8046dda8 820b76dc 81f11b1c 00000000 00000000
820b76dc 820b765c 8046dda8 00040000 00000000
820b765c 81f96a5c 820b76dc 00040000 00000000
81f96a5c 81f66f1c 820b765c 00040000 00000000
81f66f1c 81f667fc 81f96a5c 00040000 00000000
...
이 리스트는 HANDLE_TABLE 구조체에서 HandleTableList 로 연결된 리스트이다.
nt!_HANDLE_TABLE
+0x000 Flags : Uint4B
+0x004 HandleCount : Int4B
+0x008 Table : Ptr32 Ptr32 Ptr32 _HANDLE_TABLE_ENTRY
+0x00c QuotaProcess : Ptr32 _EPROCESS
+0x010 UniqueProcessId : Ptr32 Void
+0x014 FirstFreeTableEntry : Int4B
+0x018 NextIndexNeedingPool : Int4B
+0x01c HandleTableLock : _ERESOURCE
+0x054 HandleTableList : _LIST_ENTRY
+0x05c HandleContentionEvent : _KEVENT
따라서 핸들 테이블의 주소는 (리스트주소 - 54) 이다.
그러면 핸들 테이블들을 하나씩 살펴보자.
첫번째 핸들 테이블의 주소는 820b76dc - 54 이다.
이것은 누구의 핸들 테이블인지 보자.
nt!_HANDLE_TABLE
+0x000 Flags : 0
+0x004 HandleCount : 0x84
+0x008 Table : 0xe1002000 -> 0xe1002400 -> 0xe1002800 _HANDLE_TABLE_ENTRY
+0x00c QuotaProcess : (null)
+0x010 UniqueProcessId : 0x00000008
+0x014 FirstFreeTableEntry : 0x85
+0x018 NextIndexNeedingPool : 0x100
+0x01c HandleTableLock : _ERESOURCE
+0x054 HandleTableList : _LIST_ENTRY [ 0x820b765c - 0x8046dda8 ]
+0x05c HandleContentionEvent : _KEVENT
ProcessId 가 8 인걸 보니 시스템 프로세스 같다.
그러고 보니 위에서 찾았던 시스템 프로세스의 핸들 테이블 주소와 일치한다.
두번째 핸들 테이블의 주소는 820b765c - 54 이다.
nt!_HANDLE_TABLE
+0x000 Flags : 0
+0x004 HandleCount : 0x24
+0x008 Table : 0xe1003000 -> 0xe1003400 -> 0xe1003800 _HANDLE_TABLE_ENTRY
+0x00c QuotaProcess : (null)
+0x010 UniqueProcessId : (null)
+0x014 FirstFreeTableEntry : 0x29
+0x018 NextIndexNeedingPool : 0x100
+0x01c HandleTableLock : _ERESOURCE
+0x054 HandleTableList : _LIST_ENTRY [ 0x81f96a5c - 0x820b76dc ]
+0x05c HandleContentionEvent : _KEVENT
오... 주소가 위에서 봤던 커널 핸들 테이블 주소와 일치한다.
ProcessId 가 0으로 설정되어 있는 핸들 테이블이 커널 핸들 테이블인 것이다.
세번째 핸들 테이블의 주소는 81f96a5c -54 이다.
nt!_HANDLE_TABLE
+0x000 Flags : 0
+0x004 HandleCount : 0x21
+0x008 Table : 0xe1364000 -> 0xe1364400 -> 0xe1364800 _HANDLE_TABLE_ENTRY
+0x00c QuotaProcess : 0x81f966e0 _EPROCESS
+0x010 UniqueProcessId : 0x0000008c
+0x014 FirstFreeTableEntry : 0x23
+0x018 NextIndexNeedingPool : 0x100
+0x01c HandleTableLock : _ERESOURCE
+0x054 HandleTableList : _LIST_ENTRY [ 0x81f66f1c - 0x820b765c ]
+0x05c HandleContentionEvent : _KEVENT
이제 OuotaProcess와 UniqueProcessId가 나타난다.
PROCESS 81f966e0 SessionId: 0 Cid: 008c Peb: 7ffdf000 ParentCid: 0008
DirBase: 034a4000 ObjectTable: 81f96a08 TableSize: 33.
Image: smss.exe
이것은 smss.exe 프로세스의 핸들 테이블이다.
이후로는 실행중인 프로세스들의 핸들 테이블이 이어진다.
다행히 핸들 테이블이 리스트로 엮여 있어서 프로세스와 연결되어 있지 않은 ObpKernelHandleTable을 찾을 수 있었다. ^^b