Click here to Skip to main content
Click here to Skip to main content

Detecting Windows NT/2K process execution

By , 25 Mar 2002
 
//---------------------------------------------------------------------------
//
// ThreadMonitor.cpp
//
// SUBSYSTEM: 
//              Monitoring process creation and termination  
//				
// MODULE:    
//              Thread management
//
// DESCRIPTION:
//              Implement abstract interface provided by CCustomThread
//
// AUTHOR:		Ivo Ivanov
//                                                                         
//---------------------------------------------------------------------------


//---------------------------------------------------------------------------
//
// Includes
//
//---------------------------------------------------------------------------
#include "ThreadMonitor.h"
#include "NtDriverController.h"

//---------------------------------------------------------------------------
//
// class CThreadMonitor
//
//---------------------------------------------------------------------------
CProcessThreadMonitor::CProcessThreadMonitor(
	TCHAR*               pszThreadGuid,     // Thread unique ID
	CNtDriverController* pDriverController, // service controller
	CQueueContainer*     pRequestManager    // The underlying store
	):
	CCustomThread(pszThreadGuid),
	m_pRequestManager(pRequestManager),
	m_hKernelEvent(INVALID_HANDLE_VALUE),
	m_hDriverFile(INVALID_HANDLE_VALUE)
{
	assert(NULL != pDriverController);
	//
	// Store the pointe to the service controller, thus
	// we can use it later
	//
	m_pDriverCtl = pDriverController;

	::ZeroMemory((PBYTE)&m_LastCallbackInfo, sizeof(m_LastCallbackInfo));
}

CProcessThreadMonitor::~CProcessThreadMonitor()
{

}

//
// A user supplied implementation of the thread function.
// Override Run() and insert the code that should be executed when 
// the thread runs.
//
void CProcessThreadMonitor::Run()
{
	HANDLE handles[2] = 
	{
		m_hShutdownEvent,
		m_hKernelEvent
	};

	while (TRUE)
	{
		DWORD dwResult = ::WaitForMultipleObjects(
			sizeof(handles)/sizeof(handles[0]), // number of handles in array
			&handles[0],                        // object-handle array
			FALSE,                              // wait option
			INFINITE                            // time-out interval
			);
		//
		// the system shuts down
		//
		if (handles[dwResult - WAIT_OBJECT_0] == m_hShutdownEvent)
			break;
		//
		// The kernel event has been just signaled
		//
		else
			RetrieveFromKernelDriver();
	} // while
}

//
// Perform action prior to activate the thread
//
BOOL CProcessThreadMonitor::OnBeforeActivate()
{
	BOOL bResult = FALSE;
	//
	// Try opening the device driver
	//
	m_hDriverFile = ::CreateFile(
		TEXT("\\\\.\\ProcObsrv"),
		GENERIC_READ | GENERIC_WRITE, 
		FILE_SHARE_READ | FILE_SHARE_WRITE,
		0,                     // Default security
		OPEN_EXISTING,
		FILE_FLAG_OVERLAPPED,  // Perform asynchronous I/O
		0);                    // No template
	if (INVALID_HANDLE_VALUE != m_hDriverFile)
		//
		// Attach to kernel mode created event handle
		//
		bResult = OpenKernelModeEvent();

	return bResult;
}

//
// Called after the thread function exits
//
void CProcessThreadMonitor::OnAfterDeactivate()
{
	if (INVALID_HANDLE_VALUE != m_hKernelEvent)
	{
		::CloseHandle(m_hKernelEvent);
		m_hKernelEvent = INVALID_HANDLE_VALUE;
	}
	if (INVALID_HANDLE_VALUE != m_hDriverFile)
	{
		::CloseHandle(m_hDriverFile);
		m_hDriverFile = INVALID_HANDLE_VALUE;
	}
}

//
// Attach to the particular kernel mode created event handle
//
BOOL CProcessThreadMonitor::OpenKernelModeEvent()
{
	m_hKernelEvent = ::OpenEvent(
		SYNCHRONIZE, FALSE, TEXT("ProcObsrvProcessEvent") );

	return (INVALID_HANDLE_VALUE != m_hKernelEvent);
}

//
// Retrieve data from the kernel mode driver.
//
void CProcessThreadMonitor::RetrieveFromKernelDriver()
{
	OVERLAPPED  ov          = { 0 };
	BOOL        bReturnCode = FALSE;
	DWORD       dwBytesReturned;
	PROCESS_CALLBACK_INFO  callbackInfo;
	QUEUED_ITEM queuedItem;         
	//
    // Create an event handle for async notification from the driver
	//
	ov.hEvent = ::CreateEvent(
		NULL,  // Default security
		TRUE,  // Manual reset
		FALSE, // non-signaled state
		NULL
		); 
	//
	// Get the process info
	//
	bReturnCode = ::DeviceIoControl(
		m_hDriverFile,
		IOCTL_PROCOBSRV_GET_PROCINFO,
		0, 
		0,
		&callbackInfo, sizeof(callbackInfo),
		&dwBytesReturned,
		&ov
		);
	//
	// Wait here for the event handle to be set, indicating
	// that the IOCTL processing is completed.
	//
	bReturnCode = ::GetOverlappedResult(
		m_hDriverFile, 
		&ov,
		&dwBytesReturned, 
		TRUE
		);
	//
	// Prevent duplicated events
	//
	if ( (m_LastCallbackInfo.bCreate != callbackInfo.bCreate) ||
	     (m_LastCallbackInfo.hParentId != callbackInfo.hParentId) ||
		 (m_LastCallbackInfo.hProcessId != callbackInfo.hProcessId) )
	{
		//
		// Setup the queued element
		//
		::ZeroMemory((PBYTE)&queuedItem, sizeof(queuedItem));
		queuedItem.hParentId = callbackInfo.hParentId;
		queuedItem.hProcessId = callbackInfo.hProcessId;
		queuedItem.bCreate = callbackInfo.bCreate;
		//
		// and add it to the queue
		//
		m_pRequestManager->Append(queuedItem);
		//
		// Hold last event
		//
		m_LastCallbackInfo = callbackInfo;
	} // if
	//
	//
	//
	::CloseHandle(ov.hEvent);
}

//----------------------------End of the file -------------------------------

By viewing downloads associated with this article you agree to the Terms of use and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Ivo Ivanov
Chief Technology Officer
Australia Australia
Member
I'm a Security Researcher with over 20 years of experience. I specialise in Windows Internals and Malware Analysis. I'm the owner of InfoProcess and also a co-founder and Chief Security Architect of Vinsula.

Permalink | Advertise | Privacy | Mobile
Web02 | 2.6.130516.1 | Last Updated 26 Mar 2002
Article Copyright 2002 by Ivo Ivanov
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid