内核和用户模式下进程与线程创建
文章目錄
- 內核模式下進程與線程的創建
- 進程創建
- 線程創建
- 用戶模式下進程與線程的創建
內核模式下進程與線程的創建
進程創建
在內核模式中,一個進程的創建是從函數NtCreateProcess開始的。該函數位于文件ntoskrnl.exe中,該文件位于%windir%\system32.它對用戶傳進的部分參數進行簡單處理,然后交給函數NtCreateProcessEx
NTSTATUS NtCreateProcessEx( __out PHANDLE ProcessHandle, //返回進程句柄__in ACCESS_MASK DesiredAccess, //新進程訪問權限__in_opt POBJECT_ATTRIBUTES ObjectAttributes, //進程對象屬性__in HANDLE ParentProcess, //父進程句柄__in ULONG Flags, //標志集合__in_opt HANDLE SectionHandle, //該進程映像文件句柄 __in_opt HANDLE DebugPort, //調試端口對象指針__in_opt HANDLE ExceptionPort, //異常端口對象指針__in ULONG JobMemberLevel //要創建的進程在一個Job集中的級別 );該函數檢查句柄ProcessHandle是否可寫,然后將創建工作交給函數,PspCreateProcess系統中所有的進程的創建工作均是由該函數負責完成的,其創建進程的步驟大致如下:
調用函數ObCreateObject創建windows執行體內核對象EPROCESS,該對象為新進程的進程對象,該對象歸系統所有,并由系統統一管理
調用函數ObReferenceObjectByHandle獲取內存區對象的指針SectionHandle。
根據傳入的端口參數內容初始化新進程對象的相應字段
如果父進程不為空,則創建一個全新的地址空間
調用函數KeInitializeProcess初始化新進程對象的基本優先級,Affinity,進程頁表目錄和超空間的頁幀號
調用函數PspInitializeProcessSecurity從父進程復制一個令牌初始化新進程的安全屬性,并設置進程優先級
調用函數MmInitializeProcessAddressSpace初始化新進程的地址空間,并將映像映射到地址空間;同時加載Ntdll.dll和系統范圍的國家語言支持(NLS)表
調用函數ExCreateHandle在CID句柄表中創建一個進程ID項。CID是客戶身份號(Client ID),一般由進程號和線程號兩部分組成,用于識別某個進程
審計本次進程創建行為,并構造PEB,將新進程假如全局進程鏈表PsActiveProcessHead中
調用函數ObInsertObject將新進程對象插入當前進程的句柄表中
設置進程基本優先級,訪問權限,創建時間。
通過以上步驟,進程對象創建完成。但進程時有“惰性”的,離開了線程,進程的空間只是一個固定在內存中的死的空間而已;直到它的第一個線程被創建和初始化之后,進程中的代碼才能被真正運作起來
線程創建
與進程的創建類似,內核中線程的創建是從函數NtCreateThread開始的。該函數對用戶傳遞來的參數進行簡單檢查,并復制InitialTeb到局部變量CaptureInitialTeb中;處理完參數后,交給函數PspCreateThread。該函數是真正創建線程的函數,其原型如下:
NTSTATUS PspCreateThread( OUT PHANDLE ThreadHandle, //返回線程句柄 IN ACCESS_MASK DesiredAccess, //新線程的訪問權限 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, //新線程對象屬性 IN HANDLE ProcessHandle, //線程所屬進程句柄 IN PEPROCESS ProcessPointer, //指向所屬進程的EPROCESS對象 OUT PCLIENT_ID ClientId OPTIONAL //返回新線程的CLIENT_ID結構 IN PCONTEXT ThreadContext OPTIONAL, //新線程的執行環境 IN PINITIAL_TEB InitialTeb OPTIONAL, //新線程TEB IN PKSTART_POUTINE StartRoutine OPTIONAL, //系統線程啟動函數地址 IN PVOID StartContext //系統線程啟動函數的執行環境 );內核中創建線程的步驟大致如下:
用戶模式下進程與線程的創建
在用戶層,創建一個進程通常使用kernel32.dll中的函數CreateProcess來完成,該函數一旦返回成功,新的進程和進程中的第一個線程就建立起來了。從用戶層的角度看進程創建大致步驟如下:
在內核模式下,系統服務分發函數KiSystemService獲得CPU控制權,它利用當前線程指定的系統服務表,調用執行體層的函數NtCreateProcessEx,開始內核過程得進程創建。執行體層的進程對象建立以后,進程的地址空間完成初始化,EPROCESS中的進程環境塊(PEB)也已完成初始化;例如,跟蹤一段CreateProcess代碼,可以看到陷阱機制
以上代碼時函數Ntdll.ZwCreateSection的調用過程,前面是一系列的函數參數入棧操作,最后通過call指令調用函數。進入到函數內部看,函數Ntdll.ZwCreateSection是一段代理代碼,通過對eax賦值后,為edx指定偏移地址,即可實施call ntdll.KiFastSystemCall調用,如下圖:
其中eax存放系統服務號,從以上反匯編代碼可以看到,系統最終通過指令SYSENTER(Windows XP系統)或者 int 2E(Windows 2000系統)進入內核態執行相應程序
注意:
至此,用戶模式下的進程創建實際上才剛剛開始,因為最終的進程要求給Windows子系統來運行,并由子系統維護進程的狀態,進程的消息等信息
在內核模式中,新線程的啟動例程是KiThreadStartup函數,從WRK中可以獲取到該函數的代碼:
KiThreadStartup函數首先將中斷請求級別(Interrupt ReQuest Level,IRQL)降低到PC_LEVEL,然后進入內核模式調用系統初始的線程函數PspUserThreadStartup。函數PspUserThreadStartup通知緩存管理器預取可執行映像文件的頁面,即該進程上一次啟動的前10s內引用到的頁面。讀取后,將一個用戶模式APC插入線程的用戶APC隊列,此APC例程指向ntdll.dll的LdrInitializeThunk函數,然后函數PspUserThreadStartup返回
總結
以上是生活随笔為你收集整理的内核和用户模式下进程与线程创建的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: PE结构延迟加载导入表
- 下一篇: HOOK虚函数