windows建立進程的使用者態和核心態互動—-小話windows(1)

來源:互聯網
上載者:User

作者:陳曦

日期:2012-6-19 12:28:30

環境:[win7旗艦版 SP1  ; Intel i3  x86, 支援64位  ;vs2010  ; wrk-v1.2  ; Virtual PC 2007   windows 2003 server sp1 standard edition鏡像 ;WinDbg 6.11.0001.404(x86) ] 

轉載請註明出處

Q: 在windows下,調用CreateProcess這個API來建立進程,它內部究竟做了什嗎?

A: 對於作業系統,一般肯定是分層的。核心將處理最終的建立進程操作,但是它的上層可能有一些模組,進行一些參數合法性判斷或者為了可移植考慮的判斷。windows同樣不例外。看看windows下面核心上面的模組:

不妨先寫一個CreateProcess的程式,通過逆向工程得到內部調用的東西。

Q: 如下代碼:

#include <windows.h>#include <stdio.h>int main(){    PROCESS_INFORMATION processInfo;    STARTUPINFOAstartupInfo;    ZeroMemory(&processInfo, sizeof(processInfo));    ZeroMemory(&startupInfo, sizeof(startupInfo));    startupInfo.cb = sizeof(startupInfo);    BOOL ret = CreateProcessA(NULL, "c:\\windows\\system32\\cmd.exe", NULL, NULL, false, 0, NULL, NULL, &startupInfo, &processInfo);    if(ret)printf("create process ok...\n");    else    {printf("create process failed...\n");printf("error is %d", GetLastError());    }    return 0;}

編譯成CreateProcessDemo.exe, 運行:

可以看出,它正確地建立了進程。

A:  下面我們將找出哪個模組包含CreateProcessA函數。進入VS的命令列工具,

使用如下命令dumpbin.exe  /all  CreateProcessDemo.exe  >  d:\dumpbin_createprocessdemo.txt得到所有dump的資訊,找到如下資訊:

 KERNEL32.dll                41819C Import Address Table                41803C Import Name Table                     0 time date stamp                     0 Index of first forwarder reference                   A4 CreateProcessA                  1C0 GetCurrentProcess                  4C0 TerminateProcess                  162 FreeLibrary                  4F1 VirtualQuery                  214 GetModuleFileNameW                  24A GetProcessHeap                  2CB HeapAlloc                  2CF HeapFree                  279 GetSystemTimeAsFileTime                  1C1 GetCurrentProcessId                  1C5 GetCurrentThreadId                  293 GetTickCount                  3A7 QueryPerformanceCounter                   CA DecodePointer                  4A5 SetUnhandledExceptionFilter

可以看出,CreateProcessA是在KERNEL32.DLL中被引用的。

Q: 現在我們可以在kernel32.dll中查看CreateProcessA的調用關係了?

A: 是的。使用ida,開啟系統目錄下面的kernel32.dll, 並尋找CreateProcessA函數的位置:

可以在靠近最後的時候發現調用CreateProcessInternalA常式。

Q: 繼續尋找CreateProcessInternalA常式的內部實現,它最終會調用CreateProcessInternalW來實現。繼續尋找CreateProcessInternalW的實現,發現它最終會調用NtCreateUserProcess常式(在xp或者server 2003下,會調用NtCreateProcessEx).此常式不在kernel32.dll中,它在哪裡?

A: 正如上面的圖示描述,它以nt開頭,它在ntdll.dll中。同樣適用ida開啟ntdll.dll, 找到NtCreateUserProcess的實現:

Q: ZwCreateUserProcess是什麼,好像和NtCreateUserProcess是一樣的?

A: 僅僅在ntdll.dll中來說,依照上面的,它們是一致的;可是在核心中,它們不完全一致。Nt開頭的常式會進行存取權限和參數合法性判斷,而Zw不會,Zw它可以由核心模式代碼直接使用;同時,調用Zw開頭的常式會將先前的模式改變為核心模式,而使用Nt開頭的常式不能。

這裡,可以看下xp或2003 server下的nt核心對應的代碼:

////NtCreateProcess函數是調用它 的。//此函數調用PspCreateProcess函數。//NTSTATUS              // typedef  ULONG  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    )/*++ Routine Description: //常式描述    This routine creates a process object.    //建立一個進程對象Arguments:   //參數    ProcessHandle - Returns the handle for the new process. //返回新進程的控制代碼指標    DesiredAccess - Supplies the desired access modes to the new process. //提供新進程的存取權限    ObjectAttributes - Supplies the object attributes of the new process. //提供新進程的對象屬性    .    .    .--*/{    NTSTATUS Status;////  在偵錯模式下才有用;否則,被定義為空白語句//    PAGED_CODE();   //如果線程之前執行的模式不是核心模式    if (KeGetPreviousMode() != KernelMode) {         //        // Probe all arguments    //檢查所有的參數        //        try {            ProbeForWriteHandle (ProcessHandle); //ProbeForWriteHandle宏在ex.h檔案中定義        } except (EXCEPTION_EXECUTE_HANDLER) {            return GetExceptionCode ();        }    }    if (ARGUMENT_PRESENT (ParentProcess)) {  //如果參數--父進程控制代碼存在        Status = PspCreateProcess (ProcessHandle, //調用PspCreateProcess函數                                   DesiredAccess,                                   ObjectAttributes,                                   ParentProcess,                                   Flags,                                   SectionHandle,                                   DebugPort,                                   ExceptionPort,                                   JobMemberLevel);    } else {    //否則,返回參數不合法的錯誤        Status = STATUS_INVALID_PARAMETER;    }    return Status;}

Q: 剛剛所說的使用者模式是如何進入核心模式的?

A: 上面的ntdll.dll中執行依然是使用者模式,NtCreateUserProcess通過向eax傳入中斷號, edx傳入7FFE0300H為參數地址來進行系統調用,進入核心模式。它的內部實現為:

