无HOOK监控进线程句柄操作

在 NT5 平台下,要监控进线程句柄的操作。

通常要挂钩三个API:NtOpenProcess、NtOpenThread、NtDuplicateObject。但是在 VISTA SP1 以及之后的系统中,我们可以完全抛弃 HOOK 方案了,转而使用一个标准的 API:ObRegisterCallbacks。下面做一个监视进线程句柄操作的程序,并实现保护名为 CALC.EXE 的进程不被结束。

首先介绍一下 ObRegisterCallbacks 这个函数。此函数的前缀是Ob,看得出它是属于对象管理器的函数,Register 是注册,Callbacks 是回调(复数)。

因此从字面意思上看,它是注册一个对象回调的意思。现在它只能监控进程对象和线程对象。但微软承诺会给此函数增加功能,实现对其它内核对象的监控。这个函数在不能合法进行内核挂钩的 WIN64 上特别有用,但是微软做了一个很扯淡的限制: 驱动程序必须有数字签名才能使用 此函数。不过国外的黑客对此限制很不爽,他们通过逆向 ObRegisterCallbacks,找到了破解这个限制的方法。经研究,内核通过 MmVerifyCallbackFunction 验证此回调是否合法,但此函数只是简单的验证了一下 DriverObject->DriverSection->Flags 的值是不是为 0x20:所以可以简单破解掉这个限制:

X32typedef struct _LDR_DATA_TABLE_ENTRY32{LIST_ENTRY32 InLoadOrderLinks;LIST_ENTRY32 InMemoryOrderLinks;LIST_ENTRY32 InInitializationOrderLinks;ULONG DllBase;ULONG EntryPoint;ULONG SizeOfImage;UNICODE_STRING32 FullDllName;UNICODE_STRING32 BaseDllName;ULONG Flags;USHORT LoadCount;USHORT TlsIndex;union {LIST_ENTRY32 HashLinks;struct {ULONG SectionPointer;ULONG  CheckSum;};};union {struct {ULONG  TimeDateStamp;};struct {ULONG LoadedImports;};};} LDR_DATA_TABLE_ENTRY32, *PLDR_DATA_TABLE_ENTRY32;PLDR_DATA_TABLE_ENTRY32 ldr;ldr = (PLDR_DATA_TABLE_ENTRY32)(pDriverObj->DriverSection);ldr->Flags |= 0x20;
X64typedef struct _LDR_DATA_TABLE_ENTRY64{LIST_ENTRY64    InLoadOrderLinks;LIST_ENTRY64    InMemoryOrderLinks;LIST_ENTRY64    InInitializationOrderLinks;PVOID            DllBase;PVOID            EntryPoint;ULONG            SizeOfImage;UNICODE_STRING    FullDllName;UNICODE_STRING     BaseDllName;ULONG            Flags;USHORT            LoadCount;USHORT            TlsIndex;PVOID            SectionPointer;ULONG            CheckSum;PVOID            LoadedImports;PVOID            EntryPointActivationContext;PVOID            PatchInformation;LIST_ENTRY64    ForwarderLinks;LIST_ENTRY64    ServiceTagLinks;LIST_ENTRY64    StaticLinks;PVOID            ContextInformation;ULONG64            OriginalBase;LARGE_INTEGER    LoadTime;} LDR_DATA_TABLE_ENTRY64, *PLDR_DATA_TABLE_ENTRY64;PLDR_DATA_TABLE_ENTRY64 ldr;ldr = (PLDR_DATA_TABLE_ENTRY64)(pDriverObj->DriverSection);ldr->Flags |= 0x20;

上面代码如果是用于商业或者其他正当场合,注意要好好测试下,我是在网上找了到了那个结构体定义,然后自己在win7 32和win764位机器上测试了一下,没问题。小伙伴记得好好测试其他系统再用。然后就是来两个回调函数,一个是进程回调,一个是线程回调:

