Monitor Process Creation with WMI

S12 - H4CK
7 min readJan 29, 2024

Welcome to my new article, today i will show you how we can monitor every process creation in Windows using WMI (Windows Management Instrumentation).

Introduction

And if you want to learn the basics about Windows Malware Development you have my Introduction course available from $15.

*Send a email for crypto payments: s12deff@gmail.com *

As a red teamer and ethical malware developer well-versed in C++, I am excited to guide you through the intricacies of monitoring process creation on Windows using WMI (Windows Management Instrumentation). In today’s digital landscape, understanding and safeguarding against unauthorized process executions is paramount. Join me on this journey as we explore the capabilities of WMI in tracking and analyzing every process creation, providing valuable insights for enhancing system security. Let’s dive into the world of Windows monitoring and empower ourselves with the knowledge to fortify digital environments effectively.

Code

#include <Windows.h>
#include <iostream>
#include <WbemIdl.h>
#include <comutil.h>

using namespace std;

class EventSink : public IWbemObjectSink
{
LONG m_lRef;
bool bDone;

public:
EventSink() { m_lRef = 0; }
~EventSink() { bDone = true; }

virtual ULONG STDMETHODCALLTYPE AddRef();
virtual ULONG STDMETHODCALLTYPE Release();
virtual HRESULT
STDMETHODCALLTYPE
QueryInterface(REFIID riid, void** ppv);

virtual HRESULT STDMETHODCALLTYPE SetStatus(LONG lFlags, HRESULT hResult, BSTR strParam, IWbemClassObject* pObjParam);
virtual HRESULT STDMETHODCALLTYPE Indicate(LONG lObjectCount, IWbemClassObject** apObjArray);
};

ULONG EventSink::AddRef()
{
return InterlockedIncrement(&m_lRef);
}

ULONG EventSink::Release()
{
LONG lRef = InterlockedDecrement(&m_lRef);

if (lRef == 0)
delete this;
return lRef;
}

HRESULT EventSink::QueryInterface(REFIID riid, void** ppv)
{
if (riid == IID_IUnknown || riid == IID_IWbemObjectSink)
{
*ppv = (IWbemObjectSink*)this;
AddRef();

return WBEM_S_NO_ERROR;
}
else
return E_NOINTERFACE;
}

HRESULT EventSink::SetStatus(LONG lFlags, HRESULT hResult, BSTR strParam, IWbemClassObject* pObjParam)
{
return WBEM_S_NO_ERROR;
}

HRESULT EventSink::Indicate(long lObjectCount, IWbemClassObject** pArray)
{
HRESULT hr = S_OK;
_variant_t vtProp;

// Walk through all returned objects
for (int i = 0; i < lObjectCount; i++)
{
IWbemClassObject* pObj = pArray[i];

// First, get a pointer to the object properties
hr = pObj->Get(_bstr_t(L"TargetInstance"), 0, &vtProp, 0, 0);
if (!FAILED(hr))
{

// Then, get a pointer to the process object' interface to query its properties
IUnknown* pProc = vtProp;
hr = pProc->QueryInterface(IID_IWbemClassObject, (void**)&pObj);
if (SUCCEEDED(hr))
{
_variant_t pVal;

// print process name
hr = pObj->Get(L"Name", 0, &pVal, NULL, NULL);
if (SUCCEEDED(hr))
{
if ((pVal.vt == VT_NULL) || (pVal.vt == VT_EMPTY))
printf("Name: %s\n", (pVal.vt == VT_NULL) ? "NULL" : "EMPTY");
else
printf("Name: %S\n", pVal.bstrVal);
}
VariantClear(&pVal);

// print process ID
hr = pObj->Get(L"Handle", 0, &pVal, NULL, NULL);
if (SUCCEEDED(hr))
{
if ((pVal.vt == VT_NULL) || (pVal.vt == VT_EMPTY))
printf("PID: %s\n", (pVal.vt == VT_NULL) ? "NULL" : "EMPTY");
else
printf("PID: %S\n", pVal.bstrVal);
}
VariantClear(&pVal);

// print Executable Path
hr = pObj->Get(L"ExecutablePath", 0, &pVal, NULL, NULL);
if (SUCCEEDED(hr))
{
if ((pVal.vt == VT_NULL) || (pVal.vt == VT_EMPTY))
printf("ExecutablePath: %s\n", (pVal.vt == VT_NULL) ? "NULL" : "EMPTY");
else
printf("ExecutablePath: %S\n", pVal.bstrVal);
}
VariantClear(&pVal);

// print command line
hr = pObj->Get(L"CommandLine", 0, &pVal, NULL, NULL);
if (SUCCEEDED(hr))
{
if ((pVal.vt == VT_NULL) || (pVal.vt == VT_EMPTY))
printf("CommandLine: %s\n", (pVal.vt == VT_NULL) ? "NULL" : "EMPTY");
else
printf("CommandLine: %S\n", pVal.bstrVal);
}
VariantClear(&pVal);
}
}
VariantClear(&vtProp);
}

return WBEM_S_NO_ERROR;
}

