[RedDev Series #3] Spawn Process From WMI In C++

GhouLSec
3 min readOct 16, 2021

COM object provides another options to create a new process besides using common Windows APIs such as CreateProcess or ShellExecute.

For threat actor, the good way of this kind of process creation is that the wmiprvse.exe will break the process chain from its parent process as it is initiated from the COM object. So the new child process spawned will have no PID chain relationship with the initiator process wmi_create_process.exe. This will makes investigation slightly difficult.

Process chain break example from execution of wmiprvse.exe

Reproduce the PoC in C++

  1. Initialize the COM library by calling CoInitializeEx
CoInitializeEx(0, COINIT_MULTITHREADED);

2. Initiate a IWbemClassObject interface by calling CoCreateInstance. In order to call that interface, we have to pass the correct rclsid and riid into CoCreateInstance as shown as below.

REFCLSID rclsid = CLSID_WbemLocator; // Unmarshaler CLSID, 4590f811–1d3a-11d0–891f-00aa004b2e24REFIID riid = IID_IWbemLocator ; // Interface UUID, dc12a687–737f-11cf-884d-00aa004b2e24CoCreateInstance(rclsid, NULL, 1, riid, (LPVOID*)&wbemLocator);

2. Call the ConnectServer method from interface pointer wbemLocator. It will setting up the wbemServices object that bounds to the namespace ROOT\\CIMV2 there.

IWbemLocator interface only have one method which is ConnectServer

IWbemServices* wbemServices = NULL;wbemLocator->ConnectServer((BSTR)L"ROOT\\CIMV2", NULL, NULL, 0, NULL, 0, 0, &wbemServices);

3. Calling GetObject function from wbemService object which will retrieve information from object path Win32_ProcessStartup.

Output will be the oWin32ProcessStartupclass object pointer.

IWbemClassObject* oWin32ProcessStartup = NULL;                        wbemServices->GetObject((BSTR)L"Win32_ProcessStartup", 0, NULL, &oWin32ProcessStartup, NULL);

4. SpawnInstance create new instance of a class based on the object classoWin32ProcessStartupretrived from the steps above.

Output pStartupInstance class object pointer will pass into ProcessStartupInformation (Step 9) property later.

IWbemClassObject* pStartupInstance = NULL;oWin32ProcessStartup->SpawnInstance(0, &pStartupInstance);

5. Calling GetObject function from wbemService object which will retrieve information from object path Win32_Process.

Param oWin32Process will hold the result of the function called.

IWbemClassObject* oWin32Process = NULL;                        wbemServices->GetObject((BSTR)L"Win32_Process", 0, NULL, &oWin32Process, NULL);

6. GetMethod returns information about the requested method Create from object oWin32Process.

Param pInParamsDefinition will hold the result of the function called.

IWbemClassObject* pInParamsDefinition = NULL; oWin32Process->GetMethod((BSTR)L"Create", 0, &pInParamsDefinition, NULL);

7. SpawnInstance called by pInParamsDefinition object to create new instance of a class which will pass into ExecMethod class later.

Output pParamsInstanceclass object pointer will pass into ExecMethodfunction later.

IWbemClassObject* pParamsInstance = NULL;pInParamsDefinition->SpawnInstance(0, &pParamsInstance);

8. Setting up CommandLine property in pParamsInstance object.

VARIANT varCommand;                        
VariantInit(&varCommand);
varCommand.vt = VT_BSTR;
varCommand.bstrVal = wcCommandExecute; // Your command line here
pParamsInstance->Put((BSTR)L"CommandLine", 0, &varCommand, 0);

9. Setting up ProcessStartupInformationproperty in pParamsInstance object.

VARIANT vtDispatch;                        
VariantInit(&vtDispatch);
vtDispatch.vt = VT_DISPATCH;
vtDispatch.byref = pStartupInstance; // From step 4

pParamsInstance->Put((BSTR)L"ProcessStartupInformation", 0, &vtDispatch, 0);

10. Spawn the new process by calling ExecMethod from wbemServices with Win32_Process object path and Create method with a predefined pParamsInstance object from steps above.

IWbemClassObject* pOutParams = NULL;    wbemServices->ExecMethod((BSTR)L"Win32_Process", (BSTR)L"Create", 0, NULL, pParamsInstance, &pOutParams, NULL);

Extra

You can refer to the full source code and the Ghidra decompiled code which is quite useful when reversing the malware that use this kind of technique to spawn new process.

Full Source Code
Ghidra Decompiled Code

References:

--

--