0x00前言
windows11是如何建立程式並管理他們的呢?這篇分析CreateProcess在3環使用者層做了哪些事情。
作業系統:windows 11
工具:vs,IDA,windbg
0x01CreateProcess第一階段
CreateProcess用來建立一個新的程式和它的主執行緒,這個新程式執行指定的可執行檔案。下面看一個示例 建立一個程式
#include <stdio.h> #include <windows.h> int main(int argc, char* argv[]) { STARTUPINFO si; PROCESS_INFORMATION pi; ZeroMemory(&si, sizeof(si)); si.cb = sizeof(si); ZeroMemory(&pi, sizeof(pi)); TCHAR szCommandLine[] = TEXT("powershell.exe"); if (!CreateProcess(NULL, // No module name (use command line) szCommandLine, // Command line NULL, // Process handle not inheritable NULL, // Thread handle not inheritable FALSE, // Set handle inheritance to FALSE 0, // No creation flags NULL, // Use parent's environment block NULL, // Use parent's starting directory &si, // Pointer to STARTUPINFO structure &pi) // Pointer to PROCESS_INFORMATION structure ) return 0; }
現在我們就來分析CreateProcess 這個函式的內部實現
根據是你union 編碼還是ascii 呼叫CreateProcessW或者CreateProcessA 會呼叫kenrel32.dll 的createprocess
引數複製 完了 接著會繼續呼叫KERNELBASE.dll 裡面的CreateProcessW 這裡面就是他的3環具體實現
0x02CreateProcess第二階段
CreateProcessW 可以看到複製完引數 呼叫了 CreateProcessInternalW 去實現建立程式程式碼
真正的起點,應該是從CreateProcessInternal開始的
下面開始分析CreateProcessInternal函式
第一步就是 引數初始化和賦值
首先是引數的是否為空判斷
lpCommandLine命令列字串 不能為空
lpStartupInfo傳遞給新程式的資訊 不能為空
lpProcessInformation新程式返回的資訊 不能為空
獲取當前程式peb的地址
接著dwCreationFlags 控制優先順序等一系列標誌判斷
其中有程式碼會判斷dwCreationFlags是否包含DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS標誌位,
有則呼叫DbgUiConnectToDbg建立除錯物件,並呼叫DbgUiGetThreadDebugObject獲取該除錯物件。
這也是一些偵錯程式開啟程式的原理
接著建立新程式的環境塊RtlCreateEnvironmentEx
接著STARTUPINFO 資料處理
檢測到STARTUPINFO 包含擴充套件資料 會呼叫函式BasepConvertWin32AttributeList
判斷lpCurrentDirectory是否為NULL,不為NULL則申請堆空間,呼叫GetFullPathNameW由字串獲取對應的全路徑
接著呼叫BaseFormatObjectAttributes通過引數ProcessAttributes格式化ProcessObjectAttributes物件,
通過引數ThreadAttributes格式化ThreadObjectAttributes物件,準備進入0環
接著就是對傳入的lpCommandLine 引數做處理
最後到BasepCreateProcessParameters 根據FileName、bInheritHandles、Environment、StartupInfo這些資訊,
建立RTL_USER_PROCESS_PARAMETERS結構體作為0環引數。
接著就是進入0環 NtCreateUserProcess 後面開始分析0環