首页 > 其他分享 >驱动开发:内核注册并监控对象回调

驱动开发:内核注册并监控对象回调

时间:2022-12-12 12:34:06浏览次数:29  
标签:注册 OB 进程 线程 内核 pOperationInformation 监控 OPERATION 回调

在笔者上一篇文章`《驱动开发:内核枚举进程与线程ObCall回调》`简单介绍了如何枚举系统中已经存在的`进程与线程`回调,本章`LyShark`将通过对象回调实现对进程线程的`句柄`监控,在内核中提供了`ObRegisterCallbacks`回调,使用这个内核`回调`函数,可注册一个`对象`回调,不过目前该函数`只能`监控进程与线程句柄操作,通过监控进程或线程句柄,可实现保护指定进程线程不被终止的目的。

在笔者上一篇文章​​《驱动开发:内核枚举进程与线程ObCall回调》​​​简单介绍了如何枚举系统中已经存在的​​进程与线程​​​回调,本章​​LyShark​​​将通过对象回调实现对进程线程的​​句柄​​​监控,在内核中提供了​​ObRegisterCallbacks​​​回调,使用这个内核​​回调​​​函数,可注册一个​​对象​​​回调,不过目前该函数​​只能​​监控进程与线程句柄操作,通过监控进程或线程句柄,可实现保护指定进程线程不被终止的目的。

由于目前​​对象回调​​​只能监控进程与线程,而这个监控是通过​​ObjectType​​​这么一个成员控制的,如果成员是​​PsProcessType​​​则代表监控进程,反之​​PsThreadType​​​则是监控线程,无论监控进程还是线程都调用​​ObRegisterCallbacks​​这个函数来完成注册。

函数​​ObRegisterCallbacks​​​其微软对他的定义是这样的,用户传入​​OB_OPERATION_REGISTRATION​​​结构,以及​​OB_CALLBACK_REGISTRATION​​​回调结构,其中​​PreOperation​​​则是传入的回调函数,也是最重要的,其次是​​ObjectType​​指定成进程回调。

NTSTATUS ObRegisterCallbacks(
[in] POB_CALLBACK_REGISTRATION CallbackRegistration,
[out] PVOID *RegistrationHandle
);

首先来实现一个检测的案例,注册一个进程回调对象​​MyLySharkComObjectCallBack​​​,通过​​ObRegisterCallbacks​​​注册的回调只需要传入一个填充好的​​OB_CALLBACK_REGISTRATION​​​回调结构体,以及一个全局句柄即可,这个全局句柄的作用仅仅只是在程序结束时,调用​​ObUnRegisterCallbacks​​卸载监控而已,实现代码如下所示。

// 署名权
// right to sign one's name on a piece of work
// PowerBy: LyShark
// Email: [email protected]
#include <ntddk.h>
#include <ntstrsafe.h>

PVOID Globle_Object_Handle;

// 绕过签名检测
void BypassCheckSign(PDRIVER_OBJECT pDriverObj)
{
typedef struct _LDR_DATA
{
struct _LIST_ENTRY InLoadOrderLinks;
struct _LIST_ENTRY InMemoryOrderLinks;
struct _LIST_ENTRY InInitializationOrderLinks;
VOID* DllBase;
VOID* EntryPoint;
ULONG32 SizeOfImage;
UINT8 _PADDING0_[0x4];
struct _UNICODE_STRING FullDllName;
struct _UNICODE_STRING BaseDllName;
ULONG32 Flags;
}LDR_DATA, *PLDR_DATA;

PLDR_DATA ldr;
ldr = (PLDR_DATA)(pDriverObj->DriverSection);
ldr->Flags |= 0x20;
}

// 自定义回调
OB_PREOP_CALLBACK_STATUS MyLySharkComObjectCallBack(PVOID RegistrationContext, POB_PRE_OPERATION_INFORMATION OperationInformation)
{
DbgPrint("[lyshark] 执行回调函数... \n");
return STATUS_SUCCESS;
}

VOID UnDriver(PDRIVER_OBJECT driver)
{
ObUnRegisterCallbacks(Globle_Object_Handle);
DbgPrint("回调卸载完成... \n");
}

