C++ 如何在c+中检测win32进程的创建/终止+;

C++ 如何在c+中检测win32进程的创建/终止+;,c++,winapi,process,C++,Winapi,Process,我知道,要接收有关Win32进程创建或终止的通知,我们可以使用APIPsSetCreateProcessNotifyRoutine()实现NT内核模式驱动程序,该驱动程序提供注册系统范围回调函数的能力,在每次新进程启动、退出或终止时,操作系统都会调用该回调函数 这是不可能创建NT内核模式驱动程序,只使用C++的Win32 API函数吗?当然,不使用无限循环的基本解查询活动进程列表 有没有提供相同功能(系统范围回调、异步事件)的库或win32 API?我唯一能想到的是WMI,不确定它是否提供进程创

我知道,要接收有关Win32进程创建或终止的通知,我们可以使用API
PsSetCreateProcessNotifyRoutine()
实现NT内核模式驱动程序,该驱动程序提供注册系统范围回调函数的能力,在每次新进程启动、退出或终止时,操作系统都会调用该回调函数

这是不可能创建NT内核模式驱动程序,只使用C++的Win32 API函数吗?当然,不使用无限循环的基本解查询活动进程列表


有没有提供相同功能(系统范围回调、异步事件)的库或win32 API?

我唯一能想到的是WMI,不确定它是否提供进程创建回调,但可能值得研究。

API挂钩应该是填充类似内容的正确方法。您可以钩住createProcess(A/W/asUserA/W….等)和NtTerminateProcess

您可以使用来监视所有窗口创建进程,但是,除此之外的任何操作都需要WMI、windows驱动程序或一点'

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__
\ifndef\uu进程终止通知\uh__
#定义进程终止通知__
#包括
命名空间ProcessTerminationNotification
{
typedef boost::函数t通知函数;
无效registerTerminationCallback(TNotificationFunction回调,未签名的processId);
}
#endif/\uuu进程终止通知\uh__
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");
    }
}
\define\u WIN32\u DCOM
#包括
使用名称空间std;
#包括
#包括
#包括
#pragma注释(lib,“wbemuid.lib”)
#包括“ProcessTerminationNotification.h”
类EventSink:public IWbemObjectSink
{
friend void ProcessTerminationNotification::registerTerminationCallback(TNotificationFunction回调,未签名的processId);
首席采购官pSvc;
CComPtr pStubSink;
长m_lRef;
ProcessTerminationNotification::TNotificationFunction m_回调;
公众:
EventSink(ProcessTerminationNotification::TNotificationFunction回调)
:m_lRef(0)
,m_回调(回调)
{}
~EventSink()
{}
虚拟ULONG STDMETHODCALLTYPE AddRef()
{
返回联锁增量(&m_lRef);
}
虚拟ULONG标准方法调用类型发布()
{
长lRef=联锁衰减(&m_lRef);
如果(lRef==0)
删除此项;
返回lRef;
}
虚拟HRESULT STDMETHODCALLTYPE查询接口(refid riid,void**ppv)
{
如果(riid==IID_IUnknown | | riid==IID_IWbemObjectSink)
{
*ppv=(IWbemObjectSink*)此;
AddRef();
返回WBEM\U S\U无错误;
}
否则返回E_NOINTERFACE;
}
虚拟HRESULT STDMETHODCALLTYPE指示(
长计数,
IWbemClassObject\uuuuRPC\uFAR*\uuuuuRPC\uFAR*apObjArray
)
{
m_callback();
/*取消注册事件接收器,因为进程已终止*/
pSvc->CancelAsyncCall(PSSubLink);
返回WBEM\U S\U无错误;
}
虚拟HRESULT STDMETHODCALLTYPE设置状态(
/*[in]*/LONG lFlags,
/*[in]*/HRESULT HRESULT,
/*[in]*/BSTR strParam,
/*[in]*/IWbemClassObject\uuuurpc\ufar*pObjParam
)
{
返回WBEM\U S\U无错误;
} 
};
void ProcessTerminationNotification::registerTerminationCallback(TNotificationFunction回调,未签名的processId)
{
巴勒斯坦解放军司令部;
HRESULT hres=CoCreateInstance(
CLSIDwbemLocator,
0, 
CLSCTX_INPROC_服务器,
IID_IWbemLocator,
(LPVOID*)和pLoc);
如果(失败(hres))
{

cout您可以通过挂接
CreateProcessInternalW
函数来监视进程创建。通过挂接此函数,您甚至可以将DLL注入新进程。

正如前面的评论所暗示的,使用WMI监视进程事件有一个缺点,因为WMI没有同步提供事件,即延迟很短。

《Windows内部构件第1部分》一书提到了一种称为“Windows事件跟踪(ETW)”的机制,它是操作系统事件的低级机制

以下博文展示了如何在.Net中使用ETW来监控流程:

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,或者如果您需要阻止进程或线程启动,或者当您需要同步通知时,您可以使用内核模式驱动程序方法。例如,我们的产品正是这样做的。

WMI查询可能会耗费大量CPU性能mance,如果设计不正确。如果使用Win32_Process class中的内部事件来跟踪进程创建事件,则会影响性能。另一种方法是利用安全审核日志。在多台计算机的情况下,您可以使用本地安全策略或GPO启用进程跟踪。一旦进程跟踪开始,您可以使用自定义XML查询订阅安全事件日志,以监视您感兴趣的某些进程。进程创建事件ID为4688。 `


*[EventData[Data[@Name='NewProcessName']='C:\Windows\explorer.exe']]
和
*[系统[(EventID=4688)]]

`

是的,WMI可以提供我所需要的(进程创建/终止回调)。如果有人对如何实现感兴趣,那么请看一看感谢有人知道WMI如何在内部实现事件吗?根据《Windows Internals Part 1》一书
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);
<QueryList>
 <Query Id="0" Path="Security">
   <Select Path="Security">
       *[EventData[Data[@Name='NewProcessName'] ='C:\Windows\explorer.exe']]
       and
       *[System[(EventID=4688)]]
   </Select>
 </Query>
</QueryList>