NTSTATUSNtCreateProcess(  //建立進程    __out PHANDLE ProcessHandle,   //進程控制代碼的指標    __in ACCESS_MASK DesiredAccess,    __in_opt POBJECT_ATTRIBUTES ObjectAttributes,    __in HANDLE ParentProcess,    //父進程控制代碼    __in BOOLEAN InheritObjectTable,  //是否繼承控制代碼表    __in_opt HANDLE SectionHandle,    __in_opt HANDLE DebugPort,         //調試連接埠    __in_opt HANDLE ExceptionPort     //異常連接埠    ){    ULONG Flags = 0;    if ((ULONG_PTR)SectionHandle & 1) {        Flags |= PROCESS_CREATE_FLAGS_BREAKAWAY;    }    if ((ULONG_PTR) DebugPort & 1) {        Flags |= PROCESS_CREATE_FLAGS_NO_DEBUG_INHERIT;    }    if (InheritObjectTable) {  //是否繼承控制代碼表        Flags |= PROCESS_CREATE_FLAGS_INHERIT_HANDLES;    }//調用NtCreateProcessEx函數    return NtCreateProcessEx (ProcessHandle,                              DesiredAccess,                              ObjectAttributes OPTIONAL, //OPTIONAL只是表示選擇性參數的意思,並不會對編譯造成影響                              ParentProcess,                              Flags,   //上面計算得到的Flags                              SectionHandle,                              DebugPort,                              ExceptionPort,                              0);}

因為未找到win7的WRK原始碼資訊,上面為nt核心的實現。注意,如上程式執行是在win7系統下的執行。

Q: 為了更清楚地得到內部調用細節,是否可以使用虛擬機器來測試一下?

A: 可以,使用虛擬機器進行核心模式調試,來驗證上面的整個過程;當然,因為使用的虛擬機器系統是2003 server sp1, 它的核心和win7核心是不同的,所以會有不一致的地方。

Q: 當虛擬機器和調試器啟動後(此具體過程略,關於wrk的配置可以在網上搜尋),然後做什嗎?

A: 先在win7下面編寫一個可以在虛擬機器系統2003 server sp1下可以跑的程式.可以是任意的了。

Q: 如下代碼:

#include <stdio.h>int main(){    printf("hello\n");    return 0;}

為了保證在低版本下可運行,編譯時間將使用的庫設定成使用靜態庫。

編譯成hello.exe.放到虛擬機器系統案頭上。此時讓hello.exe運行嗎?

A: 不要著急,我們先在NtCreateProcessEx開始處加斷點。如下:

如紅色地方。接著讓虛擬機器繼續運行,在虛擬機器的案頭雙擊hello.exe運行起來。

Q: 雙擊後,調試器遇到斷點停頓下來:

如上,紫色位置為windbg跑到斷點時的。此時,是否就可以看看呼叫堆疊了?

A: 是的。使用在kd提示符後輸入k命令得到堆棧資訊:

可以看出從kernel32中的CreateProcessW,到CreateProcessInternalW, 又到ntdll中的NtCreateProcessEx,接著調入陷入核心常式KiFastSystemCallRet進入nt模組(即為核心模組)。在核心中,它調用NtCreateProcessEx函數來完成具體的工作。

Q: ntdll中的NtCreateProcessEx與nt中的NtCreateProcessEx名稱一樣,會有衝突嗎?

A: 它們不是簡單的上層和下層的模組,中間又有了一些模組,所以名稱一樣不會直接造成衝突;並且ntdll調用核心常式也肯定不是把函數名稱傳進去的; 編譯器是可以正確地找到了地址,運行時也不會混淆。

Q: 在核心中,NtCreateProcessEx和ZwCreateProcessEx有什麼區別?

A: 使用x  nt!ZwCreateProcessEx先看看核心中是否存在ZwCreateProcessEx:

由上可以看出確實存在。

接著反組譯碼:

可以看出,它的實現很直接,調用系統調用具體處理。它和之前看到的NtCreateProcessEx顯然不一樣,NtCreateProcessEx先進行了一些參數和模式的判斷。所以說,ZwCreateProcessEx會將啟動並執行模式轉變成核心模式,因為它通過系統調用被迫陷入核心模式。不過,NtCreateProcessEx內部的處理依然是它實際的實現。

Q: 那麼,調用結束時如何返回呢?

A: 如下,

在base\ntos\ke\i386\trap.asm中包含了返回時的處理:

kss61:;; Upon return, (eax)= status code. This code may also be entered from a failed; KiCallbackReturn call.;        mov     esp, ebp                ; deallocate stack space for arguments;; Restore old trap frame address from the current trap frame.;kss70:  mov     ecx, PCR[PcPrcbData+PbCurrentThread] ; get current thread address        mov     edx, [ebp].TsEdx        ; restore previous trap frame address        mov     [ecx].ThTrapFrame, edx  ;;;   System service's private version of KiExceptionExit;   (Also used by KiDebugService);;   Check for pending APC interrupts, if found, dispatch to them;   (saving eax in frame first).;        public  _KiServiceExit_KiServiceExit:        cli                                         ; disable interrupts        DISPATCH_USER_APC   ebp, ReturnCurrentEax;; Exit from SystemService;        EXIT_ALL    NoRestoreSegs, NoRestoreVolatile

主要就是恢複調用時的資訊,繼續執行。

作者:陳曦

日期:2012-6-19 12:28:30

環境:[win7旗艦版 SP1  ; Intel i3  x86, 支援64位  ;vs2010  ; wrk-v1.2  ; Virtual PC 2007   windows 2003 server sp1 standard edition鏡像 ;WinDbg 6.11.0001.404(x86) ] 

轉載請註明出處

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.