NTSTATUS DriverEntry(IN PDRIVER_OBJECT Driver, PUNICODE_STRING RegistryPath)
{
DbgPrint("hello lyshark.com \n");

BypassCheckSign(Driver);

OB_OPERATION_REGISTRATION Base; // 回调函数结构体
OB_CALLBACK_REGISTRATION CallbackReg; // 回调函数

CallbackReg.RegistrationContext = NULL; // 注册上下文(你回调函数返回参数)
CallbackReg.Version = OB_FLT_REGISTRATION_VERSION; // 注册回调版本
CallbackReg.OperationRegistration = &Base; // 回调结构体
CallbackReg.OperationRegistrationCount = 1; // 操作计数(下钩数量)

RtlUnicodeStringInit(&CallbackReg.Altitude, L"600000"); // 长度
Base.ObjectType = PsProcessType; // 进程操作类型.此处为进程操作
Base.Operations = OB_OPERATION_HANDLE_CREATE; // 操作句柄创建
Base.PreOperation = MyLySharkComObjectCallBack; // 你自己的回调函数
Base.PostOperation = NULL;

// 注册回调
if (ObRegisterCallbacks(&CallbackReg, &Globle_Object_Handle))
{
DbgPrint("[lyshark message] 回调注册成功...");
}
Driver->DriverUnload = UnDriver;
return STATUS_SUCCESS;
}

当驱动程序被加载以后,一旦有进程运行则会执行我们自己的​​MyLySharkComObjectCallBack​​回调,而在回调函数内则可以执行任意功能,运行如下所示。

驱动开发:内核注册并监控对象回调_Windows 内核驱动开发

如上所示只是演示基本的回调申请流程,回调函数通常需要包含两个值,其一​​RegistrationContext​​​用于标注上下文,其二​​POB_PRE_OPERATION_INFORMATION​​则用于标注进程或者线程创建的信息结构体。

OB_PREOP_CALLBACK_STATUS MyLySharkComObjectCallBack(PVOID RegistrationContext, POB_PRE_OPERATION_INFORMATION OperationInformation)

那么如何实现​​拦截进程启动​​这个功能呢,我们可以在回调函数中写入以下代码进行拦截。

  • CreateHandleInformation.DesiredAccess 将打开句柄的权限清零
  • CreateHandleInformation.OriginalDesiredAccess 判断是否终止
if (pOperationInformation->Operation == OB_OPERATION_HANDLE_CREATE)
{
DbgPrint("lyshark.exe 进程打开 \n");
pOperationInformation->Parameters->CreateHandleInformation.DesiredAccess=0;
if ((pOperationInformation->Parameters->CreateHandleInformation.OriginalDesiredAccess & PROCESS_TERMINATE) == PROCESS_TERMINATE)
{
pOperationInformation->Parameters->CreateHandleInformation.DesiredAccess &= ~PROCESS_TERMINATE;
}
}

拦截进程创建核心代码如下所示。

// 署名权
// right to sign one's name on a piece of work
// PowerBy: LyShark
// Email: [email protected]
#include <ntddk.h>
#include <ntstrsafe.h>

#define PROCESS_TERMINATE 0x1

// 导出两个API
NTKERNELAPI PEPROCESS IoThreadToProcess(PETHREAD Thread);
NTKERNELAPI char* PsGetProcessImageFileName(PEPROCESS Process);

// 全局句柄
PVOID Globle_Object_Handle = NULL;

// 绕过签名检测
void BypassCheckSign(PDRIVER_OBJECT pDriverObj)
{
typedef struct _LDR_DATA
{
struct _LIST_ENTRY InLoadOrderLinks;
struct _LIST_ENTRY InMemoryOrderLinks;
struct _LIST_ENTRY InInitializationOrderLinks;
VOID* DllBase;
VOID* EntryPoint;
ULONG32 SizeOfImage;
UINT8 _PADDING0_[0x4];
struct _UNICODE_STRING FullDllName;
struct _UNICODE_STRING BaseDllName;
ULONG32 Flags;
}LDR_DATA, *PLDR_DATA;

PLDR_DATA ldr;
ldr = (PLDR_DATA)(pDriverObj->DriverSection);
ldr->Flags |= 0x20;
}