NTKERNELAPI PEPROCESS IoThreadToProcess(PETHREAD Thread);
NTKERNELAPI char* PsGetProcessImageFileName(PEPROCESS Process);BOOLEAN IsProtectedProcessName(PEPROCESS eprocess)
{char *Name=PsGetProcessImageFileName(eprocess);if(!_stricmp("calc.exe",Name))return TRUE;elsereturn FALSE;
}PVOID obHandle=NULL,obHandle2=NULL;OB_PREOP_CALLBACK_STATUS preCall(PVOID RegistrationContext, POB_PRE_OPERATION_INFORMATION pOperationInformation)
{#define PROCESS_TERMINATE 0x1HANDLE pid;if(pOperationInformation->ObjectType!=*PsProcessType)goto exit_sub;pid = PsGetProcessId((PEPROCESS)pOperationInformation->Object);DbgPrint("[OBCALLBACK][Process]PID=%ld\n",pid);UNREFERENCED_PARAMETER(RegistrationContext);if( IsProtectedProcessName((PEPROCESS)pOperationInformation->Object) ){if (pOperationInformation->Operation == OB_OPERATION_HANDLE_CREATE){//pOperationInformation->Parameters->CreateHandleInformation.DesiredAccess=0;if ((pOperationInformation->Parameters->CreateHandleInformation.OriginalDesiredAccess & PROCESS_TERMINATE) == PROCESS_TERMINATE){pOperationInformation->Parameters->CreateHandleInformation.DesiredAccess &= ~PROCESS_TERMINATE;}}if(pOperationInformation->Operation == OB_OPERATION_HANDLE_DUPLICATE){//pOperationInformation->Parameters->DuplicateHandleInformation.DesiredAccess=0;if ((pOperationInformation->Parameters->DuplicateHandleInformation.OriginalDesiredAccess & PROCESS_TERMINATE) == PROCESS_TERMINATE){pOperationInformation->Parameters->DuplicateHandleInformation.DesiredAccess &= ~PROCESS_TERMINATE;}}}
exit_sub:return OB_PREOP_SUCCESS;
}OB_PREOP_CALLBACK_STATUS preCall2(PVOID RegistrationContext, POB_PRE_OPERATION_INFORMATION pOperationInformation)
{#define THREAD_TERMINATE2 0x1PEPROCESS ep;PETHREAD et;HANDLE pid;if(pOperationInformation->ObjectType!=*PsThreadType)goto exit_sub;et=(PETHREAD)pOperationInformation->Object;ep=IoThreadToProcess(et);pid = PsGetProcessId(ep);DbgPrint("[OBCALLBACK][Thread]PID=%ld; TID=%ld\n",pid,PsGetThreadId(et));UNREFERENCED_PARAMETER(RegistrationContext);if( IsProtectedProcessName(ep) ){if (pOperationInformation->Operation == OB_OPERATION_HANDLE_CREATE){//pOperationInformation->Parameters->CreateHandleInformation.DesiredAccess=0;if ((pOperationInformation->Parameters->CreateHandleInformation.OriginalDesiredAccess & THREAD_TERMINATE2) == THREAD_TERMINATE2){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;}}}
exit_sub:return OB_PREOP_SUCCESS;
}然后就是在驱动里注册/卸载这两个回调函数:
NTSTATUS ObProtectProcess(BOOLEAN Enable)
{if(Enable==TRUE){NTSTATUS obst1=0,obst2=0;OB_CALLBACK_REGISTRATION obReg,obReg2;OB_OPERATION_REGISTRATION opReg,opReg2;//reg ob callback 1memset(&obReg, 0, sizeof(obReg));obReg.Version = ObGetFilterVersion();obReg.OperationRegistrationCount = 1;obReg.RegistrationContext = NULL;RtlInitUnicodeString(&obReg.Altitude, L"321124");obReg.OperationRegistration = &opReg;memset(&opReg, 0, sizeof(opReg));opReg.ObjectType = PsProcessType;opReg.Operations = OB_OPERATION_HANDLE_CREATE | OB_OPERATION_HANDLE_DUPLICATE;opReg.PreOperation = (POB_PRE_OPERATION_CALLBACK)&preCall;obst1=ObRegisterCallbacks(&obReg, &obHandle);//reg ob callback 2memset(&obReg2, 0, sizeof(obReg2));obReg2.Version = ObGetFilterVersion();obReg2.OperationRegistrationCount = 1;obReg2.RegistrationContext = NULL;RtlInitUnicodeString(&obReg2.Altitude, L"321125");obReg2.OperationRegistration = &opReg2;memset(&opReg2, 0, sizeof(opReg2));opReg2.ObjectType = PsThreadType;opReg2.Operations = OB_OPERATION_HANDLE_CREATE | OB_OPERATION_HANDLE_DUPLICATE;opReg2.PreOperation = (POB_PRE_OPERATION_CALLBACK)&preCall2;obst1=ObRegisterCallbacks(&obReg2, &obHandle2);return NT_SUCCESS(obst1) & NT_SUCCESS(obst2);}else{if(obHandle!=NULL)ObUnRegisterCallbacks(obHandle);if(obHandle2!=NULL)ObUnRegisterCallbacks(obHandle2);return TRUE;}
}
执行结果:

Win64 驱动内核编程-11.回调监控进线程句柄操作相关推荐

  1. Win64 驱动内核编程-12.回调监控进线程创建和退出

    回调监控进线程创建和退出 两个注册回调的函数:PsSetCreateProcessNotifyRoutine   进程回调PsSetCreateThreadNotifyRoutine    线程回调分 ...

  2. Win64 驱动内核编程-14.回调监控文件

    回调监控文件 使用 ObRegisterCallbacks 实现保护进程,其实稍微 PATCH 下内核,这个函数还能实现文件操作监视.但可惜只能在 WIN7X64 上用.因为在 WIN7X64 上 P ...

  3. Win64 驱动内核编程-15.回调监控注册表

    回调监控注册表 在 WIN32 平台上,监控注册表的手段通常是 SSDT HOOK.不过用 SSDT HOOK 的方式监控注册表实在是太麻烦了,要 HOOK 一大堆函数,还要处理一些 NT6 系统有而 ...

  4. Win64 驱动内核编程-30.枚举与删除线程回调

    枚举与删除线程回调 进程回调可以监视进程的创建和退出,这个在前面的章节已经总结过了.某些游戏保护的驱动喜欢用这个函数来监视有没有黑名单中的程序运行,如果运行则阻止运行或者把游戏退出.而线程回调则通常用 ...

  5. Win64 驱动内核编程-13.回调监控模块加载

    回调监控模块加载 模块加载包括用户层模块(.DLL)和内核模块(.SYS)的加载.传统方法要监控这两者加在必须 HOOK 好几个函数,比如 NtCreateSection 和 NtLoadDriver ...

  6. Win64 驱动内核编程-31.枚举与删除映像回调

    枚举与删除映像回调 映像回调可以拦截 RING3 和 RING0 的映像加载.某些游戏保护会用此来拦截黑名单中的驱动加载,比如 XUETR.WIN64AST 的驱动.同理,在反游戏保护的过程中,也可以 ...

  7. Win64 驱动内核编程-8.内核里的其他常用

    内核里的其他常用 1.遍历链表.内核里有很多数据结构,但它们并不是孤立的,内核使用双向链表把它们像糖 葫芦一样给串了起来.所以遍历双向链表能获得很多重要的内核数据.举个简单的例子,驱 动对象 Driv ...

  8. Win64 驱动内核编程-18.SSDT

    SSDT 学习资料:http://blog.csdn.net/zfdyq0/article/details/26515019 学习资料:WIN64内核编程基础 胡文亮 SSDT(系统服务描述表),刚开 ...

  9. Win64 驱动内核编程-3.内核里使用内存

    内核里使用内存 内存使用,无非就是申请.复制.设置.释放.在 C 语言里,它们对应的函数是:malloc.memcpy.memset.free:在内核编程里,他们分别对应 ExAllocatePool ...

最新文章

  1. 多倍体单体型组装算法研究
  2. 浏览器是怎样工作的(一):基础知识
  3. bzoj1875 边点互换+矩乘
  4. python好找工作吗2017-你为什么不来了解一下Python?
  5. netty 进程挂起_这可能是目前最透彻的Netty原理架构解析
  6. 各种基本的排序算法在Object-C实现
  7. 【数据科学系统学习】机器学习算法 # 西瓜书学习记录 [12] 集成学习实践
  8. 开关电源之EMI设计
  9. 修改spring Boot启动时的默认图案Banner
  10. 基础架构之GitLab
  11. Go语言详解内存对齐
  12. 【斯坦福大学公开课CS224W——图机器学习】二、图机器学习中的传统方法(2)
  13. P3545 [POI2012]HUR-Warehouse Store
  14. 华为mate40营销之我见
  15. 我国主要城市2023年房价数据
  16. 前缀和(一维数组+二维数组+差分)
  17. 使用计算属性实现购物车功能效果(商品数量增减、单选多选计算金额和总价,)
  18. 语义计算_语义多态性如何在量子计算中起作用
  19. selenium的工作原理
  20. 网友:后悔知道太晚了,视频被判定为重复度过高?原来答案是这样

热门文章

  1. 安全警报:Oracle 2018一月号安全补丁修复由来已久安全漏洞
  2. 数据库MYSQL学习系列二
  3. 2016年全球芯片市场或衰退2.13%
  4. 软件测试--测试Demo
  5. javaScript一些函数--Math()
  6. 纯正价格正则表达式,请指正
  7. 编写更好的CSS代码
  8. 都大二下学期了,说说读大学的感受吧
  9. centos 安装VSFTP
  10. 心得体悟帖---16、哪些看起来很难做的事情真的不过如此