Click here to Skip to main content
15,891,184 members
Articles / Programming Languages / C++

Detecting Windows NT/2K process execution

Rate me:
Please Sign up or sign in to vote.
4.94/5 (69 votes)
25 Mar 2002CPOL7 min read 1.1M   11.4K   233  
An article on how to get notification from the OS when a process starts
//---------------------------------------------------------------------------
//
// QueueContainer.cpp
//
// SUBSYSTEM: 
//              Monitoring process creation and termination  
//				
// MODULE:    
//              Implement a multithreaded thread safe queue
// 
// DESCRIPTION:
//
// AUTHOR:		Ivo Ivanov
//                                                                         
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------
//
// Includes
//
//---------------------------------------------------------------------------

#include "common.h"
#include "QueueContainer.h"

//---------------------------------------------------------------------------
//
// class CQueueContainer
//
//---------------------------------------------------------------------------

//
// Queue's constructor
//
CQueueContainer::CQueueContainer(CCallbackHandler* pHandler):
	m_pHandler(pHandler)
{
	Init();
}

//
// Queue's destructor
//
CQueueContainer::~CQueueContainer()
{
	Done();
}

//
// Get data from the kernel mode driver
//
void CQueueContainer::WaitOnElementAvailable()
{
	HANDLE handles[2] = 
	{
		m_evtShutdownRemove,
		m_evtElementAvailable
	};

	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_evtShutdownRemove)
			break;
		//
		// An element just became available in the queue
		//
		else
		{
			DoOnProcessCreatedTerminated();
		}
	} // while
}

//
// A method for accessing handle to an internal event handle
//
HANDLE CQueueContainer::Get_ElementAvailableHandle() const
{
	return m_evtElementAvailable;
}

//
// Initates the process of handling notification in the queue
//
BOOL CQueueContainer::StartReceivingNotifications()
{
	BOOL bResult = FALSE;
	if (!m_pRetrievalThread->GetIsActive())
	{
		m_pRetrievalThread->SetActive( TRUE );
		bResult = m_pRetrievalThread->GetIsActive();
	}
	return bResult;
}

//
// Shutdown if there is something in progress
//
void CQueueContainer::StopReceivingNotifications()
{
	if (m_pRetrievalThread->GetIsActive())
		::SetEvent(m_evtShutdownRemove);
}

//
// Initialize the system
//
void CQueueContainer::Init()
{
	//
	// Create the monitoring mutex
	//
	m_mtxMonitor = ::CreateMutex(NULL, FALSE, NULL);
	assert(NULL != m_mtxMonitor);	//
	// Create the "remove" event
	//
	m_evtElementAvailable = ::CreateEvent(NULL, FALSE, FALSE, NULL);
	assert(NULL != m_evtElementAvailable);
	//
	// Create an event for shutting down the remove operation
	//
	m_evtShutdownRemove = ::CreateEvent(NULL, FALSE, FALSE, NULL);
	assert(NULL != m_evtShutdownRemove);
	//
	// Create a thread for picking up posted in the queue item notifications
	//
	m_pRetrievalThread = new CRetrievalThread(
		TEXT("{4EA19E49-1E3F-48da-AE16-2F2FD6A11F59}"),
		this
		);
}

//
// Release all allocated resources
//
void CQueueContainer::Done()
{
	StopReceivingNotifications();
	delete m_pRetrievalThread;
	if (NULL != m_evtElementAvailable)
		::CloseHandle(m_evtElementAvailable);
	if (NULL != m_evtShutdownRemove)
		::CloseHandle(m_evtShutdownRemove);
	if (NULL != m_mtxMonitor)
		::CloseHandle(m_mtxMonitor);
}
	
//
// Insert data into the queue
//
BOOL CQueueContainer::Append(const QUEUED_ITEM& element)
{
	BOOL bResult = FALSE;
	DWORD dw = ::WaitForSingleObject(m_mtxMonitor, INFINITE);
	bResult = (WAIT_OBJECT_0 == dw);
	if (bResult)
	{
		//
		// Add it to the STL queue
		//
		m_Queue.push_back(element);
		//
		// Notify the waiting thread that there is 
		// available element in the queue for processing 
		//
		::SetEvent(m_evtElementAvailable);
	}//
	::ReleaseMutex(m_mtxMonitor);
	return bResult;
}

//
// Implement specific behavior when kernel mode driver notifies 
// the user-mode app
//
void CQueueContainer::DoOnProcessCreatedTerminated()
{
	QUEUED_ITEM element;
	// Initially we have atleast one element for processing
	BOOL bRemoveFromQueue = TRUE;
	while (bRemoveFromQueue)
	{
		DWORD dwResult = ::WaitForSingleObject(
			m_mtxMonitor, INFINITE
			);
		if (WAIT_OBJECT_0 == dwResult)
		{
			bRemoveFromQueue = (m_Queue.size() > 0); 
			// Is there anything in the queue
			if (bRemoveFromQueue)
			{
				// Get the element from the queue
				element = m_Queue.front();	
				m_Queue.pop_front();
			} // if
			else
				//
				// Let's make sure that the event hasn't been 
				// left in signaled state if there are no items 
				// in the queue 
				//
				::ResetEvent(m_evtElementAvailable);
		} // if
		::ReleaseMutex(m_mtxMonitor);
		//
		// Process it only there is an element that has 
		// been picked up
		//
		if (bRemoveFromQueue)	
			m_pHandler->OnProcessEvent( &element, m_pvParam );
		else
			break;
	} // while
}

//
// Set an external parameter, thus we could take the advantage 
// of it later on in the callback routine
//
void CQueueContainer::SetExternalParam(PVOID pvParam)
{
	m_pvParam = pvParam;
}

//
// Delegate this method to a call of CCallbackHandler 
//
void CQueueContainer::OnProcessEvent(PQUEUED_ITEM pQueuedItem)
{
	if (pQueuedItem->bCreate)
		::OutputDebugString(TEXT("Process created.\n")); 
	else
		::OutputDebugString(TEXT("Process terminated.\n")); 

	m_pHandler->OnProcessEvent(
			pQueuedItem,
			m_pvParam
			);
}

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

By viewing downloads associated with this article you agree to the Terms of Service 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)


Written By
United States United States
I specialize in OS Internals and Reverse Engineering.
Before joining my current employer I used to run a security blog for malware analysis: http://vinsula.com/security-blog

Comments and Discussions