// 判断是否是需要保护的进程
BOOLEAN CheckProcess(PEPROCESS eprocess)
{
char *Name = PsGetProcessImageFileName(eprocess);
if (!_stricmp("lyshark.exe", Name))
return TRUE;
else
return FALSE;
}

// 进程回调
OB_PREOP_CALLBACK_STATUS MyLySharkProcessObjectCallBack(PVOID RegistrationContext, POB_PRE_OPERATION_INFORMATION pOperationInformation)
{
HANDLE pid;

// 只取出进程回调
if (pOperationInformation->ObjectType != *PsProcessType)
{
return OB_PREOP_SUCCESS;
}

// 得到所有进程的ID
pid = PsGetProcessId((PEPROCESS)pOperationInformation->Object);
// DbgPrint("进程PID= %ld \n", pid);

UNREFERENCED_PARAMETER(RegistrationContext);

// 验证是否是需要的进程
if (CheckProcess((PEPROCESS)pOperationInformation->Object))
{
// 创建句柄
if (pOperationInformation->Operation == OB_OPERATION_HANDLE_CREATE)
{
DbgPrint("lyshark.exe 进程打开事件 \n");
pOperationInformation->Parameters->CreateHandleInformation.DesiredAccess=0;
if ((pOperationInformation->Parameters->CreateHandleInformation.OriginalDesiredAccess & PROCESS_TERMINATE) == PROCESS_TERMINATE)
{
DbgPrint("[LyShark Message] 拦截进程打开 \n");
pOperationInformation->Parameters->CreateHandleInformation.DesiredAccess &= ~PROCESS_TERMINATE;
}
}
// 复制句柄
if (pOperationInformation->Operation == OB_OPERATION_HANDLE_DUPLICATE)
{
DbgPrint("lyshark.exe 进程被关闭 \n");
pOperationInformation->Parameters->DuplicateHandleInformation.DesiredAccess=0;
if ((pOperationInformation->Parameters->DuplicateHandleInformation.OriginalDesiredAccess & PROCESS_TERMINATE) == PROCESS_TERMINATE)
{
pOperationInformation->Parameters->DuplicateHandleInformation.DesiredAccess &= ~PROCESS_TERMINATE;
}
}
}
return OB_PREOP_SUCCESS;
}

VOID UnDriver(PDRIVER_OBJECT driver)
{
ObUnRegisterCallbacks(Globle_Object_Handle);
DbgPrint("回调卸载完成... \n");
}

NTSTATUS DriverEntry(IN PDRIVER_OBJECT Driver, PUNICODE_STRING RegistryPath)
{
DbgPrint("hello lyshark.com \n");

BypassCheckSign(Driver);

OB_OPERATION_REGISTRATION ob_process_callback;
OB_CALLBACK_REGISTRATION op_process_operation;

memset(&ob_process_callback, 0, sizeof(ob_process_callback));
ob_process_callback.ObjectType = PsProcessType;
ob_process_callback.Operations = OB_OPERATION_HANDLE_CREATE | OB_OPERATION_HANDLE_DUPLICATE;
ob_process_callback.PreOperation = MyLySharkProcessObjectCallBack;
ob_process_callback.PostOperation = NULL;

RtlUnicodeStringInit(&op_process_operation.Altitude, L"600000");
op_process_operation.RegistrationContext = NULL;
op_process_operation.Version = OB_FLT_REGISTRATION_VERSION;
op_process_operation.OperationRegistration = &ob_process_callback;
op_process_operation.OperationRegistrationCount = 1;

// 注册进程回调
if (ObRegisterCallbacks(&op_process_operation, &Globle_Object_Handle))
{
DbgPrint("进程回调注册成功...");
}

Driver->DriverUnload = UnDriver;
return STATUS_SUCCESS;
}

加载这个驱动,当有进程被创建时,则首先判断是否是​​lyshark.exe​​如果是则直接禁止打开,也就是终止掉。

驱动开发:内核注册并监控对象回调_回调函数_02

同理进程可以被拦截,那么如果增加更多的过滤条件,则​​线程​​同样可以被拦截,拦截线程代码如下所示。

