首页
社区
课程
招聘
[原创]微软轻量级系统监控工具sysmon原理与实现------内核事件结构
2020-11-20 17:10 5673

[原创]微软轻量级系统监控工具sysmon原理与实现------内核事件结构

2020-11-20 17:10
5673

前两次我们分别讲了sysmon的ring3与ring0的实现原理,但是当初使用的版本的是8.X的版本,最新的版本10.X的sysmon功能有所增加,经过分析代码上也有变化。比如增加DNS得功能,这个功能实现也很简单,就是ETW里获取Microsoft-Windows-DNS-Client得数据,但是本篇不讲这个,本续篇主要讲内核里的事件结构。

所有的内核里上报的事件开头基本都是。

ReportSize
ReportType
struct _Report_Common_Header
{
ULONG ReportType;
ULONG ReportSize;
};

下面具体讲解每个事件的结构。

正文开始

1.FileCreate

下图是文件上报事件,除了上报上诉三个字段外,还有ProcessPid、EventCreateTime,FileCreateTime、hashVlaue算法id,hashvalue、三组进程相关的数据用户UserSid、进程ImageFileName、文件名FileName

可以看到内核里上报出来的事件类型是根据是否计算hash来判断,分别是10 、11

struct _Report_File
{
Common_Header Header;
CHAR data[16];
ULONG ProcessPid;
ULONG ParentPid;
LARGE_INTEGER CreateTime;
LARGE_INTEGER FileCreateTime;
ULONG HashingalgorithmRulev;
CHAR FileHash[84];
ULONG DataLength[4];
CHAR Data2[1];
};

2. 设置文件属性时间改变事件

内核出来的事件Type 值是2

结构体与FileCreate稍微有些不同,少了文件hash的计算的步骤,但是多了一个设置文件改变的时间。

struct _Report_File_SetAttrubute
{
Common_Header Header;
CHAR data[16];
ULONG ProcessPid;
ULONG ParentPid;
LARGE_INTEGER CreateTime;
LARGE_INTEGER FileTime;
LARGE_INTEGER FileCreateTime;
ULONG DataLength[4];
CHAR Data2[1];
};

3.进程创建事件

进程创建上报事件内核的事件Type值是4或者1

他的结构体如下(具体不在讲解,名字字面意思都能看懂)

struct _Report_Process
{
Report_Common_Header Header;
CHAR data[16];
ULONG ProcessPid;
ULONG ParentPid;
ULONG SessionId;
ULONG UserSid;
LARGE_INTEGER CreateTime;
LUID AuthenticationId;
ULONG TokenIsAppContainer;
LUID TokenId;
ULONG HashingalgorithmRule;
DWORD DataChunkLength[6];
CHAR Data[1];
};

4. 进程退出事件

进程退出事件内核的Type值是3

struct _Report_Process_Create
{
Report_Common_Header Header;
CHAR data[16];
ULONG ProcessPid;
ULONG ParentPid;
LARGE_INTEGER CreateTime;
ULONG SidLength;
ULONG XXXXXXX;
SID UserSid;
CHAR Data[1];
};

可以看到数据有进程id、 父进程id、事件创建时间、UserSid

5. 线程创建事件

内核里的事件类型是7

t010b27a2ae2af977c3.png

结构体如下

struct _ Report_Process_Thread
{
Report_Common_Header Header;
CHAR data[16];
LARGE_INTEGER CreateTime;
ULONG ThreadOwnerPidv;
ULONG ThreadId;
ULONG ThreadAddress;
ULONG OpenProcessPid;
WCHAR DllInfo[261];
WCHAR DllExportInfo[261];
};

DllInfo是指线程所在的模块名,DllExportInfo是该模块的导出表信息

6. OpenProcess事件

内核事件类型是: 9

结构体定义如下:

struct _ Report_OpenProcess
{
Report_Common_Header Header;
CHAR data[16];
ULONG ProcessId;
ULONG MyThreadId;
ULONG OpenPrcesid;
ULONG AccessMask;
LARGE_INTEGER CreateTime;
ULONG StatckTrackInfoSize;
ULONG DataLength[3];
CHAR Data[1];
};

7. 注册表事件

进程注册表操作事件的Type值是12

t018955ffa4d0c7981e.png

结构体如下:

struct _Report_Process_Registry
{
Report_Common_Header Header;
CHAR data[16];
ULONG OperateEventType;
ULONG ParentPid;
LARGE_INTEGER CreateTime;
ULONG ProcessPid;
ULOG DataLenth[5];
CHAR Data[1];
};

这里要说明的是附加数据段有5个数据

UserSid

RegistryOperateName

进程名带参数

KeyName

ValueName

其中RegistryOperateName的值是根据OperateEventType的值从下面的数组中选取

