3.APC的挂入过程
無論是正常狀態還是掛靠狀態,都有兩個APC隊列,一個內核隊列,一個用戶隊列。
每當要掛入一個APC函數時,不管是內核APC還是用戶APC,內核都要準備一個KAPC的數據結構,并且將這個KAPC結構掛到相應的APC隊列中。
kd> dt _kapc nt!_KAPC+0x000 Type //類型APC類型為0x12+0x002 Size //本結構體的大小0x30+0x004 Spare0 //未使用+0x008 Thread //目標線程+0x00c ApcListEntry //APC隊列掛的位置+0x014 KernelRoutine //指向一個函數(調用ExFreePoolWithTag釋放APC)+0x018 RundownRoutine //未使用+0x01c NormalRoutine //用戶APC總入口或者真正的內核apc函數+0x020 NormalContext //內核APC: NULL用戶APC:真正的APC函數 +0x024 SystemArgument1 //APC函數的參數+0x028 SystemArgument2 //APC函數的參數+0x02c ApcStateIndex //掛哪個隊列,有四個值: 0 1 2 3+0x02d ApcMode //內核APC用戶APC+0x02e Inserted //表示本apc是否已掛入隊列掛入前: 0掛入后1+0x000 Type
APC的類型為0x12,windows下任何一種內核對象都有一個類型編號。
+0x014 KernelRoutine
APC執行完畢后,釋放本結構內存
+0x01c NormalRoutine
如果你當前的APC是內核APC,通過它就能找到內核APC函數。
如果你當前的APC是用戶APC,通過它找到的只是用戶APC的總入口并不是用戶APC函數。
+0x020 NormalContext
如果是內核APC這個值為空,如果是用戶APC這個值執行的就是用戶APC函數
+0x02c ApcStateIndex
- =0原始環境
- =1掛靠環境
- =2當前環境
- =3插入APC時的當前環境
正常情況下:
KTHREAD.ApcStatePointer[0] 指向 KTHREAD.ApcState KTHREAD.ApcStatePointer[1] 指向 KTHREAD.SavedApcState掛靠情況下:
KTHREAD.ApcStatePointer[0] 指向 KTHREAD.SavedApcState KTHREAD.ApcStatePointer[1] 指向 KTHREAD.ApcState·
0時無論是在正常還是掛靠的情況下都能正常寫到原來的那個列表中[0]
1時正常情況下寫的就是SavedApcState,掛靠就是ApcState [1]
2 初始化的時候,當前進程的ApcState
3 插入的時候,當前進程的ApcState
在你初始化APC時可能時正常情況也可能是掛靠情況時用3,在你真正插入是它會再做一次判斷。
APC掛入流程
我在3環插入APC調用QueueUserAPC,但是在0環有很多內核函數有很多函數也是可以插入APC的,它可能直接調用KelnitializeApc或者KilsertQueueApc來分配APC并且掛入APC。
KeInitializeApc函數說明
void KeInitializeApc (IN PKAPC Apc,//KAPC指針 (分配好內存的還沒初始化)IN PKTHREAD Thread,//目標線程IN KAPC_ENVIRONMENT TargetEnvironment,//0 1 2 3四種狀態IN PKKERNEL_ROUTINE KernelRoutine//銷毀KAPC的函數地址IN PKRUNDOWN_ROUTINE RundownRoutine OPTIONAL//未使用IN PKNORMAL_ROUTINE NormalRoutine,//用戶APC總入口或者內核apc函數IN KPROCESSOR_MODE Mode,//要插入用戶apc隊列還是內核apc隊列IN PVOID Context//內核APC: NULL 用戶APC:真正的APC函數 ) 1. 2.Thread傳進來會掛到 _KAPC.0x8 Thread 3.TargetEnvironment 傳進來會掛到_KAPC.0x2c ApcStateIndex 4.KernelRoutine 傳進來會掛到_KAPC.0x14 KernelPoutine 5. 6.NormalRoutine 傳進來會掛到_KAPC.0x1c NormalRoutine 7.Mode 傳進來會掛到_KAPC.0x2d ApcMode 8.Context 傳進來會掛到_KAPC.0x20 NormalRoutineKeInsertQueueApc函數說明
BOOLEAN NTAPI KeInsertQueueApc(IN PKAPC Apc,IN PVOID SystemArgument1,IN PVOID SystemArgument2,IN KPRIORITY PriorityBoost);UserApcPending = 1時,用戶apc才能被執行。
Alertable屬性說明(是否運行被APC吵醒):
kd> dt KTHREAD ntdil! KTHREAD ... +0x164 Alertable: UChar ...DWORD SleepEx (DWORD dwMilliseconds, //time-out interval BOOL bAlertable // early completion option );DWORD WaitForSingleObjectEx (HANDLE hHandle,//handle to objectDWORD dwMilliseconds, // time-out interval BOOL bAlertable //alertable option );上面的兩個api的最后一個還是就可以修改KTHREAD->Alertable 的值。 = 1 當前的線程是可以被APC喚醒的 = 0 不可被APC喚醒如果為用戶模式
3個跳轉都沒有實現的話
Alertable總結
總結
以上是生活随笔為你收集整理的3.APC的挂入过程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 2.备用APC队列
- 下一篇: 4.内核APC执行过程