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

文章地址:https://www.cnblogs.com/Icys/p/EtwProcess.html

何为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;
}

注意事项

  1. 必须给管理员权限

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

其他

作者(本人)水平有限,部分翻译可能有误,代码有问题可以直接回复我。

以后有时间可能会考虑翻译一下这个作者其他的关于Etw的例子,毕竟Etw实现的这些功能都很有意思,并且都比较高级。

C++实现ETW进行进程变动监控的更多相关文章

  1. zabbix3.0.4添加对指定进程的监控

    zabbix3.0.4添加对进程的监控: 主要思路: 通过 ps -ef|grep sdk-push-1.0.0.jar |grep -v grep|wc -l 这个命令来判断进程sdk-push是否 ...

  2. C#进程创建监控

    关于c#进程创建监控的文章大多都是“遍历一次进程用if去判断存在或否”这样的方法,我觉得体验不是很好.这几天写的一个软件正好需要实时监控进程创建的模块,在网上找到了很不错的方法,整理一下分享出来给大家 ...

  3. .NET Core项目部署到Linux(Centos7)(八)为.NET Core项目创建Supervisor进程守护监控

    目录 1.前言 2.环境和软件的准备 3.创建.NET Core API项目 4.VMware Workstation虚拟机及Centos 7安装 5.Centos 7安装.NET Core环境 6. ...

  4. 如何灵活运用Linux 进程资源监控和进程限制

    导读 每个 Linux 系统管理员都应该知道如何验证硬件.资源和主要进程的完整性和可用性.另外,基于每个用户设置资源限制也是其中一项必备技能. 在这篇文章中,我们会介绍一些能够确保系统硬件和软件正常工 ...

  5. Ubuntu 14.10 下运行进程实时监控pidstat命令详解

    简介 pidstat主要用于监控全部或指定进程占用系统资源的情况,如CPU,内存.设备IO.任务切换.线程等.pidstat首次运行时显示自系统启动开始的各项统计信息,之后运行pidstat将显示自上 ...

  6. linux服务器内存、根目录使用率、某进程的监控告警脚本

    脚本内容如下 #!/bin/bash #磁盘超过百分之80发送邮件告警 DISK_USED=`df -T |sed -n "2p" |awk '{print ($4/$3)*100 ...

  7. Linux 运行进程实时监控pidstat命令详解

    简介 pidstat主要用于监控全部或指定进程占用系统资源的情况,如CPU,内存.设备IO.任务切换.线程等.pidstat首次运行时显示自系统启动开始的各项统计信息,之后运行pidstat将显示自上 ...

  8. python 守护进程,监控进程

    守护进程代码: import time, os import subprocess def run(): while True: taskList = os.popen('tasklist').rea ...

  9. 进程实时监控pidstat命令详解

    pidstat主要用于监控全部或指定进程占用系统资源的情况,如CPU,内存.设备IO.任务切换.线程等.pidstat首次运行时显示自系统启动开始的各项统计信息,之后运行pidstat将显示自上次运行 ...

随机推荐

  1. MKL库奇异值分解(LAPACKE_dgesvd)

    对任意一个\(m\times n\)的实矩阵,总可以按照SVD算法对其进行分解.即: \[A = U\Sigma V^T \] 其中\(U.V\)分别为\(m\times m.n\times n\)的 ...

  2. 眼见不一定为实:调用链HBase倾斜修复

    hello,大家好,我是小楼. 今天给大家分享一个关于HBase数据倾斜的排查案例,不懂调用链?不懂HBase?没关系,看完包懂~ 背景 最近HBase负责人反馈HBase存储的调用链数据偶尔出现极其 ...

  3. XCTF练习题---MISC---如来十三掌

    XCTF练习题---MISC---如来十三掌 flag:flag{bdscjhbkzmnfrdhbvckijndskvbkjdsab} 解题步骤: 1.观察题目,下载附件进行查看 2.打开附件,压根看 ...

  4. 【Linux 网络编程】生动讲解 Reactor 模式与 Proactor 模式

    五种 I/O 模型 先花费点时间了解这几种 I/O 模型,有助于后面的理解. 阻塞 I/O 与非阻塞 I/O 阻塞和非阻塞的概念能应用于所有的文件描述符,而不仅仅是 socket.我们称阻塞的文件描述 ...

  5. 【Java分享客栈】未来迈向高级工程师绕不过的技能:JMeter压测

    前言 因为工作需要,久违的从自己的有道云笔记中去寻找压测相关的内容,翻开之后发现还不错,温故一遍后顺便整理出来分享给大家. 题外话,工作8年多,有道云笔记不知不觉都6G多了,扫一眼下来尽是云烟过往,竟 ...

  6. 119_Power Pivot 长尾明细显示为【其他】

    博客:www.jiaopengzi.com 焦棚子的文章目录 请点击下载附件 一.背景 最近比较忙,太久不没有更新文章,确实没有好的素材,就写一个吧. 在关于产品数据分析的时候,我们经常关注的是主要的 ...

  7. spring 配置文件 --bean

    bean标配的基本配置        id:Bean实例在Spring容器中的唯一标识        class Bean的全限定名        scope            1.当scope的 ...

  8. column-文本对齐输出

    文本输出对齐,可以指定对应的分隔符,将上下文的字符串按分隔符列对齐. 语法 column [选项] 选项 -s 设置分隔符,默认为空格. -t 判断输入的列数来创建一个表,使列对齐. -c 设置显示的 ...

  9. Spring-boot整合Activiti7

    Spring-boot整合Activiti7 pom.xml    <properties>        <maven.compiler.source>15</mave ...

  10. 【NOIP2017 提高组正式赛】列队 题解

    题目大意 有一个 \(n\times m\) 的方阵,每次有 \((x,y)\) 离开,离开后有两个命令 向左看齐.这时第一列保持不动,所有学生向左填补空缺.这条指令之后,空位在第 \(x\) 行第 ...