7.HOOK NtTerminateProcess驱动保护进程

30 篇文章 4 订阅
17 篇文章 2 订阅

1、项目说明

将系统服务表中某个函数改成自己的函数,使任务管理器右键无法关闭自己,只有点击自己的关闭按钮才可以正常关闭。

2、获取目标进程的进程名

kd> dt _Eprocess
ntdll!_EPROCESS
   +0x000 Pcb              : _KPROCESS
   +0x06c ProcessLock      : _EX_PUSH_LOCK
   +0x070 CreateTime       : _LARGE_INTEGER
   +0x078 ExitTime         : _LARGE_INTEGER
   +0x080 RundownProtect   : _EX_RUNDOWN_REF
   +0x084 UniqueProcessId  : Ptr32 Void
   +0x088 ActiveProcessLinks : _LIST_ENTRY
   +0x090 QuotaUsage       : [3] Uint4B
   +0x09c QuotaPeak        : [3] Uint4B
   +0x0a8 CommitCharge     : Uint4B
   +0x0ac PeakVirtualSize  : Uint4B
   +0x0b0 VirtualSize      : Uint4B
   +0x0b4 SessionProcessLinks : _LIST_ENTRY
   +0x0bc DebugPort        : Ptr32 Void
   +0x0c0 ExceptionPort    : Ptr32 Void
   +0x0c4 ObjectTable      : Ptr32 _HANDLE_TABLE
   +0x0c8 Token            : _EX_FAST_REF
   +0x0cc WorkingSetLock   : _FAST_MUTEX
   +0x0ec WorkingSetPage   : Uint4B
   +0x0f0 AddressCreationLock : _FAST_MUTEX
   +0x110 HyperSpaceLock   : Uint4B
   +0x114 ForkInProgress   : Ptr32 _ETHREAD
   +0x118 HardwareTrigger  : Uint4B
   +0x11c VadRoot          : Ptr32 Void
   +0x120 VadHint          : Ptr32 Void
   +0x124 CloneRoot        : Ptr32 Void
   +0x128 NumberOfPrivatePages : Uint4B
   +0x12c NumberOfLockedPages : Uint4B
   +0x130 Win32Process     : Ptr32 Void
   +0x134 Job              : Ptr32 _EJOB
   +0x138 SectionObject    : Ptr32 Void
   +0x13c SectionBaseAddress : Ptr32 Void
   +0x140 QuotaBlock       : Ptr32 _EPROCESS_QUOTA_BLOCK
   +0x144 WorkingSetWatch  : Ptr32 _PAGEFAULT_HISTORY
   +0x148 Win32WindowStation : Ptr32 Void
   +0x14c InheritedFromUniqueProcessId : Ptr32 Void
   +0x150 LdtInformation   : Ptr32 Void
   +0x154 VadFreeHint      : Ptr32 Void
   +0x158 VdmObjects       : Ptr32 Void
   +0x15c DeviceMap        : Ptr32 Void
   +0x160 PhysicalVadList  : _LIST_ENTRY
   +0x168 PageDirectoryPte : _HARDWARE_PTE_X86
   +0x168 Filler           : Uint8B
   +0x170 Session          : Ptr32 Void
   											+0x174 ImageFileName    : [16] UChar
   +0x184 JobLinks         : _LIST_ENTRY
   +0x18c LockedPagesList  : Ptr32 Void
   +0x190 ThreadListHead   : _LIST_ENTRY
   +0x198 SecurityPort     : Ptr32 Void
   +0x19c PaeTop           : Ptr32 Void
   +0x1a0 ActiveThreads    : Uint4B
   +0x1a4 GrantedAccess    : Uint4B
   +0x1a8 DefaultHardErrorProcessing : Uint4B
   +0x1ac LastThreadExitStatus : Int4B
   +0x1b0 Peb              : Ptr32 _PEB
   +0x1b4 PrefetchTrace    : _EX_FAST_REF
   +0x1b8 ReadOperationCount : _LARGE_INTEGER
   +0x1c0 WriteOperationCount : _LARGE_INTEGER
   +0x1c8 OtherOperationCount : _LARGE_INTEGER
   +0x1d0 ReadTransferCount : _LARGE_INTEGER
   +0x1d8 WriteTransferCount : _LARGE_INTEGER
   +0x1e0 OtherTransferCount : _LARGE_INTEGER
   +0x1e8 CommitChargeLimit : Uint4B
   +0x1ec CommitChargePeak : Uint4B
   +0x1f0 AweInfo          : Ptr32 Void
   +0x1f4 SeAuditProcessCreationInfo : _SE_AUDIT_PROCESS_CREATION_INFO
   +0x1f8 Vm               : _MMSUPPORT
   +0x238 LastFaultCount   : Uint4B
   +0x23c ModifiedPageCount : Uint4B
   +0x240 NumberOfVads     : Uint4B
   +0x244 JobStatus        : Uint4B
   +0x248 Flags            : Uint4B
   +0x248 CreateReported   : Pos 0, 1 Bit
   +0x248 NoDebugInherit   : Pos 1, 1 Bit
   +0x248 ProcessExiting   : Pos 2, 1 Bit
   +0x248 ProcessDelete    : Pos 3, 1 Bit
   +0x248 Wow64SplitPages  : Pos 4, 1 Bit
   +0x248 VmDeleted        : Pos 5, 1 Bit
   +0x248 OutswapEnabled   : Pos 6, 1 Bit
   +0x248 Outswapped       : Pos 7, 1 Bit
   +0x248 ForkFailed       : Pos 8, 1 Bit
   +0x248 HasPhysicalVad   : Pos 9, 1 Bit
   +0x248 AddressSpaceInitialized : Pos 10, 2 Bits
   +0x248 SetTimerResolution : Pos 12, 1 Bit
   +0x248 BreakOnTermination : Pos 13, 1 Bit
   +0x248 SessionCreationUnderway : Pos 14, 1 Bit
   +0x248 WriteWatch       : Pos 15, 1 Bit
   +0x248 ProcessInSession : Pos 16, 1 Bit
   +0x248 OverrideAddressSpace : Pos 17, 1 Bit
   +0x248 HasAddressSpace  : Pos 18, 1 Bit
   +0x248 LaunchPrefetched : Pos 19, 1 Bit
   +0x248 InjectInpageErrors : Pos 20, 1 Bit
   +0x248 VmTopDown        : Pos 21, 1 Bit
   +0x248 Unused3          : Pos 22, 1 Bit
   +0x248 Unused4          : Pos 23, 1 Bit
   +0x248 VdmAllowed       : Pos 24, 1 Bit
   +0x248 Unused           : Pos 25, 5 Bits
   +0x248 Unused1          : Pos 30, 1 Bit
   +0x248 Unused2          : Pos 31, 1 Bit
   +0x24c ExitStatus       : Int4B
   +0x250 NextPageColor    : Uint2B
   +0x252 SubSystemMinorVersion : UChar
   +0x253 SubSystemMajorVersion : UChar
   +0x252 SubSystemVersion : Uint2B
   +0x254 PriorityClass    : UChar
   +0x255 WorkingSetAcquiredUnsafe : UChar
   +0x258 Cookie           : Uint4B

EPROCESS结构体在0x174处存储了当前进程名称(不是指针),最多只能存储16个字节

那么如何获取EPROCESS结构体呢?
可以通过ObReferenceObjectByHandle函数

NTSTATUS 
  ObReferenceObjectByHandle(
    IN HANDLE  			Handle,
    IN ACCESS_MASK 		DesiredAccess,
    IN POBJECT_TYPE  	ObjectType  OPTIONAL,
    IN KPROCESSOR_MODE  AccessMode,
    OUT PVOID  			*Object,		//可以返回一个EPROCESS指针
    OUT POBJECT_HANDLE_INFORMATION  HandleInformation  OPTIONAL
    );

3、判断是如何关闭的

在这里插入图片描述
在这里插入图片描述
通过找规律可以发现:
若是点X关闭,则ProcessHandle == 0xFFFFFFFF
若任务管理器关闭,则ExitStatus == 1

4、实现代码

知道以上几点就可以顺利写代码了,跟上节课代码差不多,稍微改一改就行了!模板代码

#include <Ntifs.h>


//0x7A NTOpenProcess
//0x101 NtTerminateProcess
#define FuctionID 0x101	//调用号

void PageProtectOn()
{
	//恢复内存保护
	__asm
	{
		mov eax,cr0
			or eax,10000h
			mov cr0,eax
			sti
	}
}

