[英]How to detect win32 process creation/termination in c++
我知道要接收有关Win32进程创建或终止的通知,我们可能会使用API PsSetCreateProcessNotifyRoutine()
实现NT内核模式驱动程序,该API提供注册系统范围的回调函数的功能,每次新进程启动时,OS都会调用该函数,退出或终止。
仅使用c ++使用Win32 API函数,而无需创建NT内核模式驱动程序,是否有可能? 当然,不使用无限循环的基本解决方案来查询活动进程列表。
是否有提供相同功能(系统范围的回调,异步事件)的库或win32 API?
WMI很棒,它也可以使用进程名称。 尽管如果您需要跟踪流程终止,则可以使用以下更轻量和更简便的方法:
VOID CALLBACK WaitOrTimerCallback(
_In_ PVOID lpParameter,
_In_ BOOLEAN TimerOrWaitFired
)
{
MessageBox(0, L"The process has exited.", L"INFO", MB_OK);
return;
}
DWORD dwProcessID = 1234;
HANDLE hProcHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessID);
HANDLE hNewHandle;
RegisterWaitForSingleObject(&hNewHandle, hProcHandle , WaitOrTimerCallback, NULL, INFINITE, WT_EXECUTEONLYONCE);
一旦进程终止,此代码将调用WaitOrTimerCallback
。
我唯一能想到的是WMI,不确定是否提供了流程创建回调,但是可能值得研究。
Anders是正确的,WMI为此很好地工作。 由于我在项目中需要此代码,因此我可以共享用于检测(任意)进程终止的代码(给定其ID):
ProcessTerminationNotification.h:
#ifndef __ProcessTerminationNotification_h__
#define __ProcessTerminationNotification_h__
#include <boost/function.hpp>
namespace ProcessTerminationNotification
{
typedef boost::function< void(void) > TNotificationFunction;
void registerTerminationCallback(TNotificationFunction callback, unsigned processId);
}
#endif // __ProcessTerminationNotification_h__
ProcessTerminationNotification.cpp:
#define _WIN32_DCOM
#include <iostream>
using namespace std;
#include <comdef.h>
#include <Wbemidl.h>
#include <atlcomcli.h>
#pragma comment(lib, "wbemuuid.lib")
#include "ProcessTerminationNotification.h"
class EventSink : public IWbemObjectSink
{
friend void ProcessTerminationNotification::registerTerminationCallback(TNotificationFunction callback, unsigned processId);
CComPtr<IWbemServices> pSvc;
CComPtr<IWbemObjectSink> pStubSink;
LONG m_lRef;
ProcessTerminationNotification::TNotificationFunction m_callback;
public:
EventSink(ProcessTerminationNotification::TNotificationFunction callback)
: m_lRef(0)
, m_callback(callback)
{}
~EventSink()
{}
virtual ULONG STDMETHODCALLTYPE AddRef()
{
return InterlockedIncrement(&m_lRef);
}
virtual ULONG STDMETHODCALLTYPE Release()
{
LONG lRef = InterlockedDecrement(&m_lRef);
if (lRef == 0)
delete this;
return lRef;
}
virtual HRESULT STDMETHODCALLTYPE 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;
}
virtual HRESULT STDMETHODCALLTYPE Indicate(
LONG lObjectCount,
IWbemClassObject __RPC_FAR *__RPC_FAR *apObjArray
)
{
m_callback();
/* Unregister event sink since process is terminated */
pSvc->CancelAsyncCall(pStubSink);
return WBEM_S_NO_ERROR;
}
virtual HRESULT STDMETHODCALLTYPE SetStatus(
/* [in] */ LONG lFlags,
/* [in] */ HRESULT hResult,
/* [in] */ BSTR strParam,
/* [in] */ IWbemClassObject __RPC_FAR *pObjParam
)
{
return WBEM_S_NO_ERROR;
}
};
void ProcessTerminationNotification::registerTerminationCallback( TNotificationFunction callback, unsigned processId )
{
CComPtr<IWbemLocator> pLoc;
HRESULT hres = CoCreateInstance(
CLSID_WbemLocator,
0,
CLSCTX_INPROC_SERVER,
IID_IWbemLocator,
(LPVOID*)&pLoc);
if (FAILED(hres))
{
cout << "Failed to create IWbemLocator object. "
<< "Err code = 0x"
<< hex << hres << endl;
throw std::exception("ProcessTerminationNotificaiton initialization failed");
}
// Step 4: ---------------------------------------------------
// Connect to WMI through the IWbemLocator::ConnectServer method
CComPtr<EventSink> pSink(new EventSink(callback));
// Connect to the local root\cimv2 namespace
// and obtain pointer pSvc to make IWbemServices calls.
hres = pLoc->ConnectServer(
_bstr_t(L"ROOT\\CIMV2"),
NULL,
NULL,
0,
NULL,
0,
0,
&pSink->pSvc
);
if (FAILED(hres))
{
cout << "Could not connect. Error code = 0x"
<< hex << hres << endl;
throw std::exception("ProcessTerminationNotificaiton initialization failed");
}
// Step 5: --------------------------------------------------
// Set security levels on the proxy -------------------------
hres = CoSetProxyBlanket(
pSink->pSvc, // Indicates the proxy to set
RPC_C_AUTHN_WINNT, // RPC_C_AUTHN_xxx
RPC_C_AUTHZ_NONE, // RPC_C_AUTHZ_xxx
NULL, // Server principal name
RPC_C_AUTHN_LEVEL_CALL, // RPC_C_AUTHN_LEVEL_xxx
RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx
NULL, // client identity
EOAC_NONE // proxy capabilities
);
if (FAILED(hres))
{
cout << "Could not set proxy blanket. Error code = 0x"
<< hex << hres << endl;
throw std::exception("ProcessTerminationNotificaiton initialization failed");
}
// Step 6: -------------------------------------------------
// Receive event notifications -----------------------------
// Use an unsecured apartment for security
CComPtr<IUnsecuredApartment> pUnsecApp;
hres = CoCreateInstance(CLSID_UnsecuredApartment, NULL,
CLSCTX_LOCAL_SERVER, IID_IUnsecuredApartment,
(void**)&pUnsecApp);
CComPtr<IUnknown> pStubUnk;
pUnsecApp->CreateObjectStub(pSink, &pStubUnk);
pStubUnk->QueryInterface(IID_IWbemObjectSink,
(void **) &pSink->pStubSink);
// The ExecNotificationQueryAsync method will call
// The EventQuery::Indicate method when an event occurs
char buffer[512];
sprintf_s(buffer, "SELECT * "
"FROM __InstanceDeletionEvent WITHIN 1 "
"WHERE TargetInstance ISA 'Win32_Process' AND TargetInstance.ProcessId=%u", processId);
hres = pSink->pSvc->ExecNotificationQueryAsync(
_bstr_t("WQL"),
_bstr_t(buffer),
WBEM_FLAG_SEND_STATUS,
NULL,
pSink->pStubSink);
// Check for errors.
if (FAILED(hres))
{
cout << "ExecNotificationQueryAsync failed "
"with = 0x" << hex << hres << endl;
throw std::exception("ProcessTerminationNotificaiton initialization failed");
}
}
请注意,此处省略了初始化COM和COM进程安全性的代码(CoInitializeEx和CoInitializeSecurity),因为它应在应用程序初始化中完成。
将其与全局函数一起使用或使用boost :: bind连接到任意方法,例如后者:
class MyClass
{
public:
void myProcessTerminationCallback() { cout << "Wohoo!!" << endl; }
};
ProcessTerminationNotification::registerTerminationCallback(
boost::bind(&MyClass::myProcessTerminationCallback, <pointer to MyClass instance>),
1234); // Process ID = 1234
您可以使用带有CBTProc的 SetWindowsHookEx来监视所有Window的创建过程,但是除此以外 ,还需要WMI,Windows驱动程序或一点“ Black Magic ”
正如先前的评论所暗示的那样,使用WMI监视过程事件存在一个缺点,因为WMI无法同步提供事件,即延迟很短。
《 Windows Internals Part 1》一书指的是一种称为“ Windows事件跟踪(ETW)”的机制,它是用于操作系统事件的低级机制。
以下博客文章显示了如何在.Net中使用ETW来监视进程: http : //blogs.msdn.com/b/vancem/archive/2013/03/09/using-traceevent-to-mine-information-in -os-registered-etw-providers.aspx
您可以通过挂钩CreateProcessInternalW
函数来监视进程的创建。 通过挂钩此函数,您甚至可以将DLL注入新进程。
除了WMI之外,或者如果需要阻止进程或线程的启动,或者需要同步通知时,可以使用内核模式驱动程序方法。 例如,我们的CallbackProcess产品就可以做到这一点。
如果设计不当,WMI查询可能会消耗大量CPU性能。 如果使用Win32_Process类的内部事件来跟踪进程创建事件,则将严重影响性能。 另一种方法是利用安全审核日志。 如果有多台计算机,则可以使用“本地安全策略”或GPO启用“进程跟踪”。 流程跟踪开始后,您可以使用自定义XML查询订阅安全事件日志,以监视您感兴趣的某些流程。 进程创建事件ID为4688。
<QueryList>
<Query Id="0" Path="Security">
<Select Path="Security">
*[EventData[Data[@Name='NewProcessName'] ='C:\Windows\explorer.exe']]
and
*[System[(EventID=4688)]]
</Select>
</Query>
</QueryList>
`
API挂钩应该是实现类似功能的正确方法。 您可以挂钩createProcess(A / W / asUserA / W ....等)和NtTerminateProcess
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.