There are two APIs for process creation, createprocessa and CreateProcessW. These two functions only have different character codes of parameters, and will eventually call the same function.
1, Introduction to function parameters
First, let's look at the parameters of the process creation function
Take CreateProcessW as an example:
WINBASEAPI BOOL WINAPI CreateProcessW( LPCWSTR lpApplicationName, LPWSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCWSTR lpCurrentDirectory, LPSTARTUPINFOW lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation );
- lpApplicationName: points to a NULL terminated string used to specify the executable module
- lpCommandLine: points to a NULL terminated string that specifies the command line to execute
- lpProcessAttributes: points to a SECURITY_ATTRIBUTES structure, which determines whether the returned handle can be inherited by the child process
typedef struct _SECURITY_ATTRIBUTES { DWORD nLength; LPVOID lpSecurityDescriptor; BOOL bInheritHandle; } SECURITY_ATTRIBUTES, *PSECURITY_ATTRIBUTES, *LPSECURITY_ATTRIBUTES;
- lpThreadAttributes: the same as lpProcessAttribute, but this parameter determines whether the thread is inherited
- bInheritHandles: indicates whether the new process inherits a handle from the calling process
- dwCreationFlags: Specifies additional flags that control the creation of priority classes and processes
- lpEnvironment: refers to the environment block of a new process. If this parameter is empty, the new process uses the environment of the calling process
- lpCurrentDirectory: points to a NULL terminated string that specifies the working path of the child process
- lpStartupInfo: points to a STARTUPINFO structure that determines how the main form of a new process is displayed
typedef struct _STARTUPINFOW { DWORD cb; LPWSTR lpReserved; LPWSTR lpDesktop; LPWSTR lpTitle; DWORD dwX; DWORD dwY; DWORD dwXSize; DWORD dwYSize; DWORD dwXCountChars; DWORD dwYCountChars; DWORD dwFillAttribute; DWORD dwFlags; WORD wShowWindow; WORD cbReserved2; LPBYTE lpReserved2; HANDLE hStdInput; HANDLE hStdOutput; HANDLE hStdError; } STARTUPINFOW, *LPSTARTUPINFOW;
- lpProcessInformation: refers to a process used to receive the identification information of the new PROCESS_INFORMATION structure
typedef struct _PROCESS_INFORMATION { HANDLE hProcess; HANDLE hThread; DWORD dwProcessId; DWORD dwThreadId; } PROCESS_INFORMATION, *PPROCESS_INFORMATION, *LPPROCESS_INFORMATION;
The specific meaning of these parameters can be known in the subsequent reverse analysis
2, Detailed analysis of character encoding conversion of CreateProcessA
CreateProcessInternalA is called directly inside CreateProcessA, but two parameters are added at the beginning and end, and the values are zero
The CreateProcessInternalA function is analyzed below
The flow chart is as follows:
(1) First, judge whether lpCommandLine is empty
- If lpCommandLine is not empty, call basep8bitstringtodynamicunicode string to convert it to UNICODE_STRING type
- If lpCommandLine is empty, proceed to the next step
(2) Then determine whether lpApplicationName is empty
- Call basep8bitstringtodynamicunicode string to convert it to UNICODE_STRING type
- If lpApplicationName is empty, proceed to the next step
(3) Then determine whether the lpCurrentDirectory is empty
- Call basep8bitstringtodynamicunicode string to convert it to UNICODE_STRING type
- If lpCurrentDirectory is empty, proceed to the next step
(4) Since lpStartupInfo also has three ANSI strings inside, it also needs to be converted
- First, create a local variable StartupInfo of StartupInfo type, and copy the parameter lpStartupInfo into StartupInfo. At this time, you also need to convert the string in StartupInfo into UNICODE
(5) When all parameters have been changed to UNICODE, CreateProcessInternalW can be called
For CreateProcessW, CreateProcessInternalW is directly called internally