void PageProtectOff()
{
	//去掉内存保护
	__asm
	{
		cli
			mov eax,cr0
			and eax,not 10000h
			mov cr0,eax		
	}
}

//1、找到系统服务表:函数地址表
typedef struct _KSYSTEM_SERVICE_TABLE
{
	PULONG ServiceTableBase;			//函数地址表基地址
	PULONG ServiceCounterTableBase; //被访问了多少次
	ULONG  NumberOfService;			//表中服务函数的总数
	PUCHAR ParamTableBase;			//服务函数的参数个数数组的起始地址
}KSYSTEM_SERVICE_TABLE,*PKSYSTEM_SERVICE_TABLE;

typedef struct _KSERVICE_DESCRIPTOR_TABLE
{
	KSYSTEM_SERVICE_TABLE ntoskrnl;//ntoskrnl.exe的函数
	KSYSTEM_SERVICE_TABLE win32k;//win32k.sys的函数
	KSYSTEM_SERVICE_TABLE notUsed1;//
	KSYSTEM_SERVICE_TABLE notUsed2;//
}KSERVICE_DESCRIPTOR_TABLE,*PKSERVICE_DESCRIPTOR_TABLE;

//NtTerminateProcess函数指针
typedef NTSTATUS (*NTTERMINATEPROCESS) (HANDLE ProcessHandle, NTSTATUS ExitStatus);


//KeServiceDescriptorTable时ntoskrnl.exe所导出的全局变量 申明一下就可以直接用了
extern PKSERVICE_DESCRIPTOR_TABLE KeServiceDescriptorTable; 
//存储原来的函数地址
ULONG uOldNtTerminateProcess;

//2.准备用于替换的函数
NTSTATUS MyNtTerminateProcess(HANDLE ProcessHandle, NTSTATUS ExitStatus)
{
	//自己的业务..各种过滤 或者修改返回结果
	PEPROCESS pEprocess;
	NTSTATUS status;
	PCHAR ImageFileName;
	

	//通过句柄获取EPROCESS
	status = ObReferenceObjectByHandle(ProcessHandle,FILE_ANY_ACCESS,*PsProcessType,KernelMode,&pEprocess,NULL);
	if (!NT_SUCCESS(status))
	{
		return status;
	}
	//获取进程名字 _EPROCESS + 0x171  == ImageFileName
	ImageFileName = (PCHAR)pEprocess + 0x174;
	//判断是否是要保护的进程
	if (strcmp(ImageFileName, "notepad.exe") == 0)
	{
		//判断如何退出
		if (ProcessHandle == (HANDLE)0xFFFFFFFF)
		{
			//点X关闭
			DbgPrint("点X关闭 成功退出:%s: NtTerminateProcess(%x, %x)\n", ImageFileName, ProcessHandle, ExitStatus);
			return ((NTTERMINATEPROCESS)uOldNtTerminateProcess)(ProcessHandle, ExitStatus);
		}
		else if(ExitStatus == 1)
		{
			// 通过任务管理器关闭
			DbgPrint("通过任务管理器关闭 拒绝关闭:%s: NtTerminateProcess(%x, %x)\n", ImageFileName, ProcessHandle, ExitStatus);
			return STATUS_ACCESS_DENIED;
		}
		else
		{
			return STATUS_ACCESS_DENIED;
		}
	}

	return ((NTTERMINATEPROCESS)uOldNtTerminateProcess)(ProcessHandle, ExitStatus);
}
//3.修改函数地址
NTSTATUS HookNtTerminateProcess()
{
	NTSTATUS Status;
	Status = STATUS_SUCCESS;
	PageProtectOff();
	uOldNtTerminateProcess = KeServiceDescriptorTable->ntoskrnl.ServiceTableBase[FuctionID];
	KeServiceDescriptorTable->ntoskrnl.ServiceTableBase[FuctionID] = (ULONG)MyNtTerminateProcess;
	PageProtectOn();
	return Status;
}
//4.恢复
VOID UnHookNtTerminateProcess()
{
	PageProtectOff();
	KeServiceDescriptorTable->ntoskrnl.ServiceTableBase[FuctionID] = (ULONG)uOldNtTerminateProcess;
	PageProtectOn();
}
//卸载函数
VOID DriverUnload(PDRIVER_OBJECT driver)
{
	UnHookNtTerminateProcess();
	KdPrint(("驱动程序停止运行了.\r\n"));
}

