2.备用APC队列
如果想讓線程做什么事情,就給它的APC隊列里面掛一個APC。
kd> dt _kthread nt!_KTHREAD ... +0x034 ApcState : _KAPC_STATE//APC ... +0x138 ApcStatePointer : [2] Ptr32 _KAPC_STATE//APC指針 ... +0x14c SavedApcState : _KAPC_STATE//備用APC ... +0x165 ApcStateIndex : UChar//線程狀態(tài) +0x166 ApcQueueable : UChar//當前成員是否允許插入APC ...SavedApcState的意義
線程APC隊列中的APC函數(shù)都是與進程相關聯(lián)的,具體點說: A進程的, T線程中的所有APC函數(shù),要訪問的內(nèi)存地址都是A進程的。
但線程是可以掛靠到其他的進程:比如A進程的線程T,通過修改 Cr3(改為B進程的頁目錄基址),就可以訪問B進程地址空間,即所謂"進程掛靠".
當T線程掛靠B進程后, APC隊列中存儲的卻仍然是原來的APC!具體,點說,比如某個APC函數(shù)要讀取一個地址為0x12345678的數(shù)據(jù),如果此時進行 讀取,讀到的將是B進程的地址空間,這樣邏輯就錯誤了!
為了避免混亂,在T線程掛靠B進程時,會將ApcState中的值暫時存儲到SavedApcState中,等回到原進程A時,再將APC隊列恢復
SavedApcState又稱為備用APC隊列。
掛靠環(huán)境下ApcState的意義
在掛靠的環(huán)境下,也是可以先線程APC隊列插入APC的,那這種情況下, 使用的是哪個APC隊列呢?
A進程的T線程掛靠B進程 A是T的所屬進程 B是T的掛靠進程
ApcState: B進程相關的APC函數(shù)
SavedApcState: A進程相關的APC函數(shù)
在正常情況下,當前進程就是所屬進程A,如果是掛靠情況下,當前進程就是掛靠進程B.
+0x138 ApcStatePointer
為了操作方便, KTHREAD結構體中定義了一個指針數(shù)組ApcStatePointer ,長度為2.
正常情況下:
ApcStatePointer[0] 指向 ApcState
ApcStatePointer(1] 指向 SavedApcState
掛靠情況下:
ApcStatePointer(0] 指向 SavedApcState
ApcStatePointer(1] 指向 ApcState
+0x165 ApcStatelndex
ApcStatelndex用來標識當前線程處于什么狀態(tài):
0正常狀態(tài)
1掛靠狀態(tài)
ApcStatePointer與ApcStatelndex組合尋址
正常情況下,向ApcState隊列中插入APC時:
- ApcStatePointer[0] 指向 ApcState 此時 ApcStatelndex的值為0
- ApcStatePointer[ApcStatelndex] 指向ApcState
掛靠情況下,向ApcState隊列中插入APC時:
- ApcStatePointer[1]指向ApcState此時ApcStatelndex的值為1
- ApcStatePointer[ApcStateIndex] 指向 ApcState
無論什么環(huán)境下, ApcState Pointer[ApcStateIndex]指向的都是ApcState ApcState則總是表示線程當前使用的apc狀
+0x166 ApcQueueable
ApcQueueable用于表示是否可以向線程的APC隊列中插入APC。
當線程正在執(zhí)行退出的代碼時,會將這個值設置為0,如果此時執(zhí)行.插入APC的代碼(KelnsertQueueApc后面會講),在插入函數(shù)中會判斷這個值的狀態(tài),如果為0,則插入失敗。
總結
- 上一篇: 1.APC机制
- 下一篇: 3.APC的挂入过程