教你在64位Win7系统下使用ObRegisterCallbacks内核函数来实现进程保护

原文链接:https://bbs.pediy.com/thread-168023.htm

我平时工作很忙,也很少有空闲时间上看雪论坛。我在看雪论坛里面文章发表的很少,几只有几篇,我也很少回答别人的问题。我的很多朋友都这样问我问题:我整理了一下,无非就以下几种问题:

(1)怎么样在64位的Windows7操作系统下实现进程保护? 
(2)我在网络上搜索了很多天,我根本就找不到64位进程保护的文章啊!
(3)公司的项目很急,领导让我实现64位系统下的进程保护,这要怎么做啊?
(4)为什么网络上给的文章都是32位的啊?
(5)为什么64位的Windows系统不能Hook SSDT啊?

  本文是在Windows 7的64位操作系统下来实现进程保护。 这里只给出核心代码的实现方式,用来保护Calc.exe(计算器)程序,不能够被任务管理器来结束。

  很多时候,网络上的进程保护例子都是针对Windows 的32位操作系统的, 基本上也都是告诉你如何Hook SSDT。 进程保护的实现,快而有效的方法基本上都是去Hook ZwTerminateProcess或者ZwOpenProcess等。 而这些技术都被人用烂了。你知道的,在百度或Google上随便一搜索Hook SSDT这样的关键字,就会出来非常多的文章告诉你怎样做。

  我这里要告诉大家的是: 如何在 64位的Windows系统上保护进程,使得进程不被Windows自带的任务管理器给结束掉。

  我们知道,在64位的Windows7系统下,驱动程序要有数字证书必须要签名, 并且驱动程序不能够去Hoook SSDT、GDT等等 ,因为这会引发BSOD, 其根本原因就是PatchGuard组件在保护着64位操作系统的内核。

  首先,我们一起来看一看WDK文档里面对ObRegisterCallbacks()的主要描述:

The ObRegisterCallbacks routine registers a list of callback routines for thread and process handle operations.

NTSTATUS 
  ObRegisterCallbacks(
    IN POB_CALLBACK_REGISTRATION  CallBackRegistration,
    OUT PVOID  *RegistrationHandle
    );

CallBackRegistration 
A pointer to an OB_CALLBACK_REGISTRATION structure that specifies the list of callback routines and other registration information. 

RegistrationHandle 
A pointer to a variable that receives a value that identifies the set of registered callback routines. The caller passes this value to the ObUnRegisterCallbacks routine to unregister the set of callbacks. 

我们可以看见,有一个对应的ObUnRegisterCallbacks函数,以及其他的说明。

其实保护进程,也就是修改结构体POB_PRE_OPERATION_INFORMATION里面对应的成员值了。

在代码中一般都是:

PVOID obHandle;//定义一个void*类型的变量,它将会作为ObRegisterCallbacks函数的第2个参数。 

NTSTATUS ProtectProcess(BOOLEAN Enable)
{
        
  OB_CALLBACK_REGISTRATION obReg;
  OB_OPERATION_REGISTRATION opReg;

  memset(&obReg, 0, sizeof(obReg));
  obReg.Version = ObGetFilterVersion();
  obReg.OperationRegistrationCount = 1;
  obReg.RegistrationContext = NULL;
  RtlInitUnicodeString(&obReg.Altitude, L"321000");

  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; //在这里注册一个回调函数指针

obReg.OperationRegistration = &opReg; //注意这一条语句

return ObRegisterCallbacks(&obReg, &obHandle); //在这里注册回调函数
}

现在好了,到这里为止,我们已经用上了ObRegisterCallbacks函数了。事情有了一个好的开始,接着马上就要讲实现了。 在这里,我希望你再次打开WDK帮助文档,当然还是有关ObRegisterCallbacks函数的帮助。
我们首先注意上面代码的一条语句:
opReg.PreOperation = (POB_PRE_OPERATION_CALLBACK)&preCall; //在这里注册一个回调函数指针

我们在WDK帮助文档里面找到有关结构体OB_OPERATION_REGISTRATION的说明。我们在这个结构体里面找到 PreOperation结构体成员变量的帮助说明:

PreOperation 
A pointer to an ObjectPreCallback routine. The system calls this routine before the requested operation occurs. 

我们不需要使用另外一个 成员变量--PostOperation 
PostOperation 
A pointer to an ObjectPostCallback routine. The system calls this routine after the requested operation occurs.

PostOperation成员不是我们关心的,我们不去讨论它。

好了,这下,你找到了 PreOperation的用法说明了。我们知道了PreOperation是一个函数指针,我们的进程保护程序就在这个函数指针里面进行。
我们再回过头来看上面的程序代码,ProtectProcess函数的实现。 我们刚才就注意到了opReg.PreOperation = (POB_PRE_OPERATION_CALLBACK)&preCall;
现在,我们来实现 preCall函数,代码如下:

OB_PREOP_CALLBACK_STATUS 
preCall(PVOID RegistrationContext, POB_PRE_OPERATION_INFORMATION pOperationInformation)
{
   HANDLE pid = PsGetProcessId((PEPROCESS)pOperationInformation->Object);
char szProcName[16]={0};
   UNREFERENCED_PARAMETER(RegistrationContext);
   strcpy(szProcName,GetProcessNameByProcessId(pid));
   if( !_stricmp(szProcName,"calc.exe") )
    {
        if (pOperationInformation->Operation == OB_OPERATION_HANDLE_CREATE)
        {
            if ((pOperationInformation->Parameters->CreateHandleInformation.OriginalDesiredAccess & PROCESS_TERMINATE) == PROCESS_TERMINATE)
            {
                pOperationInformation->Parameters->CreateHandleInformation.DesiredAccess &= ~PROCESS_TERMINATE;
            }
            if ((pOperationInformation->Parameters->CreateHandleInformation.OriginalDesiredAccess & PROCESS_VM_OPERATION) == PROCESS_VM_OPERATION)
            {
                pOperationInformation->Parameters->CreateHandleInformation.DesiredAccess &= ~PROCESS_VM_OPERATION;
            }
            if ((pOperationInformation->Parameters->CreateHandleInformation.OriginalDesiredAccess & PROCESS_VM_READ) == PROCESS_VM_READ)
            {
                pOperationInformation->Parameters->CreateHandleInformation.DesiredAccess &= ~PROCESS_VM_READ;
            }
            if ((pOperationInformation->Parameters->CreateHandleInformation.OriginalDesiredAccess & PROCESS_VM_WRITE) == PROCESS_VM_WRITE)
            {
                pOperationInformation->Parameters->CreateHandleInformation.DesiredAccess &= ~PROCESS_VM_WRITE;
            }
        }
    }
   return OB_PREOP_SUCCESS;
}

还有,在驱动卸载的时候,要调用ObUnRegisterCallbacks函数。像这样:
VOID 
Unload(IN PDRIVER_OBJECT DriverObject)
{
  UNREFERENCED_PARAMETER(DriverObject);
  DbgPrint("driver unloading...\n");

  ObUnRegisterCallbacks(obHandle); //obHandle是上面定义的 PVOID obHandle;
}

代码就这样吗? 是的,这样就可以实现进程保护了。

另外,还需要注意绕过MmVerifyCallbackFunction函数。

在Windows Vista 及之后版本的 Windows 操作系统在驱动程序加载完成后,驱动中调用的一些系统回调函数(如 ObRegisterCallbacks,可用来监控系统中对进线程句柄的操作,如打开进程、复制线程句柄等)等 API 中会通过 MmVerifyCallbackFunction 函数对该驱动程序进行完整性检查,检测未通过则会返回 0xC0000022 拒绝访问的返回值。

你只要在百度或Google上,搜索关键字-----绕过MmVerifyCallbackFunction。这会出来很多的文章供你参考。



  NTSTATUS status = STATUS_SUCCESS;
  PLDR_DATA ldr;

  // 绕过MmVerifyCallbackFunction。
  ldr = (PLDR_DATA)DriverObject->DriverSection;
  ldr->Flags |= 0x20;
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下内容假设你是以管理员权限运行WIN7. ——>>没有UAC提示,没有“以管理员身份运行”提示,或其他类似的提示…<<—— 如何使用: 解压存档的内容到任意位置...按顺序执行: 文件名称 说明: ---------------------------------------------------------------------------------------------- 1.cmd (批处理文件,为你创建一个新的BCD项) 2.exe (字节补丁,使用dUP2...修改复制NTOSKRNL和WINLOAD) 3.cmd (批处理文件,修改后的文件会拷贝到\Windows\System32) checksum.exe (这可以解决PE校验,所以在启动时不会收到0xC0000221的错误。) ---------------------------------------------------------------------------------------------- 按顺序运行1,2,3即可。然后可以安全地删除这些文件。不需要运行checksum.exe,它已经在3.cmd中运行。 重新启动计算机,选择“PatchGuard Disabled v2”启动项来启动系统... 这将允许加载未签名的X64位驱动,挂钩NTOSKRNL,进程隐藏,等 如果有任何建议,或者问题?通过论坛与我联系! 如何卸载: ---------------------------------------------------------------------------------------------- 以管理员权限打开CMD.EXE并输入: bcdedit /delete {46595952-454E-4F50-4747-554944FEEEEE} 然后在\Windows\System32\下删除:ntkrnlmp.exe 和 osload.exe ---------------------------------------------------------------------------------------------- 若不想禁用 WIN7 X64内核保护/驱动签名,开机时选择“Windows 7”启动项即可。 永远记住这一点:这个补丁是为逆向工程和64位内核模式的探索。 这不是为最终用户…如果你不理解“是什么”或“为什么”——请不要使用它。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值