//入口函数,相当于main
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING reg_path)
{
	HookNtTerminateProcess();

	//注册销毁回调函数
	pDriver->DriverUnload = DriverUnload;
	return STATUS_SUCCESS;
}

效果如下:
在这里插入图片描述
在这里插入图片描述

5、说明

若点×关闭的你依旧return STATUS_ACCESS_DENIED,会导致 记事本界面虽然已经消失,但是进程还并未结束,会一直在后台运行,除非你停止运行驱动!
一旦你多打开几个记事本然后点×关闭,操作系统将会非常卡,CPU使用率飙升,最后死机!
如图所示:
在这里插入图片描述

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
### 回答1: 在 Python 中,keyboard.hook() 函数用于在按下或释放指定按键时执行回调函数。该函数需要传入一个回调函数作为参数,回调函数将在按键事件发生时被调用。例如,如果要在按下键盘上的 "a" 键时执行某个函数 foo(),可以这样调用:keyboard.hook(foo, 'a')。 在这里,'abc' 作为参数传递给 keyboard.hook() 函数,表示要捕捉键盘上的 'abc' 按键事件,并执行相应的回调函数。具体的回调函数实现需要根据具体的需求来编写。 ### 回答2: keyboard.hook(abc)是一个键盘钩子函数,用于在程序运行中监视键盘输入事件,并对其作出相应的处理。 所谓键盘钩子,是一段程序代码,用于截获并处理键盘输入事件。在这里,keyboard.hook()是一个函数,它接受一个参数abc,表示注册一个钩子来监视键盘输入事件abc。 键盘输入事件也可以称为键盘按键事件,即当用户在键盘上按下或释放某个按键时,就会触发相应的事件。通过使用keyboard.hook()函数,我们可以在程序运行过程中截获这些事件,并对它们进行处理。 通过注册一个abc的钩子,我们可以定义一个回调函数,当用户按下或释放键盘上的指定按键abc时,这个回调函数就会被调用。在回调函数中,我们可以自定义处理逻辑,比如记录按键信息、执行特定操作、触发其他事件等等。 总之,keyboard.hook(abc)用于在程序运行中截获特定按键事件,并在这些事件发生时执行相应的处理逻辑。这是一个非常常用的技术,可以广泛应用于各种需要响应键盘输入的程序中,比如游戏、输入检测、热键设置等等。 ### 回答3: keyboard.hook(abc)是一个函数调用,意思是将abc作为参数传递给keyboard.hook函数。 keyboard.hook函数是一个键盘钩子函数,可以用来监视键盘事件。当有键盘事件发生时,该函数将被触发并执行相应的操作。 参数abc是一个键盘事件处理函数,用来处理具体的键盘事件。可以自定义abc函数来实现不同的键盘操作。当键盘事件发生时,abc函数将被调用并执行相应的代码逻辑。 通过调用keyboard.hook函数并传递abc参数,可以实现对键盘事件的监视和处理。具体的实现方式和逻辑需要根据具体的需求和业务场景来设计。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值