日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

内核和用户模式下进程与线程创建

發布時間:2025/3/21 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 内核和用户模式下进程与线程创建 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • 內核模式下進程與線程的創建
    • 進程創建
    • 線程創建
  • 用戶模式下進程與線程的創建

內核模式下進程與線程的創建

進程創建

在內核模式中,一個進程的創建是從函數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 //系統線程啟動函數的執行環境 );

    內核中創建線程的步驟大致如下:

  • 根據進程句柄獲得進程對象并將其放到局部變量中
  • 調用函數ObCreateObject創建線程對象ETHREAD,并初始化
  • 獲取進程的RundownProtect鎖,以免線程創建過程中該進程被當掉
  • 創建線程環境塊(TEB),并用InitTeb函數進行初始化;然后,利用ThreadContext中的程序指針eip設置線程的啟動地址StartAddress字段,并且將ThreadContext的eax寄存器設置到線程的Win32StartAddress字段。完成這些操作后,調用KeInitThread函數初始化新線程的一些屬性
  • 鎖住進程,并將進程的活動線程數量加1,然后調用函數ObInsertObject把新線程加入到進程的線程鏈中
  • 調用函數KeStartThread,新線程即可運行
  • 用戶模式下進程與線程的創建

    在用戶層,創建一個進程通常使用kernel32.dll中的函數CreateProcess來完成,該函數一旦返回成功,新的進程和進程中的第一個線程就建立起來了。從用戶層的角度看進程創建大致步驟如下:

  • 調用函數CreateProcessW打開指定的可執行映像文件
  • 調用ntdll.dll中的存根函數NtCreateProcessEx,該函數利用處理器的陷阱基址切換到內核模式下
    在內核模式下,系統服務分發函數KiSystemService獲得CPU控制權,它利用當前線程指定的系統服務表,調用執行體層的函數NtCreateProcessEx,開始內核過程得進程創建。執行體層的進程對象建立以后,進程的地址空間完成初始化,EPROCESS中的進程環境塊(PEB)也已完成初始化;例如,跟蹤一段CreateProcess代碼,可以看到陷阱機制

    以上代碼時函數Ntdll.ZwCreateSection的調用過程,前面是一系列的函數參數入棧操作,最后通過call指令調用函數。進入到函數內部看,函數Ntdll.ZwCreateSection是一段代理代碼,通過對eax賦值后,為edx指定偏移地址,即可實施call ntdll.KiFastSystemCall調用,如下圖:

    其中eax存放系統服務號,從以上反匯編代碼可以看到,系統最終通過指令SYSENTER(Windows XP系統)或者 int 2E(Windows 2000系統)進入內核態執行相應程序
  • PEB創建完成后,意味著進程的創建暫時告一段落。這時候還必須為進程創建第一個線程,通過調用函數NtCreateThread構造一個可供第一個線程運行的環境,如堆的大小,初始線程棧的大小等。這些值的模式初始值來自于PE文件頭部相應字段,ntdll.dll中的該函數依舊將任務交由執行層的NtCreateThread來完成。執行體層的線程對象ETHREAD建立以后,線程的ID,TEB等也就完成了初始化
  • 進程的第一個線程的啟動函數是kernel32.dll中的BaseProcessStart函數(其他線程則是調用BaseThreadStart函數),此時的線程是被掛起的,要等到進程完全初始化完成后才真正開始
    注意:
    至此,用戶模式下的進程創建實際上才剛剛開始,因為最終的進程要求給Windows子系統來運行,并由子系統維護進程的狀態,進程的消息等信息
  • kernel32.dll向windows子系統發送一個消息, 該消息包含了剛建立的進程和線程的相關信息;Windows子系統csrss.exe接收到此消息后,開始在系統內部建立進程環境;最后,以顯示應用程序啟動光標作為進程環境創建結束
  • 當Windows子系統已經知道并登記了新進程和線程后,先前掛起的初始線程被允許恢復執行
    在內核模式中,新線程的啟動例程是KiThreadStartup函數,從WRK中可以獲取到該函數的代碼:


    KiThreadStartup函數首先將中斷請求級別(Interrupt ReQuest Level,IRQL)降低到PC_LEVEL,然后進入內核模式調用系統初始的線程函數PspUserThreadStartup。函數PspUserThreadStartup通知緩存管理器預取可執行映像文件的頁面,即該進程上一次啟動的前10s內引用到的頁面。讀取后,將一個用戶模式APC插入線程的用戶APC隊列,此APC例程指向ntdll.dll的LdrInitializeThunk函數,然后函數PspUserThreadStartup返回
  • 當函數KiThreadStartup返回到用戶模式時,由PspUserThreadStartup插入的APC也已被交付,于是函數Ntdll.LdrInitializeThunk被調用,該函數是PE映像加載器的初始化函數。
  • 完成初始化工作以后,加載PE映像中任何必要的DLL,并調用這些DLL的入口函數。最后,當LdrInitializeThunk返回到用戶模式APC分發器時,該線程開始在用戶模式下執行;然后,它調用用戶棧中的線程啟動函數
  • 至此,進程與線程全部建立完成,開始執行用戶空間中的代碼
  • 總結

    以上是生活随笔為你收集整理的内核和用户模式下进程与线程创建的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。