内容简介:上文讲解了sysmon的ring3部分实现原理,本文则开始讲解ring0部分。Sysmon的ring0是一个minifilter类型的驱动,内部实现了进程信息、文件访问信息以及注册表访问信息的记录,下面开始具体讲解它的实现流程。从DriverEntry(PDRIVER_OBJECT DriverObject, UNICODE_STRING *pRegistry)的pRegistry中截取末尾名称去获取并计算出设备名和DosDevices的名字。
上文讲解了sysmon的ring3部分实现原理,本文则开始讲解ring0部分。Sysmon的ring0是一个minifilter类型的驱动,内部实现了进程信息、文件访问信息以及注册表访问信息的记录,下面开始具体讲解它的实现流程。
- 驱动DriverEntry的初始化
从DriverEntry(PDRIVER_OBJECT DriverObject, UNICODE_STRING *pRegistry)的pRegistry中截取末尾名称去获取并计算出设备名和DosDevices的名字。
pDriverName = pRegistry->Buffer;
Len = pRegistry->Length >> 1;
pFirstName = &pDriverName[Len];
if ( pFirstName == pDriverName )
{
LABEL_8:
if ( *pFirstName != '\\' )
goto LABEL_10;
}
else
{
while ( *pFirstName != '\\' )
{
--pFirstName;
if ( pFirstName == pDriverName )
goto LABEL_8;
}
}
++pFirstName;
然后从pRegistry注册表中去获取sysmon的策略规则
使用RtlQueryRegistryValues函数,填入5个RTL_QUERY_REGISTRY_TABLE结构体
RTL_QUERY_REGISTRY_TABLE QueryRegTable[5];
RtlInitUnicodeString(&g_ProcessAccessNamesRule, 0);
memset(QueryRegTable, 0, 560u);
QueryRegTable[0].Flags = 1;
QueryRegTable[0].Name = L"Parameters";
QueryRegTable[3].EntryContext = &OptionRulesv18;
QueryRegTable[4].EntryContext = &hash_alogrithms;
QueryRegTable[1].Flags = 304;
QueryRegTable[1].Name = g_Name_ProcessAccessNames;
QueryRegTable[1].EntryContext = &g_ProcessAccessNamesRule;
QueryRegTable[1].DefaultType = 0x7000007;
QueryRegTable[1].DefaultData = &unk_10015C34;
QueryRegTable[1].DefaultLength = 4;
QueryRegTable[2].Flags = 304;
QueryRegTable[2].Name = L"ProcessAccessMasks";
QueryRegTable[2].EntryContext = &g_ProcessAccessMasksRule;
QueryRegTable[2].DefaultType = 0x3000000;
QueryRegTable[3].Flags = 304;
QueryRegTable[3].Name = (PWSTR)&g_wOption;
QueryRegTable[3].DefaultType = 0x4000000;
QueryRegTable[4].Flags = 304;
QueryRegTable[4].Name = (PWSTR)&g_wHashingalgorithm;
QueryRegTable[4].DefaultType = 0x4000000;
RtlQueryRegistryValues(0, g_SysmonRegisterPath.Buffer, QueryRegTable, 0, 0);
if ( !g_ProcessAccessNamesRule.Buffer
|| g_ProcessAccessNamesRule.Length <= 2u
|| g_ProcessAccessNamesRule.MaximumLength <= 4u )
{
RtlFreeUnicodeString(&g_ProcessAccessNamesRule);
RtlInitUnicodeString(&g_ProcessAccessNamesRule, 0);
}
g_OptionRules = (OptionRulesv18 >> 1) & 1;
对应的注册表键分别是L”Parameters”、L”ProcessAccessNames”、 L”ProcessAccessMasks” 、L” Option”、L” Hashingalgorithm”
然后再次获取L”Parameters”项下面的对应的L”Rules”的KeyValues信息,这里是驱动设置的规则。
下面展示出部分规则的数组
上面的过程结束后就开始判断操作系统是否支持flt
如果支持只实现IRP_MJ_CREATE、IRP_MJ_CLOSE 、IRP_MJ_DEVICE_CONTROL三个例程,后续会注册miniFlt过滤,如果不支持Flt就使用老的模式Sfilter的模式
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = (PDRIVER_DISPATCH)SysmonDispatchIrp;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = (PDRIVER_DISPATCH)SysmonDispatchIrp;
DriverObject->MajorFunction[IRP_MJ_CREATE] = (PDRIVER_DISPATCH)SysmonDispatchIrp;
if ( IsOpenPipeConnect && !IsSupportFlt )
{
DriverObject->MajorFunction[IRP_MJ_CREATE] = (PDRIVER_DISPATCH)SysmonDispatchIrp;
DriverObject->MajorFunction[1] = (PDRIVER_DISPATCH)SysmonDispatchIrp;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = (PDRIVER_DISPATCH)SysmonDispatchIrp;
DriverObject->MajorFunction[IRP_MJ_READ] = (PDRIVER_DISPATCH)SysmonDispatchIrp;
DriverObject->MajorFunction[IRP_MJ_WRITE] = (PDRIVER_DISPATCH)SysmonDispatchIrp;
DriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION] = (PDRIVER_DISPATCH)SysmonDispatchIrp;
DriverObject->MajorFunction[IRP_MJ_SET_INFORMATION] = (PDRIVER_DISPATCH)SysmonDispatchIrp;
DriverObject->MajorFunction[IRP_MJ_QUERY_EA] = (PDRIVER_DISPATCH)SysmonDispatchIrp;
DriverObject->MajorFunction[IRP_MJ_SET_EA] = (PDRIVER_DISPATCH)SysmonDispatchIrp;
DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = (PDRIVER_DISPATCH)SysmonDispatchIrp;
DriverObject->MajorFunction[IRP_MJ_QUERY_VOLUME_INFORMATION] = (PDRIVER_DISPATCH)SysmonDispatchIrp;
DriverObject->MajorFunction[IRP_MJ_SET_VOLUME_INFORMATION] = (PDRIVER_DISPATCH)SysmonDispatchIrp;
DriverObject->MajorFunction[IRP_MJ_DIRECTORY_CONTROL] = (PDRIVER_DISPATCH)SysmonDispatchIrp;
DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = (PDRIVER_DISPATCH)SysmonDispatchIrp;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = (PDRIVER_DISPATCH)SysmonDispatchIrp;
DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = (PDRIVER_DISPATCH)SysmonDispatchIrp;
DriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = (PDRIVER_DISPATCH)SysmonDispatchIrp;
DriverObject->MajorFunction[IRP_MJ_LOCK_CONTROL] = (PDRIVER_DISPATCH)SysmonDispatchIrp;
DriverObject->MajorFunction[IRP_MJ_CLEANUP] = (PDRIVER_DISPATCH)SysmonDispatchIrp;
DriverObject->MajorFunction[IRP_MJ_CREATE_MAILSLOT] = (PDRIVER_DISPATCH)SysmonDispatchIrp;
DriverObject->MajorFunction[IRP_MJ_QUERY_SECURITY] = (PDRIVER_DISPATCH)SysmonDispatchIrp;
DriverObject->MajorFunction[IRP_MJ_SET_SECURITY] = (PDRIVER_DISPATCH)SysmonDispatchIrp;
DriverObject->MajorFunction[IRP_MJ_POWER] = (PDRIVER_DISPATCH)SysmonDispatchIrp;
DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = (PDRIVER_DISPATCH)SysmonDispatchIrp;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CHANGE] = (PDRIVER_DISPATCH)SysmonDispatchIrp;
DriverObject->MajorFunction[IRP_MJ_QUERY_QUOTA] = (PDRIVER_DISPATCH)SysmonDispatchIrp;
DriverObject->MajorFunction[IRP_MJ_SET_QUOTA] = (PDRIVER_DISPATCH)SysmonDispatchIrp;
}
然后就是常规过程,IoCreateDevice、IoCreateSymbolicLink。
然后根据操作系统是否支持FltRegisterFilter(Driver, &g_Registration, &g_pFilter);
具体创建了哪些minifilter,接着看结构体
OperationRegistration dd IRP_MJ_CREATE ; DATA XREF: .data:10015014↓o .rdata:10013454 dd 0 .rdata:10013458 dd offset PreOperation .rdata:1001345C dd offset PostOperation .rdata:10013460 dd 0 .rdata:10013464 dd IRP_MJ_CLEANUP .rdata:10013468 dd 0 .rdata:1001346C dd offset PreOperation .rdata:10013470 dd offset PostOperation .rdata:10013474 dd 0 .rdata:10013478 dd IRP_MJ_SET_INFORMATION .rdata:1001347C dd 0 .rdata:10013480 dd offset PreOperation .rdata:10013484 dd offset PostOperation .rdata:10013488 dd 0 .rdata:1001348C dd IRP_MJ_CLOSE .rdata:10013490 dd 0 .rdata:10013494 dd offset PreOperation .rdata:10013498 dd offset PostOperation .rdata:1001349C dd 0 .rdata:100134A0 dd IRP_MJ_CREATE_NAMED_PIPE .rdata:100134A4 dd 0 .rdata:100134A8 dd offset PreOperation .rdata:100134AC dd offset PostOperation .rdata:100134B0 dd 0 .rdata:100134B4 dd IRP_MJ_OPERATION_END .rdata:100134B8 dd 0 .rdata:100134BC dd 0 .rdata:100134C0 dd 0 .rdata:100134C4 dd 0
从上可以看到minifilter过滤了IRP_MJ_CREATE、IRP_MJ_CLEANUP、IRP_MJ_SET_INFORMATION、IRP_MJ_CLOSE、IRP_MJ_CREATE_NAMED_PIPE
文件系统相关的注册完毕,然后就是设置一些进程、线程相关的回调函数例程
PsSetLoadImageNotifyRoutine(SysmonLoadImageNotifyRoutine); PsSetCreateThreadNotifyRoutine(PsCreateThreadNotifyRoutine); PsSetCreateProcessNotifyRoutine(PsCreateProcessNotifyRoutine, 0);
为了记录注册表sysmon还注册表注册表CmRegisterCallback(RegisterCallback, 0, &Cookie);回调,
为了记录进程open对象的事件注册了ob事件
g_bIsRegisterCallback = 1; g_OperationRegistration.ObjectType = (POBJECT_TYPE *)PsProcessType; g_OperationRegistration.Operations = 1; g_OperationRegistration.PreOperation = PreProcessOperation; g_OperationRegistration.PostOperation = PostProcessOperation; g_CallbackRegistration.OperationRegistration = &g_OperationRegistration; *(_DWORD *)&g_CallbackRegistration.Version = 0x10100; g_CallbackRegistration.RegistrationContext = 0; RtlInitUnicodeString(&g_CallbackRegistration.Altitude, L"1000"); Status = g_ObRegisterCallbacks(&g_CallbackRegistration, &RegistrationHandle);
为了获取管道的事件,它挂接了设备L \\Device\\NamedPipe ,创建了L \\Device\\SysmonPipeFilter 的过滤设备
至此sysmon的DriverEntry的初始化动作基本结束了。
- IRP_MJ_DEVICE_CONTROL例程
Case 0x83400000:
打开驱动开启标志,并且获取且保存当前UI进程的句柄
Case 0x83400004:
Ring3请求事件信息,并返回到ring3的缓冲区
Case 0x83400008:
加载策略规则
Case 0x8340000C:
获取传入进程的相关信息(包括TokenUser、pTokenStatics、TokenGroup、TokenSeesion)
还会获取进程pImagePathName、pCommandLine、CurrentDirectory
获取进程的CreateTime
该事件类型为4或者1
- 文件信息的记录
Minifilter的PreOperation(PFLT_CALLBACK_DATA pData, PFLT_RELATED_OBJECTS FltObjects, PVOID *CompletionContext)例程为主要的判断逻辑例程,先判断当前FileObject的路径是否为管道路径,管道事件直接记录上报事件
特别判断下IRP_MJ_SET_INFORMATION、IRP_MJ_CLEANUP,并且分别上报_,注意在判断IRP_MJ_SET_INFORMATION的时候只记录了RequestorMode是1即USER_MODE,并且是设置FileBasicInformation的请求。
PreOperation处理完毕,则PostOperation(PFLT_CALLBACK_DATA pData, PFLT_RELATED_OBJECTS pFltFileObj, PVOID CompletionContext, int Flags)对前者处理的上下文CompletionContext进行记录日志或者释放的处理,以IRP_MJ_SET_INFORMATION为例,PostOPerate则对PreOperate的CompletionContext的数据进行上报。
- 注册表信息的记录
Sysmon初始化的时候注册了一个注册表过滤,CmRegisterCallback(RegisterCallback, 0, &Cookie);回调函数是NTSTATUS __stdcall RegisterCallback(PVOID CallbackContext, PVOID Argument1, PVOID Argument2),参数Argument1是过滤的注册表操作类型,sysmon过滤了0(RegNtDeleteKey / RegNtPreDeleteKey) 、4( RegNtRenameKey\RegNtPreRenameKey)、11(RegNtPostCreateKey)、15(RegNtPostDeleteKey)、16(RegNtPostSetValueKey)、17(RegNtPostDeleteValueKey)、19(RegNtPostRenameKey)27(RegNtPostCreateKeyEx)的注册表操作
- 进程操作过滤
Sysmon注册了进程操作过滤,g_ObRegisterCallbacks(&g_CallbackRegistration, &RegistrationHandle);,
他只记录操作类型为OB_OPERATION_HANDLE_CREATE,并且只记录A进程操作B进程,A和B不是同一个进程,注意RtlWalkFrameChain这个函数是获取当前操作线程的线程栈,KeQuerySystemTime(&pOpenInfo.CreateTime);是获取当前系统时间,并且会把这些信息上报。
- 其他重点技术细节
- 进程模块的枚举
ZwQueryInformationProcess(ProcessHandle, ProcessBasicInformation, &ProcessInformation, 0x18u, 0)获取ProcessInformation的信息,从PebBaseAddress = ProcessInformation.PebBaseAddress;取得进程PEB的地址,在PEB结构中得到LDR的地址,LDR是进程加载模块的结构体,
struct _PEB
{
UCHAR InheritedAddressSpace;
UCHAR ReadImageFileExecOptions;
UCHAR BeingDebugged;
UCHAR BitField;
PVOID Mutant;
PVOID ImageBaseAddress;
PPEB_LDR_DATA Ldr;
PRTL_USER_PROCESS_PARAMETERS ProcessParameters;
PVOID SubSystemData;
PVOID ProcessHeap;
PRTL_CRITICAL_SECTION FastPebLock;
PVOID AtlThunkSListPtr;
PVOID IFEOKey;
ULONG CrossProcessFlags;
unsigned __int32 ProcessInJob : 1;
unsigned __int32 ProcessInitializing : 1;
unsigned __int32 ReservedBits0 : 30;
union
{
PVOID KernelCallbackTable;
PVOID UserSharedInfoPtr;
};
ULONG SystemReserved[1];
。。。。。。
}
PPEB_LDR_DATA Ldr;这个就是加载模块的结构,有三种加载表内存加载表,加载顺序表,初始化加载表从中可以枚举出模块信息。
struct _PEB_LDR_DATA
{
ULONG Length;
UCHAR Initialized;
PVOID SsHandle;
LIST_ENTRY InLoadOrderModuleList;
LIST_ENTRY InMemoryOrderModuleList;
LIST_ENTRY InInitializationOrderModuleList;
};
- 进程参数的获取
大致可以看到如下,首先要KeStackAttachProcess进程的空间,然后获取PEB地址,从PEB中的到ProcessParameters的结构
ProcessParameters结构如下:
struct _RTL_USER_PROCESS_PARAMETERS
{
ULONG MaximumLength;
ULONG Length;
ULONG Flags;
ULONG DebugFlags;
PVOID ConsoleHandle;
ULONG ConsoleFlags;
PVOID StandardInput;
PVOID StandardOutput;
PVOID StandardError;
CURDIR CurrentDirectory;
UNICODE_STRING DllPath;
UNICODE_STRING ImagePathName;
UNICODE_STRING CommandLine;
PVOID Environment;
ULONG StartingX;
ULONG StartingY;
ULONG CountX;
ULONG CountY;
ULONG CountCharsX;
ULONG CountCharsY;
ULONG FillAttribute;
ULONG WindowFlags;
ULONG ShowWindowFlags;
UNICODE_STRING WindowTitle;
UNICODE_STRING DesktopInfo;
UNICODE_STRING ShellInfo;
UNICODE_STRING RuntimeData;
RTL_DRIVE_LETTER_CURDIR CurrentDirectores[32];
ULONG EnvironmentSize;
};
可以看到该结构中进程参数相关的各种信息。
- 进程Token相关信息的获取
都是通过ZwQueryInformationToken函数去获取,只是是使用不同的ClassInformation类去获取,定义如下
typedef enum _TOKEN_INFORMATION_CLASS {
TokenUser ,
TokenGroups ,
TokenPrivileges ,
TokenOwner ,
TokenPrimaryGroup ,
TokenDefaultDacl ,
TokenSource ,
TokenType ,
TokenImpersonationLevel ,
TokenStatistics ,
TokenRestrictedSids ,
TokenSessionId ,
TokenGroupsAndPrivileges ,
TokenSessionReference ,
TokenSandBoxInert ,
TokenAuditPolicy ,
TokenOrigin ,
TokenElevationType ,
TokenLinkedToken ,
TokenElevation ,
TokenHasRestrictions ,
TokenAccessInformation ,
TokenVirtualizationAllowed ,
TokenVirtualizationEnabled ,
TokenIntegrityLevel ,
TokenUIAccess ,
TokenMandatoryPolicy ,
TokenLogonSid ,
TokenIsAppContainer ,
TokenCapabilities ,
TokenAppContainerSid ,
TokenAppContainerNumber ,
TokenUserClaimAttributes ,
TokenDeviceClaimAttributes ,
TokenRestrictedUserClaimAttributes ,
TokenRestrictedDeviceClaimAttributes ,
TokenDeviceGroups ,
TokenRestrictedDeviceGroups ,
TokenSecurityAttributes ,
TokenIsRestricted ,
TokenProcessTrustLevel ,
TokenPrivateNameSpace ,
TokenSingletonAttributes ,
TokenBnoIsolation ,
TokenChildProcessFlags ,
MaxTokenInfoClass
} TOKEN_INFORMATION_CLASS, *PTOKEN_INFORMATION_CLASS;
需要获取那个就可以选择那一个。
本文大致讲解完毕,内部还有很多很有意思的技术细节由于篇幅原因,读者可以自己深入挖掘,在做一个产品的时候,我们可以分析他人的产品,不仅可以了解他人的产品的长处和不足,同时也可以补充自己产品的不足的之处,一个好的产品就是在不断的琢磨研究与推翻,更重要的是细节的体现才能做好产品。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Design Accessible Web Sites
Jeremy Sydik / Pragmatic Bookshelf / 2007-11-05 / USD 34.95
It's not a one-browser web anymore. You need to reach audiences that use cell phones, PDAs, game consoles, or other "alternative" browsers, as well as users with disabilities. Legal requirements for a......一起来看看 《Design Accessible Web Sites》 这本书的介绍吧!