// 署名权
// right to sign one's name on a piece of work
// PowerBy: LyShark
// Email: [email protected]
#include <ntddk.h>
#include <ntstrsafe.h>

#define THREAD_TERMINATE2 0x1

// 导出两个API
NTKERNELAPI PEPROCESS IoThreadToProcess(PETHREAD Thread);
NTKERNELAPI char* PsGetProcessImageFileName(PEPROCESS Process);

// 全局句柄
PVOID Globle_Object_Handle = NULL;

// 绕过签名检测
void BypassCheckSign(PDRIVER_OBJECT pDriverObj)
{
typedef struct _LDR_DATA
{
struct _LIST_ENTRY InLoadOrderLinks;
struct _LIST_ENTRY InMemoryOrderLinks;
struct _LIST_ENTRY InInitializationOrderLinks;
VOID* DllBase;
VOID* EntryPoint;
ULONG32 SizeOfImage;
UINT8 _PADDING0_[0x4];
struct _UNICODE_STRING FullDllName;
struct _UNICODE_STRING BaseDllName;
ULONG32 Flags;
}LDR_DATA, *PLDR_DATA;

PLDR_DATA ldr;
ldr = (PLDR_DATA)(pDriverObj->DriverSection);
ldr->Flags |= 0x20;
}

// 判断是否是需要保护的进程
BOOLEAN CheckProcess(PEPROCESS eprocess)
{
char *Name = PsGetProcessImageFileName(eprocess);
if (!_stricmp("lyshark.exe", Name))
return TRUE;
else
return FALSE;
}

// 线程回调
OB_PREOP_CALLBACK_STATUS MyThreadObjectCallBack(PVOID RegistrationContext, POB_PRE_OPERATION_INFORMATION pOperationInformation)
{
PEPROCESS ep;
PETHREAD et;
HANDLE pid;

// 线程过滤
if (pOperationInformation->ObjectType != *PsThreadType)
{
return OB_PREOP_SUCCESS;
}

et = (PETHREAD)pOperationInformation->Object;
ep = IoThreadToProcess(et);
pid = PsGetProcessId(ep);

// DbgPrint("线程PID= %ld | TID= %ld \n", pid, PsGetThreadId(et));
UNREFERENCED_PARAMETER(RegistrationContext);

if (CheckProcess(ep))
{
if (pOperationInformation->Operation == OB_OPERATION_HANDLE_CREATE)
{
pOperationInformation->Parameters->CreateHandleInformation.DesiredAccess=0;
if ((pOperationInformation->Parameters->CreateHandleInformation.OriginalDesiredAccess & THREAD_TERMINATE2) == THREAD_TERMINATE2)
{
DbgPrint("[LyShark] 拦截lyshark.exe进程内 %d 线程创建 \n", PsGetThreadId(et));
pOperationInformation->Parameters->CreateHandleInformation.DesiredAccess &= ~THREAD_TERMINATE2;
}
}
if (pOperationInformation->Operation == OB_OPERATION_HANDLE_DUPLICATE)
{
pOperationInformation->Parameters->DuplicateHandleInformation.DesiredAccess=0;
if ((pOperationInformation->Parameters->DuplicateHandleInformation.OriginalDesiredAccess & THREAD_TERMINATE2) == THREAD_TERMINATE2)
{
pOperationInformation->Parameters->DuplicateHandleInformation.DesiredAccess &= ~THREAD_TERMINATE2;
}
}
}
return OB_PREOP_SUCCESS;
}

VOID UnDriver(PDRIVER_OBJECT driver)
{
ObUnRegisterCallbacks(Globle_Object_Handle);
DbgPrint("回调卸载完成... \n");
}

NTSTATUS DriverEntry(IN PDRIVER_OBJECT Driver, PUNICODE_STRING RegistryPath)
{
DbgPrint("hello lyshark.com \n");

BypassCheckSign(Driver);

OB_OPERATION_REGISTRATION ob_thread_callback;
OB_CALLBACK_REGISTRATION op_thread_operation;

memset(&ob_thread_callback, 0, sizeof(ob_thread_callback));
ob_thread_callback.ObjectType = PsThreadType;
ob_thread_callback.Operations = OB_OPERATION_HANDLE_CREATE | OB_OPERATION_HANDLE_DUPLICATE;
ob_thread_callback.PreOperation = MyThreadObjectCallBack;
ob_thread_callback.PostOperation = NULL;

RtlUnicodeStringInit(&op_thread_operation.Altitude, L"600001");
op_thread_operation.RegistrationContext = NULL;
op_thread_operation.Version = OB_FLT_REGISTRATION_VERSION;
op_thread_operation.OperationRegistration = &ob_thread_callback;
op_thread_operation.OperationRegistrationCount = 1;

// 注册进程回调
if (ObRegisterCallbacks(&op_thread_operation, &Globle_Object_Handle))
{
DbgPrint("进程回调注册成功...");
}

Driver->DriverUnload = UnDriver;
return STATUS_SUCCESS;
}

这段驱动加载后,如果有新线程被创建,则会被拦截并打印输出,效果图如下。

驱动开发:内核注册并监控对象回调_Windows 内核驱动开发_03


文章作者:​​lyshark​​ (王瑞)



标签:注册,OB,进程,线程,内核,pOperationInformation,监控,OPERATION,回调
From: https://blog.51cto.com/lyshark/5929384

相关文章

  • 驱动开发:内核无痕隐藏自身分析
    在笔者前面有一篇文章`《驱动开发:断链隐藏驱动程序自身》`通过摘除驱动的链表实现了断链隐藏自身的目的,但此方法恢复时会触发PG会蓝屏,偶然间在网上找到了......
  • 基于微信的产品设计01:注册登录及账号体系设计
    移动端联合登录的便捷性,以及越来越多用户倾向于选择微信作为全网登录账号,因此微信联合登录被许多APP产品作为第三方联合登录的首选。然而,采用微信联合登录后会造成一定问题,......
  • k8s容器内部通过Prometheus Operator部署MySQL Exporter监控k8s集群外部的MySQL
    写在前面在按照下面步骤操作之前,请先确保服务器已经部署k8s,prometheus,prometheusoperator,关于这些环境的部署,可以自行查找相关资料安装部署,本文档便不在此赘述。关于pro......
  • itop3568开发板旋转uboot logo和内核logo
    修改设备树rk_android11.0_sdk/kernel/arch/arm64/boot/dts/rockchip/topeet_rk3568_lcds.dtsi文件。如果配套的屏幕是LVDS7寸屏幕或者LVDS10.1寸1024*600屏幕或......
  • 监控系统哪家强?eBay 在监控系统上的实践应用!
    来源|eBayUnifiedMonitoringPlatform翻译|顾欣怡Sherlock.IO是eBay现有的监控平台,每天要处理上百亿条日志、事件和指标。FlinkStreamingjob实时处理系统用于......
  • 最全面系统的Zabbix讲解 _ 含源码&监控类型整理
    从本篇内容你能得到:1.Zabbix是什么、能做到什么2.Zabbix组件详解、架构和处理工作流程3.Zabbix各监控项类型的采集实现(SNMP、ICMP、Ping、简单检查等)4.Zabbix模板......
  • Zabbix监控cisco交换机配置指南
    1、开启交换机SNMP协议连接交换机,运行enable进入用户模式。Switch>enableSwitch#运行shsnmp查看SNMP协议是否开启Switch#shsnmp    运行configt进入全局......
  • Linux IO 监控与深入分析
    引言接昨天电话面试,面试官问了系统IO怎么分析,当时第一反应是使用iotop看系统上各进程的IO读写速度,然后使用iostat看CPU的%iowait时间占比,(%iowait:CPU等待输......
  • Linux性能监控之磁盘IO
    使用iostat查看磁盘IO  rkB/s每秒读取数据量kBwkB/s每秒写入数据量kBsvctmI/O请求的平均服务时间,单位毫秒awaitI/O请求的平均等待时间,单位毫秒;值越小,性能越好;ut......
  • linux 监控网络IO、磁盘、CPU、内存
    linux监控网络IO、磁盘、CPU、内存CPU:vmstat,sar–u,top磁盘IO:iostat–xd,sar–d,top网络IO:iftop-n,ifstat,dstat–nt,sar-nDEV23磁盘容量:df–h内存使用:free–m,top......