g_RegistryTypeName dd offset aUnknownEventTy
.rdata:100134D8 ; DATA XREF: SysmonCreateRegistryReportInfo+15E↑r
.rdata:100134D8 ; "Unknown Event type"
.rdata:100134DC dd offset aCreatekey ; "CreateKey"
.rdata:100134E0 dd offset aDeletekey ; "DeleteKey"
.rdata:100134E4 dd offset aRenamekey ; "RenameKey"
.rdata:100134E8 dd offset aCreatevalue ; "CreateValue"
.rdata:100134EC dd offset aDeletevalue ; "DeleteValue"
.rdata:100134F0 dd offset aRenamevalue ; "RenameValue"
.rdata:100134F4 dd offset aSetvalue ; "SetValue"
.rdata:100134F8 dword_100134F8 dd 100010h ; DATA XREF: Regist

8. 命名管道事件

内核的事件的Type的值是:13

结构体如下:

struct _Report_Process_NameedPipe
{
Report_Common_Header Header;
CHAR data[16];
ULONG NamedPipeType;
ULONG ParentPid;
LARGE_INTEGER CreateTime;
ULONG ProcessPid;
DWORD DataChunkLength[3];
CHAR Data[1];
};

在data块里会输出: NamePipeFileName 和ImageFileName 两个数据

9. 上报错误信息事件

内核的事件Type值是:6

结构体定义:

struct _ _Report_Event_Error
{
Report_Common_Header Header;
CHAR data[16];
ULONG ErrorDataLength[2];
CHAR Data[1];
};

Data信息里会输出两个错误信息的字符串,如:

下面我做一个小实验,以进程信息为例子,向sysomn的驱动发送IO控制码0xXXX0000X(我打码屏蔽了,希望读者自己去发现,不要做伸手党)

LARGE_INTEGER Request;
Request.LowPart = GetCurrentProcessId();
Request.HighPart = FALSE;
BYTE OutBuffer[4002] = { 0 };
ULONG BytesReturned = 0;
if ( SUCCEEDED( DeviceIoControl(
hObjectDrv,
SYSMON_REQUEST_PROCESS_INFO,
&Request,
8.
OutBuffer,
sizeof(OutBuffer),
&BytesReturned, 0 ) ) )
{
if ( BytesReturned )
{
Report_Process* pSysmon_Report_Process = (_Report_Process *)
&OutBuffer[0];
if ( pSysmon_Report_Process->Header.ReportSize )
{
CheckServiceOk = TRUE;
}
}
}
CloseHandle( hObjectDrv );

看结果:

可以看到结构体上的值都是对的,然后6个DataChunkLenggth都有值,我们在去看下面的Data内存

今天的续篇就此结束,sysmon还是可以挖掘很多很实用得东西,比如每个事件里得ProcessGuid 并不是随机生成得,而是有一定算法得,具体读者可以自行研究发现。



[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法

收藏
点赞1
打赏
分享
最新回复 (6)
雪    币: 18
活跃值: (974)
能力值: ( LV7,RANK:110 )
在线值:
发帖
回帖
粉丝
猪会被杀掉 1 2020-11-20 17:45
2
0
帮楼主顶顶.
雪    币: 1556
活跃值: (2087)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
killleer 2020-11-22 00:31
3
0
当楼主把sysmon了解透彻后就有了。。。
https://undev.ninja/sysmon-internals-from-file-delete-event-to-kernel-code-execution/
雪    币: 1989
活跃值: (1501)
能力值: ( LV8,RANK:120 )
在线值:
发帖
回帖
粉丝
basketwill 1 2020-11-22 20:53
4
0
killleer 当楼主把sysmon了解透彻后就有了。。。[em_86] https://undev.ninja/sysmon-internals-from-file-delete-event-to-kernel- ...

这些我都逆向了,只是没发出来,有些是其他网站约稿我才发的,大半年没来论坛太不活跃了, 就随便挑了一个发了,代码也逆向了差不多了,之前代码只开源了一小部分,不过我逆向的目的和你说的文章的目的不一样,我不是为了找漏洞,而是为了整体架构、功能到功能实现细节所有的整体代码的逆向!

最后于 2020-11-22 21:02 被basketwill编辑 ,原因:
雪    币: 1989
活跃值: (1501)
能力值: ( LV8,RANK:120 )
在线值:
发帖
回帖
粉丝
basketwill 1 2020-11-22 20:54
5
0
killleer 当楼主把sysmon了解透彻后就有了。。。[em_86] https://undev.ninja/sysmon-internals-from-file-delete-event-to-kernel- ...
下一部分慢慢发策略规则吧
雪    币: 1989
活跃值: (1501)
能力值: ( LV8,RANK:120 )
在线值:
发帖
回帖
粉丝
basketwill 1 2020-11-22 20:55
6
0

xxxxxxxxxx'

最后于 2020-11-22 21:01 被basketwill编辑 ,原因:
雪    币: 378
活跃值: (2812)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
appview 2020-12-24 02:12
7
0
Sysmon不错,不过还有些Bug
游客
登录 | 注册 方可回帖
返回