C++实现ETW进行进程变动监控详解

2022-07-13,,,,

何为etw

etw(event tracing for windows)提供了一种对用户层应用程序和内核层驱动创建的事件对象的跟踪记录机制。为开发者提供了一套快速、可靠、通用的一系列事件跟踪特性。

前言

一直想研究一种监控进程的方法,但wmi/枚举进程的方法,要么反应太慢,要么占用高。最近看到有人用易语言易语言完成了etw对进程变动监控的实现。

但是一直没看到c++的实现,于是决定将易语言易语言翻译为c++。

代码

直接上翻译的代码

#include <iostream>
#include <string>
#include <cstring>
#include <windows.h>
#include <evntrace.h>
#include <psapi.h>
#include <direct.h>
#include <evntcons.h>
using namespace std;

char session_name_file[] = "sample_process";

const uchar _flag[] = { 173, 74, 129, 158, 4, 50, 210, 17, 154, 130, 0, 96, 8, 168, 105, 57 };

event_trace_properties m_traceconfig;

uchar m_ptraceconfig[2048];

char m_file[256];

bool m_dowhile;

tracehandle m_htracehandle;

ulong64 m_htracehandle_econt[1];

tracehandle m_hsessionhandle;

string unicode_to_ansi(wstring strvalue)
{
    static char sbuff[1024] = { 0 };
    int iret = widechartomultibyte(cp_acp, 0, strvalue.c_str(), -1, sbuff, sizeof(sbuff), null, null);
    if (iret > 0) {
        return string(sbuff);
    }
    return "";
}

void winapi myprocessrecordevents(pevent_record eventrecord)
{
    switch (eventrecord->eventheader.eventdescriptor.id)
    {
    case 1://创建进程
        cout << "创建进程!进行创建进行的进程id:" <<
            eventrecord->eventheader.processid <<
            ",线程id:" <<
            eventrecord->eventheader.threadid <<
            ",进程sessionid:" <<
            *(ulong*)(((puchar)eventrecord->userdata)+32)<<
            ",创建的进程id:"<<
            *(ulong*)(((puchar)eventrecord->userdata) + 0) <<
            ",创建的进程路径:"<<
            unicode_to_ansi(  wstring((wchar_t*)(((puchar)eventrecord->userdata) + 60)))
            <<endl;
        break;
    case 2://进程退出
        cout << "进程退出!进程id:" <<
            eventrecord->eventheader.processid <<
            ",线程id:" <<
            eventrecord->eventheader.threadid <<
            ", 进程名:"<<
            ((lpstr)eventrecord->userdata) + 84
            <<endl;
        break;
        cout << "进程id:" << eventrecord->eventheader.processid << ",未知的行为:0x"<<hex<<eventrecord->eventheader.eventdescriptor.id << endl;
    default:

        break;
    }
}

void closeetw()
{
    ulong l_result = stoptracea(m_hsessionhandle, session_name_file, (pevent_trace_properties)(m_ptraceconfig + 8));
    if (m_htracehandle != null)
    {
        closetrace(m_htracehandle);
    }
}

dword winapi openetw(lpvoid lpthreadparameter)
{
    m_dowhile = true;

    _getcwd(m_file, sizeof(m_file));

    strcat(m_file, "\\myfile.etl");
    m_traceconfig.wnode.buffersize = 1024;
    m_traceconfig.wnode.flags = wnode_flag_traced_guid;
    m_traceconfig.wnode.clientcontext = 3;
    m_traceconfig.buffersize = 1;
    m_traceconfig.minimumbuffers = 16;
    m_traceconfig.logfilemode = event_trace_real_time_mode;

    m_traceconfig.loggernameoffset = 120;
    m_traceconfig.flushtimer = 1;

    rtlmovememory(m_ptraceconfig + 8, &m_traceconfig, 120);
    rtlcopymemory(m_ptraceconfig + 128, session_name_file, sizeof(session_name_file));
    rtlcopymemory(m_ptraceconfig + 128 + sizeof(session_name_file), m_file, strlen(m_file));
    rtlcopymemory(m_ptraceconfig + 28, _flag, sizeof(_flag));

    ulong l_result = starttracea(&m_hsessionhandle, session_name_file, (pevent_trace_properties)(m_ptraceconfig + 8));
    
    if (m_hsessionhandle == null && l_result == error_access_denied)
    {
        cout << "starttracea失败!原因:无管理员权限!" << endl;
        return 0;
    }
    else if (m_hsessionhandle == null && l_result == error_already_exists)
    {

     m_hsessionhandle = 44;//输入上一次终止时候的句柄
        closeetw();
     
        cout << "starttracea失败!原因:已经有etw事件进行数据跟踪!请使用上方屏蔽代码关闭事件或者使用 计算机管理 停用事件:sample_process" << endl;
        controltracea(m_hsessionhandle, session_name_file, (pevent_trace_properties)(m_ptraceconfig + 8), 1);
        return 0;
    }
    cout << "hsessionhandle: " << m_hsessionhandle << endl;
    const uchar m_processguid[] = { 214, 44, 251, 34, 123, 14, 43, 66, 160, 199, 47, 173, 31, 208, 231, 22 }; // psprovguid
    l_result = enabletraceex((lpcguid)(m_processguid), 0, m_hsessionhandle, 1, 0, 16, 0, 0, 0);         //这里matchanykeyword的64其实是0x40,表示 #kernel_keywords_image

    event_trace_logfilea m_logfile;
    zeromemory(&m_logfile, sizeof(m_logfile));
    m_logfile.loggername = session_name_file;
    *((ulong*)((puchar)&m_logfile + 20)) = 268439808;
    m_logfile.eventrecordcallback = myprocessrecordevents;
    m_logfile.context = (pvoid)0x114514;//随便输入一个数就好了
    setlasterror(0);
    m_htracehandle = opentracea(&m_logfile);

    cout << "开始监视!" << endl;
    m_htracehandle_econt[0] = m_htracehandle;
    ulong rc = processtrace(m_htracehandle_econt, 1, 0, 0);
    return 0;
}

int main()
{
    createthread(null, null, openetw, null, null, null);
    //sleep(10000);
    system("pause");
    closeetw();
    return 0;
}

注意事项

必须给管理员权限

请正常退出(按任意键),否则trace不会自己关

以上就是c++实现etw进行进程变动监控详解的详细内容,更多关于c++进程监控的资料请关注其它相关文章!

《C++实现ETW进行进程变动监控详解.doc》

下载本文的Word格式文档,以方便收藏与打印。