Author: Chen Xi
Date: 12:28:30
Environment: [win7 flagship SP1; Intel I3 x86, support 64-bit; vs2010; wrk-v1.2; Virtual PC 2007 Windows 2003 Server SP1 Standard Edition image; windbg 6.11.0001.404 (x86)]
Reprinted please indicate the source
Q: In windows, I call the CreateProcess API to create a process. What does it do internally?
A: Generally, the operating system must be hierarchical. The kernel will process the final creation process operations, but its upper layer may have some modules to determine the validity of some parameters or to be transplanted. Windows is no exception. Look at the modules in the Windows Kernel:
You may want to write a CreateProcess program to obtain internally called items through reverse engineering.
Q: The following code:
#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;}
Compile it into createprocessdemo.exe and run:
It can be seen that the process is correctly created.
A: Next we will find out which module contains the createprocessa function. Go to the vs command line tool,
Run the command dumpbin.exe/All createprocessdemo.exe> D: \ dumpbin_createprocessdemo.txt to obtain all dump information. Find the following information:
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
It can be seen that createprocessa is referenced in kernel32.dll.
Q: now we can view the call relationship of createprocessa in kernel32.dll?
A: Yes. Use IDA to open kernel32.dll in the system directory and find the location of the createprocessa function:
The createprocessinternala routine can be found near the end.
Q: continue to find the internal implementation of the createprocessinternala routine. It will eventually call createprocessinternalw for implementation. Continue to find the createprocessinternalw implementation and find that it will eventually call the ntcreateuserprocess routine (ntcreateprocessex will be called under XP or server 2003). This routine is not in kernel32.dll, where is it?
A: As described in the preceding figure, it starts with NT and is in Ntdll. dll. Ida can also open NTDLL. dll and find the implementation of ntcreateuserprocess:
Q: What is zwcreateuserprocess, as if it is the same as ntcreateuserprocess?
A: For NTDLL. dll only, they are consistent according to the above. However, they are inconsistent in the kernel. The routines starting with NT will judge the access permission and parameter validity, but ZW won't. zw can be directly used by kernel mode code. At the same time, calling a routine starting with ZW changes the previous mode to the kernel mode, but a routine starting with NT cannot.
Here, you can see the corresponding code of the NT kernel in XP or 2003 Server:
//// The ntcreateprocess function calls it. // This function calls the pspcreateprocess function. // Ntstatus // typedef ulong ntstatus; ntcreateprocessex (_ out phandle processhandle, _ in access_mask desiredaccess, _ in_opt pobject_attributes objectattributes, _ in handle parentprocess, _ in ulong flags, // create the flag _ in_opt handle sectionhandle, _ in_opt handle debugport, _ in_opt handle exceptionport, _ in ulong jobmemberlevel) /* ++ routine Description: // routine description this routine creates a process object. // Create a process object arguments: // The parameter processhandle-returns the handle for the new process. // return the new process's handle pointer desiredaccess-supplies the desired access modes to the new process. // provide the access permission for the new process objectattributes-supplies the object attributes of the new process. // provide the object attributes of the new process... -- */{ntstatus status; // available in debugging mode; otherwise, it is defined as an empty statement // paged_code (); // If the mode previously executed by the thread is not the kernel mode if (kegetpreviusmode ()! = Kernelmode) {// probe all arguments // check all parameters // try {probeforwritehandle (processhandle); // probeforwritehandle macro in ex. definition in h文}} response T (exception_execute_handler) {return getexceptioncode () ;}} if (argument_present (parentprocess) {// If the parameter -- parent process handle has status = pspcreateprocess (processhandle, // call the pspcreateprocess function desiredaccess, objectattributes, parentprocess, flags, sectionhandle, debugport, exceptionport, jobmemberlevel);} else {// otherwise, an invalid parameter error is returned. Status = unknown ;} return status ;}
Q: How does the user mode enter the kernel mode?
A: The execution in Ntdll. dll is still in the user mode. ntcreateuserprocess passes in the interrupt number to eax, while edX passes in the 7ffe0300h as the parameter address for system calling and enters the kernel mode. Its internal implementation is:
Ntstatusntcreateprocess (// create process _ out phandle processhandle, // Process Handle pointer _ in access_mask desiredaccess, _ in_opt pobject_attributes objectattributes, _ in handle parentprocess, // parent Process Handle _ in Boolean inheritobjecttable, // whether to inherit the handle table _ in_opt handle sectionhandle, _ in_opt handle debugport, // debug port _ in_opt handle exceptionport // abnormal port) {ulong flags = 0; If (ulong_ptr) sectionhandle & 1) {flags | = process_create_flags_breakaway ;} if (ulong_ptr) debugport & 1) {flags | = tables;} If (inheritobjecttable) {// whether to inherit the handle table flags | = process_create_flags_inherit_handles ;} // call the ntcreateprocessex function return ntcreateprocessex (processhandle, desiredaccess, objectattributes optional, // optional only indicates the meaning of the optional parameter and does not affect the compilation of parentprocess, flags, // The calculated flags sectionhandle, debugport, exceptionport, 0 );}
The source code of wrk of win7 is not found, and the above is the implementation of the NT kernel. Note that the above program is executed in win7.
Q: Can I use a virtual machine to test the internal call details more clearly?
A: Yes. Use a virtual machine for kernel mode debugging to verify the entire process above. Of course, because the Virtual Machine System used is 2003 Server SP1, its kernel is different from the win7 kernel, so there will be inconsistencies.
Q: After the Virtual Machine and debugger are started (the specific process is omitted, you can search for wrk configurations online), what can be done?
A: First, write a program that can be run under the VM System 2003 Server SP1 under win7. It can be arbitrary.
Q: The following code:
#include <stdio.h>int main(){ printf("hello\n"); return 0;}
To ensure that the database can be run in a lower version, the library used is set to a static library during compilation.
Compiled into hello.exe. Put it on the Virtual Machine System desktop. Does hello.exe run without permission?
A: Don't worry. We should add a breakpoint at the beginning of ntcreateprocessex. As follows:
Such as red. Connect the virtual machine to continue running, and double-click hello.exe on the Virtual Machine's table to run.
Q: After double-clicking, the debugger pauses when a breakpoint occurs:
As shown above, the purple position is when windbg runs to the breakpoint. Now, can I check the call stack?
A: Yes. Run the K command at the KD prompt to obtain the stack information:
It can be seen from createprocessw in Kernel32, createprocessinternalw, and ntcreateprocessex in Ntdll, and then transferred into the kernel routine kifastsystemcallret to enter the NT module (namely, the kernel module ). In the kernel, it calls the ntcreateprocessex function to complete the specific work.
Q: Does ntcreateprocessex in Ntdll conflict with ntcreateprocessex in NT?
A: They are not simple upper-and lower-layer modules, but there are some modules in the middle, so the same name will not directly cause conflicts; in addition, NTDLL does not include the function name when calling the kernel routine. the compiler can find the address correctly and it will not be confused during runtime.
Q: What is the difference between ntcreateprocessex and zwcreateprocessex in the kernel?
A: use X nt! Zwcreateprocessex first check whether zwcreateprocessex exists in the kernel:
From the above we can see that there is indeed.
Next, disassembly:
It can be seen that its implementation is very direct, and the specific process of calling the system is called. It is obviously different from the previously seen ntcreateprocessex. ntcreateprocessex first performs some parameter and mode judgment. Therefore, zwcreateprocessex converts the running mode into the kernel mode because it is forced to fall into the kernel mode through system calls. However, the internal processing of ntcreateprocessex is still its actual implementation.
Q: How can I return the result when the call ends?
A: as follows,
The base \ ntos \ Ke \ i386 \ trap. ASM contains the processing for returned results:
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
The main reason is to resume the call.
Author: Chen Xi
Date: 12:28:30
Environment: [win7 flagship SP1; Intel I3 x86, support 64-bit; vs2010; wrk-v1.2; Virtual PC 2007 Windows 2003 Server SP1 Standard Edition image; windbg 6.11.0001.404 (x86)]
Reprinted please indicate the source