-
-
[原创]使用ETW监控冒个进程创建和启动服务以及加载驱动程序
-
发表于:
2021-6-25 17:13
21689
-
[原创]使用ETW监控冒个进程创建和启动服务以及加载驱动程序
做edr的同学大概都晓得edr中经常需要监控windows服务以及windows驱动模块的加载的监控,windows驱动的加载的监控的方法通常使用和windows模块加载监控的方法一样,在内核驱动里使用PsSetLoadImageNotifyRoutine设置模块加载回调例程来监控ring3模块以及ring0模块的加载,回调函数 PsSetLoadImageNotifyRoutine的第二个参数判断,如果 Process Id是0 ,则表示加载驱动,如果Process Id非零,则表示加载DLL。但是这种方法监控驱动加载通常的进程Id是0,因为驱动加载的时候使用的是APC线程,当前上下文在系统线程内,所以得不到具体的进程id.
堆栈如下
所以在当到达PsSetLoadImageNotifyRoutine的时候加载驱动模块的加载的时候pid就是0了,是否有其他方法可以监控到具体的进程?答案是肯定的, 那就是ETW。
ETW是个windows日志事件Trace,每个Trace日志都有他自己的Guid,要监控服务以及驱动加载的日志就得找到对应的GUID,这个GUID是多少呢,下面我们就来具体分析。
最好的方式就是逆向调试分析,打开一个安装驱动服务的软件,比如我们这次使用的是
接下来就是上调试器附加这个进程
在调试器里找到CreateServiceW函数,发现这个函数会调用sechost.dll的sechost.CreateServiceW的函数
发现最终的实现是在这个sechost模块的CreateServiceW,在windows/system32的目录下找到对应的模块,在IDA下以及调试器看到,在运行到最后会调用NdrClientCall4
注意该函数的第一个参数是pStubDescriptor,它的类型是PMIDL_STUB_DESC pStubDescriptor,是一个结构体
typedef struct _MIDL_STUB_DESC {
void *RpcInterfaceInformation;
void * )(size_t) *(pfnAllocate;
void()(void *) * pfnFree;
union {
handle_t *pAutoHandle;
handle_t *pPrimitiveHandle;
PGENERIC_BINDING_INFO pGenericBindingInfo;
} IMPLICIT_HANDLE_INFO;
const NDR_RUNDOWN *apfnNdrRundownRoutines;
const GENERIC_BINDING_ROUTINE_PAIR *aGenericBindingRoutinePairs;
const EXPR_EVAL *apfnExprEval;
const XMIT_ROUTINE_QUINTUPLE *aXmitQuintuple;
const unsigned char *pFormatTypes;
int fCheckBounds;
unsigned long Version;
MALLOC_FREE_STRUCT *pMallocFreeStruct;
long MIDLVersion;
const COMM_FAULT_OFFSETS *CommFaultOffsets;
const USER_MARSHAL_ROUTINE_QUADRUPLE *aUserMarshalQuadruple;
const NDR_NOTIFY_ROUTINE *NotifyRoutineTable;
ULONG_PTR mFlags;
const NDR_CS_ROUTINES *CsRoutineTables;
void *ProxyServerInfo;
const NDR_EXPR_DESC *pExprInfo;
} MIDL_STUB_DESC;
最主要的是结构体中的第一个字段RpcInterfaceInformation,这个结构是RPC接口的信息,定义这RPC的GUID,当前对应的是全局内存是dword_10008F38,所以它对应的是RPC的GUIID
可以看出GUID是 367ABB81-9844-35F1-AD32-98F038001003
https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-scmr/4c8b7701-b043-400c-9350-dc29cfaa5e7a
意思就是说说这个GUID的RPC对应的名字是\PIPE\svcctl,而且它是在server.exe的这个服务进程里创建的。
接下来的工作就是去逆向service.exe这个进程。
在server.exe的程序里我们可以找到对应的RPC 接口函数是RCreateServiceW
接着会调用ScCreateServiceRpc
在下面的地方我们会看到一个函数
I_RpcBindingInqLocalClientPID(0i64, &Pid);,这个函数会获取当前RPC的客户端进程id
接着就是输出日志,当然前提是这个日志已经开启并且有人去接收它,
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!