基于SSDT HOOK技术的Ring0级进程保护组件设计与实现

一、背景介绍

进程保护这一思想很早就出现,现在大多数的杀毒软件等安全防护软件均带有对自身进程保护的功能,这是为了防止病毒等恶意程序破坏进程的运行。相对的,很多病毒为了防止被发现或终止,提高自己的运行权限,隐藏自己、保护自己不被终止。 

然而并不是只有病毒及杀毒软件有对自己的进程进行保护的需求,很多软件,如网吧、机房等的监控系统、计费系统等,以及一些必须确保自身运行过程中不被强行中断,否则会导致数据丢失、操作系统崩溃等严重后果的软件系统,都需要对自身进行必要的防护,防止恶意行为或者操作者的误操作引起的损失。  

高权限的进程保护关系到操作系统底层,并不是所有语言都容易开发高权限进程保护功能,尤其是基于代码托管的语言。目前,实现进程保护的软件均将进程保护功能嵌入在软件内,没有专门的组件提供进程保护功能。因此我们想利用C++实现一套专门提供进程隐藏、进程保护的组件,以 DLL(Dynamic Link Lib)的形式呈现给软件开发者,使其通过调用即可实现对进程的高权限保护,而不必在乎其软件本身的开发语言。 

进程保护的实现方式多种多样,当如何做实现高权限(如运行在 Ring0 特权级下) 、灵活性(方便的对单个/多个进程进行守护) 、可移植性等特性成为关键因素。在选择实现技术时,我们选择了 SSDT  Hook 技术作为组件的实现方式。

SSDT 为 Windows 操作系统下的系统服务描述符表,这个表是一个把 Ring3 的Win32 API和Ring0 的内核 API联系起来的角色。我们利用 SSDT的角色特点,设计钩子拦截进程操作相关API调用,实现进程隐藏及进程保护。其中由于SSDT的读取只能在 Ring0 层完成,于是我们使用了内核驱动并借助 DeviceIoControl来完成相应操作。


二、SSDT Hook技术 

2.1 SSDT简介 

SSDT,全称 System Services Descriptor Table,即系统服务描述符表。这个表一个把Ring3 的Win32 API和Ring0的内核 API联系起来的角色。 

例如,我们打开任务管理器(taskmgr.exe),选中一个进程,如 notepad.exe并选择结束进程,这时记事本程序就会关闭。这个过程看似简单,但是其中的流程如下: 

1、taskmgr 进程首先获取要结束的进程句柄,通过 OpenProcess()这个 Ring3下API,OpenProcess 调用在Kernel32.dll 中; 

2、系统捕获API调用,转到Ring0 级下,从 SSDT中取得对应的 Ring0 API:NtOpenProcess 的入口地址,执行相应操作,此过程在 ntdll.dll 中; 

3、完成NtOpenProcess 操作后转回Ring3 级下返回 OpenProcess 函数,继而返回taskmgr进程,因此获取了要结束的进程的句柄; 

4、taskmgr 执行 TerminateProcess()这个 Ring3 下的 API,传入进程句柄,尝试结束进程; 

5、系统捕获API调用,再次转到 Ring0 级下,从SSDT中取得对应的 Ring0 API:NtTerminateProcess 的入口地址,执行结束进程操作;

6、完成 NtTerminateProcess 操作后转回 Ring3 级下返回 Te

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vt hook ssdt是一种技术,用于在操作系统内核中拦截和修改系统服务调用。通过Vt(Virtualization Technology)技术,可以在操作系统运行时对系统服务进行动态修改,从而实现对系统行为的控制和修改。 以下是一个Vt hook ssdt的示例代码: ```c #include <ntddk.h> ULONG_PTR OriginalServiceAddress = 0; NTSTATUS HookServiceCall(IN PUNICODE_STRING ServiceName, IN ULONG_PTR NewServiceAddress) { NTSTATUS status = STATUS_SUCCESS; ULONG_PTR serviceAddress = 0; // 获取系统服务地址 status = ZwQuerySystemInformation(SystemModuleInformation, NULL, 0, &serviceAddress); if (status != STATUS_INFO_LENGTH_MISMATCH) { return status; } // 遍历系统服务表 PSYSTEM_MODULE_INFORMATION pModuleInfo = (PSYSTEM_MODULE_INFORMATION)ExAllocatePoolWithTag(NonPagedPool, serviceAddress, 'hook'); if (pModuleInfo == NULL) { return STATUS_INSUFFICIENT_RESOURCES; } status = ZwQuerySystemInformation(SystemModuleInformation, pModuleInfo, serviceAddress, NULL); if (!NT_SUCCESS(status)) { ExFreePoolWithTag(pModuleInfo, 'hook'); return status; } for (ULONG i = 0; i < pModuleInfo->NumberOfModules; i++) { PRTL_PROCESS_MODULES pModule = &pModuleInfo->Modules[i]; // 找到ntoskrnl.exe模块 if (wcsstr(pModule->FullPathName, L"ntoskrnl.exe") != NULL) { // 计算SSDT地址 ULONG_PTR ssdtAddress = (ULONG_PTR)pModule->ImageBase + pModule->OffsetToFileName; // 保存原始的系统服务地址 OriginalServiceAddress = *(ULONG_PTR*)ssdtAddress; // 修改系统服务地址为新的地址 *(ULONG_PTR*)ssdtAddress = NewServiceAddress; break; } } ExFreePoolWithTag(pModuleInfo, 'hook'); return status; } NTSTATUS UnhookServiceCall() { if (OriginalServiceAddress != 0) { // 恢复原始的系统服务地址 *(ULONG_PTR*)ssdtAddress = OriginalServiceAddress; OriginalServiceAddress = 0; } return STATUS_SUCCESS; } ``` 以上代码是一个简单的Vt hook ssdt的示例,通过调用`HookServiceCall`函数可以将指定的系统服务地址替换为新的地址,通过调用`UnhookServiceCall`函数可以恢复原始的系统服务地址。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值