int main(int iArgCnt, char** argv){
HRESULT hres;
hres = CoInitializeEx(0, COINIT_MULTITHREADED);
if (FAILED(hres)){
cout << "Failed to initialize COM library. Error code = " << hres << endl;
return 1;
}

hres = CoInitializeSecurity(NULL,-1,NULL,NULL, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE,NULL, EOAC_NONE, NULL);
if (FAILED(hres)){
cout << "Failed to initialize security. Error code = " << hres << endl;
CoUninitialize();
return 1;

}
IWbemLocator* pLoc = NULL;
hres = CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID*)&pLoc);

if (FAILED(hres)){
cout << "Failed to create IWbemLocator object. Error code = " << hres << endl;
CoUninitialize();
return 1;
}

IWbemServices* pSvc = NULL;
hres = pLoc->ConnectServer(_bstr_t(L"root\\CIMV2"),NULL, NULL, 0, NULL, 0, 0, &pSvc);

if (FAILED(hres)){
cout << "Could not connect. Error code = " << hres << endl;
pLoc->Release();
CoUninitialize();
return 1;
}

hres = CoSetProxyBlanket(pSvc, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL, RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE);

if (FAILED(hres)){
cout << "Could not set proxy blanket. Error code = " << hres << endl;
pSvc->Release();
pLoc->Release();
CoUninitialize();
return 1;
}
EventSink* pSink = new EventSink;
pSink->AddRef();

// Set up the event consumer
BSTR WQL = SysAllocString(L"SELECT * FROM __InstanceCreationEvent WITHIN 1 WHERE TargetInstance ISA 'Win32_Process'");
hres = pSvc->ExecNotificationQueryAsync(_bstr_t("WQL"), _bstr_t(WQL), WBEM_FLAG_SEND_STATUS, NULL, pSink);
if (FAILED(hres)){
cout << "ExecNotificationQueryAsync failed with = " << hres << endl;
pSvc->Release();
pLoc->Release();
pSink->Release();
CoUninitialize();
return 1;
}

// Wait for the event
cout << "Waiting for new process creation..." << endl;
getchar();
pSvc->CancelAsyncCall(pSink);
pSvc->Release();
pLoc->Release();
pSink->Release();
CoUninitialize();

return 0;
}

This C++ code is designed to monitor and display information about new process creations on a Windows system using Windows Management Instrumentation (WMI). Let’s break down the key components and functionalities:

  1. EventSink Class:
  • This class is derived from the IWbemObjectSink interface, which is part of the WMI API.
  • It implements methods such as AddRef, Release, QueryInterface, SetStatus, and Indicate that are necessary for handling WMI events.
  1. AddRef, Release, QueryInterface:
  • These methods are used for managing the reference count of the EventSink object.
  1. SetStatus:
  • This method is called by WMI to communicate status information back to the event sink. In this implementation, it returns WBEM_S_NO_ERROR, indicating success.
  1. Indicate:
  • This method is called by WMI to deliver the actual events. In this case, it processes the events related to new process creations.
  • It extracts information about the created process, such as its name, process ID (PID), executable path, and command line, and prints this information to the console.
  1. Main Function:
  • The main function initializes COM (Component Object Model) and sets up the necessary security settings.
  • It creates instances of IWbemLocator and IWbemServices to connect to the WMI service on the local machine.
  • The EventSink object is created, and an asynchronous query is set up to receive notifications for new process creations.
  • The program then enters a waiting state, allowing the user to observe process creation events.
  • After user input (pressing Enter), the asynchronous call is canceled, and resources are released.
  1. WMI Query:
  • The WMI query is specified in the SELECT * FROM __InstanceCreationEvent statement, indicating interest in all instance creation events within a 1-second time window where the target instance is a Win32 process.
  1. Console Output:
  • Information about the created processes is printed to the console, including the process name, PID, executable path, and command line.

It is a basic example demonstrating the use of WMI for system monitoring.

Proof of Concept

Let’s execute and try it:

And when a process is created:

Is working perfect!

Conclusions

In conclusion, this article has provided a practical demonstration of monitoring process creation on Windows using Windows Management Instrumentation (WMI). As a red teamer and ethical malware developer experienced in C++, I aimed to guide you through the intricacies of leveraging WMI for tracking and analyzing every process creation event.

Understanding and safeguarding against unauthorized process executions are crucial aspects of maintaining system security in today’s digital landscape. By exploring the capabilities of WMI, we’ve empowered ourselves with the knowledge needed to fortify digital environments effectively.

Additionally, for those eager to delve deeper into Windows Malware Development, an Introduction course is offered, providing fundamental insights into this specialized field.

The provided C++ code serves as a proof of concept, demonstrating the practical implementation of event monitoring using WMI. By executing the code, we observed the accurate tracking and reporting of new process creations.

In essence, this article equips you with practical knowledge and a foundational understanding of using WMI for process monitoring — a valuable skill set for enhancing cybersecurity practices. As we navigate the complexities of the digital realm, such insights contribute to a proactive approach in ensuring the security and integrity of Windows systems.

Get ready to unlock the secrets of ethical malware development with our unique course. We’re taking a different path through the world of cybersecurity, and here’s why you should jump on board:

*Send a email for crypto payments: s12deff@gmail.com *

If you enjoy my content and would like to help me take this project to the next level, you can become a member by donating a monthly subscription. Your support will help me continue to create high-quality content. Thank you for your generosity!

If donating is not possible for you at this time, no problem at all! Your support in sharing my project and spreading the word is greatly appreciated. I will continue to create and share my work regardless, and I am grateful for your encouragement and interest.

Thanks to read this :)

S12.

--

--