windbg學習筆記 FOR 內核調試(三) --進程句柄表HANDLE_TABLE [轉]
Posted on 2009-01-26 14:54 S.l.e!ep.¢% 閱讀(2777) 評論(2) 編輯 收藏 引用
想當年
初學核編
,
閱讀第三章的內核對象的時候跟看天書沒什么感覺
死命在想到底內核對象
,
句柄是個什么東西
干嘛用的
于是我們工作室的老大就對我說
這篇看過就過了
學到后面你自然會明白的
???
我想也是
,
很多時候感覺學東西的確是這樣
暫時看不懂的先放著
過段時間再看回來就恍然大悟了
.
我前段時間又看了下核編的第三章
唯一的收獲就是能夠大概了解到
hanle
這個所謂的索引的作用了
.
我也跟工作室的小學弟講過我理解的句柄
(
但是講完看到他們茫然的表情
~
郁悶了
~
沒辦法
可能知識面
實踐經驗等還不足以理解我說的東西吧
或者是被我們可愛的鼠仙傳染了
也開始學著他講天書了
~)
? ?
以下講的都是我所理解的東東
,
有錯誤的話也在所難免了
???
首先說說
HANDLE
這個是個什么東西
在
WinNT.h
里面查到其定義如下
typedef
void *HANDLE;
哈
~
這下子明白了
原來
HANDLE
就是一個無類型指針
,
只是充當內核對象在進程句柄表里面的索引
,
相當于在進程句柄表內的一個
ID
號
.
進程句柄表
個人理解就是存放這個進程所創建的內核對象在內核地址空間位置的一個表
(
你可以理解為數組
),
那么什么是內核對象呢
?
內核對象只不過是系統資源的一種抽象
,
我新建了個進程
,
那么系統內部就會為這個進程分配資源
,
然后創建一個內核對象
,
返回一個句柄
通過這個句柄我們可以找到進程在內核空間的位置
,
其實也就是進程對應的內核對象的位置
,
在內核里面
,
內核對象就是一堆數據結構
,
只不過數據結構很大
,
里面存放著這個進程的信息
,
這樣系統只要改變這個結構里面的數值就能操作進程
,
如此而已
~
嘿嘿
消化一下上面說的
接下來就說進程句柄表了
,
進程句柄表是保存在進程的內核對象里面的
進程的內核對象就是個
EPROCESS
的結構
結構原型如下
:
kd> dt _EPROCESS
ntdll!_EPROCESS
?? +0x000 Pcb????????????? : _KPROCESS
?? +0x
?? +0x070 CreateTime?????? : _LARGE_INTEGER
?? +0x078 ExitTime???????? : _LARGE_INTEGER
?? +0x080 RundownProtect?? : _EX_RUNDOWN_REF
?? +0x084 UniqueProcessId? : Ptr32 Void
?? +0x088 ActiveProcessLinks : _LIST_ENTRY
?? +0x090 QuotaUsage?????? : [3] Uint4B
?? +0x
?? +0x
?? +0x
?? +0x0b0 VirtualSize????? : Uint4B
?? +0x0b4 SessionProcessLinks : _LIST_ENTRY
?? +0x0bc DebugPort??????? : Ptr32 Void
?? +0x
??
+0x
?? +0x
?? +0x0cc WorkingSetLock?? : _FAST_MUTEX
?? +0x0ec WorkingSetPage?? : Uint4B
?? +0x
?? +0x110 HyperSpaceLock?? : Uint4B
?? +0x114 ForkInProgress?? : Ptr32 _ETHREAD
?? +0x118 HardwareTrigger? : Uint4B
??
+0x
?? +0x120 VadHint????????? : Ptr32 Void
??
+0x124 CloneRoot??????? : Ptr32 Void
?? +0x128 NumberOfPrivatePages : Uint4B
?? +0x
?? +0x130 Win32Process???? : Ptr32 Void
?? +0x134 Job????????????? : Ptr32 _EJOB
?? +0x138 SectionObject??? : Ptr32 Void
?? +0x
?? +0x140 QuotaBlock?????? : Ptr32 _EPROCESS_QUOTA_BLOCK
?? +0x144 WorkingSetWatch? : Ptr32 _PAGEFAULT_HISTORY
?? +0x148 Win32WindowStation : Ptr32 Void
?? +0x
?? +0x150 LdtInformation?? : Ptr32 Void
?? +0x154 VadFreeHint????? : Ptr32 Void
?? +0x158 VdmObjects?????? : Ptr32 Void
?? +0x
?? +0x160 PhysicalVadList? : _LIST_ENTRY
?? +0x168 PageDirectoryPte : _HARDWARE_PTE_X86
?? +0x168 Filler?????????? : Uint8B
?? +0x170 Session????????? : Ptr32 Void
?? +0x174 ImageFileName??? : [16] UChar
?? +0x184 JobLinks???????? : _LIST_ENTRY
?? +0x
?? +0x190 ThreadListHead?? : _LIST_ENTRY
?? +0x198 SecurityPort???? : Ptr32 Void
?? +0x
?? +0x
?? +0x
?? +0x
?? +0x
?? +0x1b0 Peb????????????? : Ptr32 _PEB
?? +0x1b4 PrefetchTrace??? : _EX_FAST_REF
?? +0x1b8 ReadOperationCount : _LARGE_INTEGER
?? +0x
?? +0x
?? +0x1d0 ReadTransferCount : _LARGE_INTEGER
?? +0x1d8 WriteTransferCount : _LARGE_INTEGER
?? +0x1e0 OtherTransferCount : _LARGE_INTEGER
?? +0x1e8 CommitChargeLimit : Uint4B
?? +0x1ec CommitChargePeak : Uint4B
?? +0x
?? +0x
?? +0x
?? +0x238 LastFaultCount?? : Uint4B
?? +0x
?? +0x240 NumberOfVads???? : Uint4B
?? +0x244 JobStatus??????? : Uint4B
?? +0x248 Flags??????????? : Uint4B
?? +0x248 CreateReported?? : Pos 0, 1 Bit
?? +0x248 NoDebugInherit?? : Pos 1, 1 Bit
?? +0x248 ProcessExiting?? : Pos 2, 1 Bit
?? +0x248 ProcessDelete??? : Pos 3, 1 Bit
?? +0x248 Wow64SplitPages? : Pos 4, 1 Bit
?? +0x248 VmDeleted??????? : Pos 5, 1 Bit
?? +0x248 OutswapEnabled?? : Pos 6, 1 Bit
?? +0x248 Outswapped?????? : Pos 7, 1 Bit
?? +0x248 ForkFailed?????? : Pos 8, 1 Bit
?? +0x248 HasPhysicalVad?? : Pos 9, 1 Bit
?? +0x248 AddressSpaceInitialized : Pos 10, 2 Bits
?? +0x248 SetTimerResolution : Pos 12, 1 Bit
?? +0x248 BreakOnTermination : Pos 13, 1 Bit
?? +0x248 SessionCreationUnderway : Pos 14, 1 Bit
?? +0x248 WriteWatch?????? : Pos 15, 1 Bit
?? +0x248 ProcessInSession : Pos 16, 1 Bit
?? +0x248 OverrideAddressSpace : Pos 17, 1 Bit
?? +0x248 HasAddressSpace? : Pos 18, 1 Bit
?? +0x248 LaunchPrefetched : Pos 19, 1 Bit
?? +0x248 InjectInpageErrors : Pos 20, 1 Bit
?? +0x248 VmTopDown??????? : Pos 21, 1 Bit
?? +0x248 Unused3????????? : Pos 22, 1 Bit
?? +0x248 Unused4????????? : Pos 23, 1 Bit
?? +0x248 VdmAllowed?????? : Pos 24, 1 Bit
?? +0x248 Unused?????????? : Pos 25, 5 Bits
?? +0x248 Unused1????????? : Pos 30, 1 Bit
?? +0x248 Unused2????????? : Pos 31, 1 Bit
?? +0x
?? +0x250 NextPageColor??? : Uint2B
?? +0x252 SubSystemMinorVersion : UChar
?
? +0x253 SubSystemMajorVersion : UChar
?? +0x252 SubSystemVersion : Uint2B
?? +0x254 PriorityClass??? : UChar
?? +0x255 WorkingSetAcquiredUnsafe : UChar
?? +0x258 Cookie?????????? : Uint4B
????
看
~
變態的長
~
我們可以看到紅色標注的那個結構成員
,
這個就是進程句柄表的地址了
,
它是一個
handle_table
結構的東東
~HOHO~
看看這個是什么結構
?
kd> dt _handle_table
ntdll!_HANDLE_TABLE
?? +0x000 TableCode??????? : Uint4B
?? +0x004 QuotaProcess???? : Ptr32 _EPROCESS
?? +0x008 UniqueProcessId? : Ptr32 Void
?? +0x
?? +0x
?? +0x024 HandleContentionEvent : _EX_PUSH_LOCK
?? +0x028 DebugInfo??????? : Ptr32 _HANDLE_TRACE_DEBUG_INFO
?? +0x
?? +0x030 FirstFree??????? : Uint4B
?? +0x034 LastFree???????? : Uint4B
?? +0x038 NextHandleNeedingPool : Uint4B
?? +0x
?? +0x040 Flags??????????? : Uint4B
?? +0x040 StrictFIFO?????? : Pos 0, 1 Bit
呵呵
結構大小尚可接受
~
那么在這個句柄表內
~
我們的句柄信息到底藏在哪里咧
?
就是在結構變量
TableCode
這里找
,
怎么找咧
?
看了下網上的
WRK
代碼
大概明白他們的思路
原來
TableCode
是個
4
字節的數值
,
這個數值的低
2
位記錄著句柄表的級數
,
什么意思咧
?
一會下面會講到
,
通過句柄值我們就可以在句柄表內查到所謂的內核對象了
不過這里面又有好多細節的東西
~
句柄需要轉換才能查到內核對象地址
,
那么我們就邊說邊做的
涉及到的東西我在補充
我們先用
windbg
來看看進程信息
(
以下涉及到的
WINDBG
命令請到學習筆記
一
二
文章去看
~)
kd> !handle 0 2 6e8
processor number 0, process 000006e8
Searching for Process with Cid == 6e8
PROCESS 812e9408? SessionId: 0? Cid: 06e8??? Peb: 7ffd5000? ParentCid: 05e0
??? DirBase:
Image: ctfmon.exe
Handle table at e
………………….
0114
: Object: e1688498? GrantedAccess: 00000002 Entry: e
Object: e1688498? Type: (81592560) Section
ObjectHeader: e1688480 (old version)
………………….
嘿嘿
6e8
是這個進程的
PID ?
內核對象的句柄值是
0114?
其他參數不說明了
自己看幫助吧
我們可以看到
PID
為
6e8
的進程的一些詳細信息
還有這個進程下的
n
多內核對象
我就顯示了
1
個
,
省的看的眼花
那么我們就開始用
windbg
研究這個句柄表吧
?
首先
我們從上面信息知道
ctfmon.exe
這個進程的內核對象地址是在
812e9408
kd> dt _eprocess 812e9408
ntdll!_EPROCESS
……
?? +0x
……
?? +0x174 ImageFileName??? : [16]? "ctfmon.exe"
……
????
省略了
N
多內容
只把重要內容顯示出來了
可以看到
這個進程名的確是
ctfmon.exe
那么它所對應的句柄表的位置在這里
:0xe190e928??
走到這里瞧下
kd> dt _handle_table 0xe190e928
ntdll!_HANDLE_TABLE
?? +0x000 TableCode??????? : 0xe
?? +0x004 QuotaProcess???? : 0x812e9408 _EPROCESS
?? +0x008 UniqueProcessId? : 0x000006e8
?? +0x
?? +0x
?? +0x024 HandleContentionEvent : _EX_PUSH_LOCK
?? +0x028 DebugInfo??????? : (null)
?? +0x
?? +0x030 FirstFree??????? : 0x118
?? +0x034 LastFree???????? : 0
?? +0x038 NextHandleNeedingPool : 0x800
?? +0x
?? +0x040 Flags??????????? : 0
?? +0x040 StrictFIFO?????? : 0y0
可以看到
TableCode
的地址在
0xe
這里就得說明下句柄表
,
句柄表分三層
頂層句柄表大小
1K
可存放
256
個元素
,
每個元素占
4bit ,
中層表大小
1K
可存放
256
個元素
,
每個元素占
4bit ,
下層表大小
2K
可放
256
個元素
每個元素
8bit .
我們可以看到
TableCode
的低
2
位是
0
表示這個句柄表只有
1
級
,
那么只要句柄值的低
10
位乘以
2
就是該內核對象的指針在句柄表里面的位置了
.
kd> dd e
e
e
看到
e1688481
了吧
?
這個就是內核對象頭的地址
,
由于對象頭和對象體偏移量是
0x18,
所以加上
0x18
就可以找到對應的內核對象了
kd> !object e1688481+17
Object: e1688498? Type: (81592560) Section
??? ObjectHeader: e1688480 (old version)
??? HandleCount: 9? PointerCount: 10
Directory Object: e1432248? Name: ShimSharedMemory
呃
….
這個是系統是
sp3
的
,
好像跟
sp2
的有點出入
.
偏移量加
0x17
才是真正的對象頭
,
而不是加
0x18…..
麻煩哪位高手解釋一下
對比剛才上面那個對象信息
0114
: Object: e1688498? GrantedAccess: 00000002 Entry: e
Object: e1688498? Type: (81592560) Section
ObjectHeader: e1688480 (old version)
一樣的
?
呵呵
~~
剛才大概把用內核句柄查找內核對象的過程演示了一下
,
反正大概操作系統也是這么利用句柄找內核對象的
,
但是
…..
巨多的疑問隨之產生
….
<!--[if !supportLists]--> 1.??? <!--[endif]--> 對象頭跟對象體到底是個什么結構?
<!--[if !supportLists]--> 2.??? <!--[endif]--> 咋個sp3下,對象頭和對象體的偏移確實是0x17 但是我根據句柄找到的對象頭的地址跟實際內核的對象頭的地址竟然相差1?到底是我哪里做錯了?
<!--[if !supportLists]--> 3.??? <!--[endif]--> 其實剛才只是演示了句柄表級數為0時的情況,還有句柄表為1級(TableCode低2位為01),2級的(TableCode低3位為10)的情況,但是這個我倒是疑惑不少,到底系統是怎么管理這張系統表的?
個人理解是這樣的
,
如果剛開始分配的的是
0
級表
,
那么可以存放
512
個對象指針
,
但是如果內核對象多出了
512
系統會分配個中層表
,
但是我看到的中層表計算偏移的公式是這樣的
TableCode
地址
+
中層偏移
*4+
低層偏移
*2??
那么當內核對象多出
512
的時候內存有是如何分配的呢
?
貌似跟
2k
的分配方式不同了
~
望高人指點
~
參考文獻: