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

打印 上一主题 下一主题

主题 896|帖子 896|积分 2688

在笔者上一篇文章《驱动开发:内核枚举进程与线程ObCall回调》简单介绍了如何枚举系统中已经存在的进程与线程回调,本章LyShark将通过对象回调实现对进程线程的句柄监控,在内核中提供了ObRegisterCallbacks回调,使用这个内核回调函数,可注册一个对象回调,不过目前该函数只能监控进程与线程句柄操作,通过监控进程或线程句柄,可实现保护指定进程线程不被终止的目的。
由于目前对象回调只能监控进程与线程,而这个监控是通过ObjectType这么一个成员控制的,如果成员是PsProcessType则代表监控进程,反之PsThreadType则是监控线程,无论监控进程还是线程都调用ObRegisterCallbacks这个函数来完成注册。
函数ObRegisterCallbacks其微软对他的定义是这样的,用户传入OB_OPERATION_REGISTRATION结构,以及OB_CALLBACK_REGISTRATION回调结构,其中PreOperation则是传入的回调函数,也是最重要的,其次是ObjectType指定成进程回调。
  1. NTSTATUS ObRegisterCallbacks(
  2.   [in]  POB_CALLBACK_REGISTRATION CallbackRegistration,
  3.   [out] PVOID                     *RegistrationHandle
  4. );
复制代码
首先来实现一个检测的案例,注册一个进程回调对象MyLySharkComObjectCallBack,通过ObRegisterCallbacks注册的回调只需要传入一个填充好的OB_CALLBACK_REGISTRATION回调结构体,以及一个全局句柄即可,这个全局句柄的作用仅仅只是在程序结束时,调用ObUnRegisterCallbacks卸载监控而已,实现代码如下所示。
  1. // 署名权
  2. // right to sign one's name on a piece of work
  3. // PowerBy: LyShark
  4. // Email: me@lyshark.com
  5. #include <ntddk.h>
  6. #include <ntstrsafe.h>
  7. PVOID Globle_Object_Handle;
  8. // 绕过签名检测
  9. void BypassCheckSign(PDRIVER_OBJECT pDriverObj)
  10. {
  11.         typedef struct _LDR_DATA
  12.         {
  13.                 struct _LIST_ENTRY InLoadOrderLinks;
  14.                 struct _LIST_ENTRY InMemoryOrderLinks;
  15.                 struct _LIST_ENTRY InInitializationOrderLinks;
  16.                 VOID*        DllBase;
  17.                 VOID*        EntryPoint;
  18.                 ULONG32      SizeOfImage;
  19.                 UINT8        _PADDING0_[0x4];
  20.                 struct _UNICODE_STRING FullDllName;
  21.                 struct _UNICODE_STRING BaseDllName;
  22.                 ULONG32      Flags;
  23.         }LDR_DATA, *PLDR_DATA;
  24.         PLDR_DATA ldr;
  25.         ldr = (PLDR_DATA)(pDriverObj->DriverSection);
  26.         ldr->Flags |= 0x20;
  27. }
  28. // 自定义回调
  29. OB_PREOP_CALLBACK_STATUS MyLySharkComObjectCallBack(PVOID RegistrationContext, POB_PRE_OPERATION_INFORMATION OperationInformation)
  30. {
  31.         DbgPrint("[lyshark] 执行回调函数... \n");
  32.         return STATUS_SUCCESS;
  33. }
  34. VOID UnDriver(PDRIVER_OBJECT driver)
  35. {
  36.         ObUnRegisterCallbacks(Globle_Object_Handle);
  37.         DbgPrint("回调卸载完成... \n");
  38. }
  39. NTSTATUS DriverEntry(IN PDRIVER_OBJECT Driver, PUNICODE_STRING RegistryPath)
  40. {
  41.         DbgPrint("hello lyshark.com \n");
  42.         BypassCheckSign(Driver);
  43.         OB_OPERATION_REGISTRATION Base;                          // 回调函数结构体
  44.         OB_CALLBACK_REGISTRATION CallbackReg;                    // 回调函数
  45.         CallbackReg.RegistrationContext = NULL;                  // 注册上下文(你回调函数返回参数)
  46.         CallbackReg.Version = OB_FLT_REGISTRATION_VERSION;       // 注册回调版本
  47.         CallbackReg.OperationRegistration = &Base;               // 回调结构体
  48.         CallbackReg.OperationRegistrationCount = 1;              // 操作计数(下钩数量)
  49.         RtlUnicodeStringInit(&CallbackReg.Altitude, L"600000");   // 长度
  50.         Base.ObjectType = PsProcessType;                          // 进程操作类型.此处为进程操作
  51.         Base.Operations = OB_OPERATION_HANDLE_CREATE;             // 操作句柄创建
  52.         Base.PreOperation = MyLySharkComObjectCallBack;           // 你自己的回调函数
  53.         Base.PostOperation = NULL;
  54.         // 注册回调
  55.         if (ObRegisterCallbacks(&CallbackReg, &Globle_Object_Handle))
  56.         {
  57.                 DbgPrint("[lyshark message] 回调注册成功...");
  58.         }
  59.         Driver->DriverUnload = UnDriver;
  60.         return STATUS_SUCCESS;
  61. }
复制代码
当驱动程序被加载以后,一旦有进程运行则会执行我们自己的MyLySharkComObjectCallBack回调,而在回调函数内则可以执行任意功能,运行如下所示。

如上所示只是演示基本的回调申请流程,回调函数通常需要包含两个值,其一RegistrationContext用于标注上下文,其二POB_PRE_OPERATION_INFORMATION则用于标注进程或者线程创建的信息结构体。
  1. OB_PREOP_CALLBACK_STATUS MyLySharkComObjectCallBack(PVOID RegistrationContext, POB_PRE_OPERATION_INFORMATION OperationInformation)
复制代码
那么如何实现拦截进程启动这个功能呢,我们可以在回调函数中写入以下代码进行拦截。

  • CreateHandleInformation.DesiredAccess 将打开句柄的权限清零
  • CreateHandleInformation.OriginalDesiredAccess 判断是否终止
  1. if (pOperationInformation->Operation == OB_OPERATION_HANDLE_CREATE)
  2. {
  3.         DbgPrint("lyshark.exe 进程打开 \n");
  4.         pOperationInformation->Parameters->CreateHandleInformation.DesiredAccess=0;
  5.         if ((pOperationInformation->Parameters->CreateHandleInformation.OriginalDesiredAccess & PROCESS_TERMINATE) == PROCESS_TERMINATE)
  6.         {
  7.                 pOperationInformation->Parameters->CreateHandleInformation.DesiredAccess &= ~PROCESS_TERMINATE;
  8.         }
  9. }
复制代码
拦截进程创建核心代码如下所示。
  1. // 署名权
  2. // right to sign one's name on a piece of work
  3. // PowerBy: LyShark
  4. // Email: me@lyshark.com
  5. #include <ntddk.h>
  6. #include <ntstrsafe.h>
  7. #define PROCESS_TERMINATE 0x1
  8. // 导出两个API
  9. NTKERNELAPI PEPROCESS IoThreadToProcess(PETHREAD Thread);
  10. NTKERNELAPI char* PsGetProcessImageFileName(PEPROCESS Process);
  11. // 全局句柄
  12. PVOID Globle_Object_Handle = NULL;
  13. // 绕过签名检测
  14. void BypassCheckSign(PDRIVER_OBJECT pDriverObj)
  15. {
  16.         typedef struct _LDR_DATA
  17.         {
  18.                 struct _LIST_ENTRY InLoadOrderLinks;
  19.                 struct _LIST_ENTRY InMemoryOrderLinks;
  20.                 struct _LIST_ENTRY InInitializationOrderLinks;
  21.                 VOID*        DllBase;
  22.                 VOID*        EntryPoint;
  23.                 ULONG32      SizeOfImage;
  24.                 UINT8        _PADDING0_[0x4];
  25.                 struct _UNICODE_STRING FullDllName;
  26.                 struct _UNICODE_STRING BaseDllName;
  27.                 ULONG32      Flags;
  28.         }LDR_DATA, *PLDR_DATA;
  29.         PLDR_DATA ldr;
  30.         ldr = (PLDR_DATA)(pDriverObj->DriverSection);
  31.         ldr->Flags |= 0x20;
  32. }
  33. // 判断是否是需要保护的进程
  34. BOOLEAN CheckProcess(PEPROCESS eprocess)
  35. {
  36.         char *Name = PsGetProcessImageFileName(eprocess);
  37.         if (!_stricmp("lyshark.exe", Name))
  38.                 return TRUE;
  39.         else
  40.                 return FALSE;
  41. }
  42. // 进程回调
  43. OB_PREOP_CALLBACK_STATUS MyLySharkProcessObjectCallBack(PVOID RegistrationContext, POB_PRE_OPERATION_INFORMATION pOperationInformation)
  44. {
  45.         HANDLE pid;
  46.         // 只取出进程回调
  47.         if (pOperationInformation->ObjectType != *PsProcessType)
  48.         {
  49.                 return OB_PREOP_SUCCESS;
  50.         }
  51.         // 得到所有进程的ID
  52.         pid = PsGetProcessId((PEPROCESS)pOperationInformation->Object);
  53.         // DbgPrint("进程PID= %ld \n", pid);
  54.         UNREFERENCED_PARAMETER(RegistrationContext);
  55.         // 验证是否是需要的进程
  56.         if (CheckProcess((PEPROCESS)pOperationInformation->Object))
  57.         {
  58.                 // 创建句柄
  59.                 if (pOperationInformation->Operation == OB_OPERATION_HANDLE_CREATE)
  60.                 {
  61.                         DbgPrint("lyshark.exe 进程打开事件 \n");
  62.                         pOperationInformation->Parameters->CreateHandleInformation.DesiredAccess=0;
  63.                         if ((pOperationInformation->Parameters->CreateHandleInformation.OriginalDesiredAccess & PROCESS_TERMINATE) == PROCESS_TERMINATE)
  64.                         {
  65.                                 DbgPrint("[LyShark Message] 拦截进程打开 \n");
  66.                                 pOperationInformation->Parameters->CreateHandleInformation.DesiredAccess &= ~PROCESS_TERMINATE;
  67.                         }
  68.                 }
  69.                 // 复制句柄
  70.                 if (pOperationInformation->Operation == OB_OPERATION_HANDLE_DUPLICATE)
  71.                 {
  72.                         DbgPrint("lyshark.exe 进程被关闭 \n");
  73.                         pOperationInformation->Parameters->DuplicateHandleInformation.DesiredAccess=0;
  74.                         if ((pOperationInformation->Parameters->DuplicateHandleInformation.OriginalDesiredAccess & PROCESS_TERMINATE) == PROCESS_TERMINATE)
  75.                         {
  76.                                 pOperationInformation->Parameters->DuplicateHandleInformation.DesiredAccess &= ~PROCESS_TERMINATE;
  77.                         }
  78.                 }
  79.         }
  80.         return OB_PREOP_SUCCESS;
  81. }
  82. VOID UnDriver(PDRIVER_OBJECT driver)
  83. {
  84.         ObUnRegisterCallbacks(Globle_Object_Handle);
  85.         DbgPrint("回调卸载完成... \n");
  86. }
  87. NTSTATUS DriverEntry(IN PDRIVER_OBJECT Driver, PUNICODE_STRING RegistryPath)
  88. {
  89.         DbgPrint("hello lyshark.com \n");
  90.         BypassCheckSign(Driver);
  91.         OB_OPERATION_REGISTRATION ob_process_callback;
  92.         OB_CALLBACK_REGISTRATION op_process_operation;
  93.         memset(&ob_process_callback, 0, sizeof(ob_process_callback));
  94.         ob_process_callback.ObjectType = PsProcessType;
  95.         ob_process_callback.Operations = OB_OPERATION_HANDLE_CREATE | OB_OPERATION_HANDLE_DUPLICATE;
  96.         ob_process_callback.PreOperation = MyLySharkProcessObjectCallBack;
  97.         ob_process_callback.PostOperation = NULL;
  98.         RtlUnicodeStringInit(&op_process_operation.Altitude, L"600000");
  99.         op_process_operation.RegistrationContext = NULL;
  100.         op_process_operation.Version = OB_FLT_REGISTRATION_VERSION;
  101.         op_process_operation.OperationRegistration = &ob_process_callback;
  102.         op_process_operation.OperationRegistrationCount = 1;
  103.         // 注册进程回调
  104.         if (ObRegisterCallbacks(&op_process_operation, &Globle_Object_Handle))
  105.         {
  106.                 DbgPrint("进程回调注册成功...");
  107.         }
  108.         Driver->DriverUnload = UnDriver;
  109.         return STATUS_SUCCESS;
  110. }
复制代码
加载这个驱动,当有进程被创建时,则首先判断是否是lyshark.exe如果是则直接禁止打开,也就是终止掉。

同理进程可以被拦截,那么如果增加更多的过滤条件,则线程同样可以被拦截,拦截线程代码如下所示。
  1. // 署名权
  2. // right to sign one's name on a piece of work
  3. // PowerBy: LyShark
  4. // Email: me@lyshark.com
  5. #include <ntddk.h>
  6. #include <ntstrsafe.h>
  7. #define THREAD_TERMINATE2 0x1
  8. // 导出两个API
  9. NTKERNELAPI PEPROCESS IoThreadToProcess(PETHREAD Thread);
  10. NTKERNELAPI char* PsGetProcessImageFileName(PEPROCESS Process);
  11. // 全局句柄
  12. PVOID Globle_Object_Handle = NULL;
  13. // 绕过签名检测
  14. void BypassCheckSign(PDRIVER_OBJECT pDriverObj)
  15. {
  16.         typedef struct _LDR_DATA
  17.         {
  18.                 struct _LIST_ENTRY InLoadOrderLinks;
  19.                 struct _LIST_ENTRY InMemoryOrderLinks;
  20.                 struct _LIST_ENTRY InInitializationOrderLinks;
  21.                 VOID*        DllBase;
  22.                 VOID*        EntryPoint;
  23.                 ULONG32      SizeOfImage;
  24.                 UINT8        _PADDING0_[0x4];
  25.                 struct _UNICODE_STRING FullDllName;
  26.                 struct _UNICODE_STRING BaseDllName;
  27.                 ULONG32      Flags;
  28.         }LDR_DATA, *PLDR_DATA;
  29.         PLDR_DATA ldr;
  30.         ldr = (PLDR_DATA)(pDriverObj->DriverSection);
  31.         ldr->Flags |= 0x20;
  32. }
  33. // 判断是否是需要保护的进程
  34. BOOLEAN CheckProcess(PEPROCESS eprocess)
  35. {
  36.         char *Name = PsGetProcessImageFileName(eprocess);
  37.         if (!_stricmp("lyshark.exe", Name))
  38.                 return TRUE;
  39.         else
  40.                 return FALSE;
  41. }
  42. // 线程回调
  43. OB_PREOP_CALLBACK_STATUS MyThreadObjectCallBack(PVOID RegistrationContext, POB_PRE_OPERATION_INFORMATION pOperationInformation)
  44. {
  45.         PEPROCESS ep;
  46.         PETHREAD et;
  47.         HANDLE pid;
  48.         // 线程过滤
  49.         if (pOperationInformation->ObjectType != *PsThreadType)
  50.         {
  51.                 return OB_PREOP_SUCCESS;
  52.         }
  53.         et = (PETHREAD)pOperationInformation->Object;
  54.         ep = IoThreadToProcess(et);
  55.         pid = PsGetProcessId(ep);
  56.         // DbgPrint("线程PID= %ld | TID= %ld \n", pid, PsGetThreadId(et));
  57.         UNREFERENCED_PARAMETER(RegistrationContext);
  58.         if (CheckProcess(ep))
  59.         {
  60.                 if (pOperationInformation->Operation == OB_OPERATION_HANDLE_CREATE)
  61.                 {
  62.                         pOperationInformation->Parameters->CreateHandleInformation.DesiredAccess=0;
  63.                         if ((pOperationInformation->Parameters->CreateHandleInformation.OriginalDesiredAccess & THREAD_TERMINATE2) == THREAD_TERMINATE2)
  64.                         {
  65.                                 DbgPrint("[LyShark] 拦截lyshark.exe进程内 %d 线程创建 \n", PsGetThreadId(et));
  66.                                 pOperationInformation->Parameters->CreateHandleInformation.DesiredAccess &= ~THREAD_TERMINATE2;
  67.                         }
  68.                 }
  69.                 if (pOperationInformation->Operation == OB_OPERATION_HANDLE_DUPLICATE)
  70.                 {
  71.                         pOperationInformation->Parameters->DuplicateHandleInformation.DesiredAccess=0;
  72.                         if ((pOperationInformation->Parameters->DuplicateHandleInformation.OriginalDesiredAccess & THREAD_TERMINATE2) == THREAD_TERMINATE2)
  73.                         {
  74.                                 pOperationInformation->Parameters->DuplicateHandleInformation.DesiredAccess &= ~THREAD_TERMINATE2;
  75.                         }
  76.                 }
  77.         }
  78.         return OB_PREOP_SUCCESS;
  79. }
  80. VOID UnDriver(PDRIVER_OBJECT driver)
  81. {
  82.         ObUnRegisterCallbacks(Globle_Object_Handle);
  83.         DbgPrint("回调卸载完成... \n");
  84. }
  85. NTSTATUS DriverEntry(IN PDRIVER_OBJECT Driver, PUNICODE_STRING RegistryPath)
  86. {
  87.         DbgPrint("hello lyshark.com \n");
  88.         BypassCheckSign(Driver);
  89.         OB_OPERATION_REGISTRATION ob_thread_callback;
  90.         OB_CALLBACK_REGISTRATION op_thread_operation;
  91.         memset(&ob_thread_callback, 0, sizeof(ob_thread_callback));
  92.         ob_thread_callback.ObjectType = PsThreadType;
  93.         ob_thread_callback.Operations = OB_OPERATION_HANDLE_CREATE | OB_OPERATION_HANDLE_DUPLICATE;
  94.         ob_thread_callback.PreOperation = MyThreadObjectCallBack;
  95.         ob_thread_callback.PostOperation = NULL;
  96.         RtlUnicodeStringInit(&op_thread_operation.Altitude, L"600001");
  97.         op_thread_operation.RegistrationContext = NULL;
  98.         op_thread_operation.Version = OB_FLT_REGISTRATION_VERSION;
  99.         op_thread_operation.OperationRegistration = &ob_thread_callback;
  100.         op_thread_operation.OperationRegistrationCount = 1;
  101.         // 注册进程回调
  102.         if (ObRegisterCallbacks(&op_thread_operation, &Globle_Object_Handle))
  103.         {
  104.                 DbgPrint("进程回调注册成功...");
  105.         }
  106.         Driver->DriverUnload = UnDriver;
  107.         return STATUS_SUCCESS;
  108. }
复制代码
这段驱动加载后,如果有新线程被创建,则会被拦截并打印输出,效果图如下。

参考文献

https://www.cnblogs.com/ciyze0101/p/5468175.html

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

吴旭华

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表