(73)分析 KeInitializeApc ,了解 KAPC 的初始化
生活随笔
收集整理的這篇文章主要介紹了
(73)分析 KeInitializeApc ,了解 KAPC 的初始化
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
一、回顧
第71篇博客我們分析了 PspTerminateThreadByPointer 函數,其中調用了 KeInitializeApc 函數初始化 KAPC 結果。這次課我們來分析 KeInitializeApc 函數,了解 APC 如何初始化。
PspTerminateThreadByPointer(psdelete.c) 調用 KeInitializeApc
KeInitializeApc (ExitApc,PsGetKernelThread (Thread),OriginalApcEnvironment, // 父進程PsExitSpecialApc, // 釋放APC內存,退出當前線程PspExitApcRundown, // 釋放APC內存PspExitNormalApc, KernelMode, // 內核模式ULongToPtr (ExitStatus)); // 線程退出碼NtQueueApcThread(psctx.c) 調用 KeInitializeApc
KeInitializeApc (Apc,&Thread->Tcb,OriginalApcEnvironment, // 插入到所屬進程(創建線程的那個進程)PspQueueApcSpecialApc, // KernelRoutine , 作用是釋放 APC 內存(ExFreePool)NULL, // RundownRoutine 未指定(PKNORMAL_ROUTINE)ApcRoutine, // 用戶APC總入口 BaseDispatchAPC(3環函數)UserMode, // 用戶模式APCApcArgument1); // 3環APC函數二、KeInitializeApc (apcobj.c)
這個函數比較簡單,就是初始化,最難理解的是 ApcStateIndex ,我已經在注釋里寫清楚了,還是不懂的話,可以結合 KiInsertQueueApc 函數來分析 ApcStateIndex 的用途。
VOID KeInitializeApc (IN PRKAPC Apc, // APC結構體指針IN PRKTHREAD Thread, // 要插入APC的目標線程IN KAPC_ENVIRONMENT Environment, // 四種環境狀態,包括父進程,掛靠進程,當前進程(提供CR3的進程),插入時的當前進程IN PKKERNEL_ROUTINE KernelRoutine, // 不管是用戶APC還是內核APC,這個函數的共同作用是釋放APC;內核APC可能會有額外的功能,如退出、掛起、恢復線程IN PKRUNDOWN_ROUTINE RundownRoutine OPTIONAL, // 如果是用戶APC,這里是NULL;如果是要求退出線程的內核APC,這里是 PspExitApcRundownIN PKNORMAL_ROUTINE NormalRoutine OPTIONAL, // 如果是用戶APC,這里是 BaseDispatchAPC(3環函數);// 如果是內核APC,這里就是內核APC函數IN KPROCESSOR_MODE ApcMode OPTIONAL, // 用戶模式 / 內核模式IN PVOID NormalContext OPTIONAL // 如果是用戶APC,這里就是3環提供的APC函數的參數)/*++Routine Description:This function initializes a kernel APC object. The thread, kernelroutine, and optionally a normal routine, processor mode, and normalcontext parameter are stored in the APC object.分配空間,初始化KAPC結構體Arguments:Apc - Supplies a pointer to a control object of type APC.Thread - Supplies a pointer to a dispatcher object of type thread.Environment - Supplies the environment in which the APC will execute.Valid values for this parameter are: OriginalApcEnvironment,AttachedApcEnvironment, CurrentApcEnvironment, or InsertApcEnvironmentKernelRoutine - Supplies a pointer to a function that is to beexecuted at IRQL APC_LEVEL in kernel mode.RundownRoutine - Supplies an optional pointer to a function that is to becalled if the APC is in a thread's APC queue when the thread terminates.NormalRoutine - Supplies an optional pointer to a function that isto be executed at IRQL 0 in the specified processor mode. If thisparameter is not specified, then the ProcessorMode and NormalContextparameters are ignored.ApcMode - Supplies the processor mode in which the function specifiedby the NormalRoutine parameter is to be executed.NormalContext - Supplies a pointer to an arbitrary data structure which isto be passed to the function specified by the NormalRoutine parameter. Return Value:None.--*/{ASSERT(Environment <= InsertApcEnvironment);//// Initialize standard control object header.//Apc->Type = ApcObject; // 0x12 內核對象類型Apc->Size = sizeof(KAPC);//// Initialize the APC environment, thread address, kernel routine address,// rundown routine address, normal routine address, processor mode, and// normal context parameter. If the normal routine address is null, then// the processor mode is defaulted to KernelMode and the APC is a special// APC. Otherwise, the processor mode is taken from the argument list.////typedef enum _KAPC_ENVIRONMENT {// OriginalApcEnvironment, // 所屬進程(創建線程的進程)// AttachedApcEnvironment, // 掛靠進程// CurrentApcEnvironment, // 當前環境,提供CR3的進程(正常狀態是所屬進程,掛靠狀態是掛靠進程)// InsertApcEnvironment // 插入APC時的環境//} KAPC_ENVIRONMENT;// ApcStateIndex 決定了掛到哪個進程的APC隊列if (Environment == CurrentApcEnvironment) {// 如果要求的是當前狀態,那么就從 Thread->ApcStateIndex 里取值,如果當前沒有掛靠,則是0,;如果掛靠了,就是1.Apc->ApcStateIndex = Thread->ApcStateIndex;} else {ASSERT((Environment <= Thread->ApcStateIndex) || (Environment == InsertApcEnvironment));// 否則就默認插入到所屬進程(創建線程的進程)的APC隊列里Apc->ApcStateIndex = (CCHAR)Environment;}Apc->Thread = Thread; // 目標線程Apc->KernelRoutine = KernelRoutine; // 主要功能是釋放APCApc->RundownRoutine = RundownRoutine; // 可選,退出線程時會用到Apc->NormalRoutine = NormalRoutine; // 如果是用戶APC,這里是 BaseDispatchAPC(3環函數);// 如果是內核APC,這里就是內核APC函數if (ARGUMENT_PRESENT(NormalRoutine)) {Apc->ApcMode = ApcMode; // 0內核,1用戶Apc->NormalContext = NormalContext; // 內核APC:NULL;用戶APC:真正的APC函數} else {Apc->ApcMode = KernelMode;Apc->NormalContext = NIL; // NULL}Apc->Inserted = FALSE;return; }總結
以上是生活随笔為你收集整理的(73)分析 KeInitializeApc ,了解 KAPC 的初始化的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: (72)进程挂靠(attach)使用备用
- 下一篇: (74)分析 APC 插入过程 —— K