Win64 驱动内核编程-11.回调监控进线程句柄操作
来源:互联网 发布:知即墨下载 编辑:程序博客网 时间:2024/05/17 23:47
无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.回调监控进线程句柄操作
- Win64 驱动内核编程-12.回调监控进线程创建和退出
- Win64 驱动内核编程-13.回调监控模块加载
- Win64 驱动内核编程-14.回调监控文件
- Win64 驱动内核编程-15.回调监控注册表
- Win64 驱动内核编程-30.枚举与删除线程回调
- Win64 驱动内核编程-4.内核里操作字符串
- Win64 驱动内核编程-5.内核里操作文件
- Win64 驱动内核编程-6.内核里操作注册表
- Win64 驱动内核编程-7.内核里操作进程
- Win64 驱动内核编程-16.WFP网络监控驱动(防火墙)
- Win64 驱动内核编程-31.枚举与删除映像回调
- Win64 驱动内核编程-32.枚举与删除注册表回调
- Win64 驱动内核编程-33.枚举与删除对象回调
- Win64 驱动内核编程-1.环境搭建
- Win64 驱动内核编程-18.SSDT
- Win64 驱动内核编程-19.HOOK-SSDT
- Win64 驱动内核编程-20.UnHook SSDT
- PHP使用CURL详解
- Flutter进阶—质感设计之直接输入
- c/ C
- 后台处理程序
- edb-debugger在Ubuntu环境下的安装
- Win64 驱动内核编程-11.回调监控进线程句柄操作
- 重要地址
- 基于ffmpeg的简单音视频编解码的例子
- Array.prototype.slice.call(arguments,1)
- Android Studio常用的插件
- 升级为奶爸感言
- 哈希查找
- 配置SSH公私钥免密码登陆
- 【dp】最大子段和问题及其拓展