HOOK集合----SSDTDPC Hook Anti(X86 win7)

介绍:

    前几天写过一篇SSDT DPC Hook的文章,最近才想起来写一下如何来对抗SSDT DPC Hook,所以有了这篇文章,其实对抗原理也很简单,就是检测出来目标驱动创建的DPC,移除掉,然后进行普通的SSDT Hook 就可以了。

 

(一)

⚪获取目标驱动信息(模块基址和大小)

⚪获取DPC信息 判断目标驱动创建出的DPC

⚪移除DPC、销毁时钟

⚪卸载SSDT Hook

(二)

 

#pragma once
#include<fltKernel.h>
#include"SSDTHook.h"
#include"Common.h"
#include"SystemHelper.h"
#include<ntimage.h>




typedef struct _KTIMER_TABLE_ENTRY32 {
	ULONG Lock;
	LIST_ENTRY32 Entry;
	ULARGE_INTEGER Time;
} KTIMER_TABLE_ENTRY32, *PKTIMER_TABLE_ENTRY32;
typedef struct _KTIMER_TABLE_ENTRY64 {
	ULONG64 Lock;
	LIST_ENTRY64 Entry;
	ULARGE_INTEGER Time;
} KTIMER_TABLE_ENTRY64, *PKTIMER_TABLE_ENTRY64;
#ifdef _WIN64
#define  KTIMER_TABLE_ENTRY KTIMER_TABLE_ENTRY64
#define  PKTIMER_TABLE_ENTRY   PKTIMER_TABLE_ENTRY64
#else
#define  KTIMER_TABLE_ENTRY KTIMER_TABLE_ENTRY32
#define  PKTIMER_TABLE_ENTRY   PKTIMER_TABLE_ENTRY32
#endif // _WIN64

NTSTATUS DPC_SSDTHook_ANTI();
NTSTATUS GetDelayProcedureCallInfo(PKTIMER* KTimer, PVOID TargetModuleBase, ULONG TargetModuleSize);

 

#include"DPC-SSDTHook-ANTI.h"


extern PDRIVER_OBJECT __DriverObject;

NTSTATUS DPC_SSDTHook_ANTI()
{
	/*
	0: kd> dt _DRIVER_OBJECT 0x88bd26d8
nt!_DRIVER_OBJECT
   +0x000 Type             : 0n4
   +0x002 Size             : 0n168
   +0x004 DeviceObject     : 0x889cc118 _DEVICE_OBJECT
   +0x008 Flags            : 0x12
   +0x00c DriverStart      : 0x9d3f2000 Void
   +0x010 DriverSize       : 0x8000
   +0x014 DriverSection    : 0x88014c70 Void
   +0x018 DriverExtension  : 0x88bd2780 _DRIVER_EXTENSION
   +0x01c DriverName       : _UNICODE_STRING "\Driver\HookRing0"
   +0x024 HardwareDatabase : 0x84b8c250 _UNICODE_STRING "\REGISTRY\MACHINE\HARDWARE\DESCRIPTION\SYSTEM"
   +0x028 FastIoDispatch   : (null)
   +0x02c DriverInit       : 0x9d3f8000     long  HookRing0!GsDriverEntry+0
   +0x030 DriverStartIo    : (null)
   +0x034 DriverUnload     : 0x9d3f3740     void  HookRing0!DriverUnload+0
   +0x038 MajorFunction    : [28] 0x9d3f33e0     long  HookRing0!CreateThroughDispatch+0

	*/
	NTSTATUS Status = STATUS_UNSUCCESSFUL;

	PKTIMER KTimer = NULL;
	PVOID  TargetModuleBase = NULL;
	ULONG  TargetModuleSize = 0;
	WCHAR  TargetModuleName[] = L"HookRing0.sys";

	//获取目标驱动信息
	Status = GetKernelModuleInfoByDriverName(__DriverObject, TargetModuleName,
		&TargetModuleBase, &TargetModuleSize);
	if (!NT_SUCCESS(Status))
	{
		return Status;
	}

	//获取DPC信息 判断目标驱动创建出的DPC

	Status = GetDelayProcedureCallInfo(&KTimer, TargetModuleBase, TargetModuleSize);
	if (!NT_SUCCESS(Status))
	{
		return Status;
	}
	//移除DPC
	//销毁时钟
	if (KTimer != 0)
	{
		KeCancelTimer(KTimer);
		KTimer = NULL;
	}
	//卸载SSDT Hook
	Status = SSDTHook(FALSE);
	

	return Status;
}

NTSTATUS GetDelayProcedureCallInfo(PKTIMER * KTimer, PVOID TargetModuleBase, ULONG TargetModuleSize)
{
	NTSTATUS Status = STATUS_UNSUCCESSFUL;
	PVOID KPRCB = NULL;
	ULONG32 CurrentProcessorNumber = 0;
	PROCESSOR_NUMBER ProcessorNumber = { 0 };
	GROUP_AFFINITY Affinity = { 0 };
	GROUP_AFFINITY PreviousAffinity = { 0 };

	ULONG32 i = 0;
	ULONG32 j = 0;
	PKTIMER v2 = NULL;
	PKDPC   KDpc = NULL;
	PUCHAR TimerEntries = NULL;
	PLIST_ENTRY KTimerTableEntry1 = NULL;
	PLIST_ENTRY KTimerTableEntry2 = NULL;
    KIRQL OldIrql = 0;

	//提高IRQL	
	CurrentProcessorNumber = KeQueryActiveProcessorCountEx(ALL_PROCESSOR_GROUPS);

	for (i = 0; i < CurrentProcessorNumber; i++)
	{
		Status = KeGetProcessorNumberFromIndex(i, &ProcessorNumber);
		if (!NT_SUCCESS(Status))
		{
			return Status;
		}

		//切换当前处理器
		Affinity.Group = ProcessorNumber.Group;
		Affinity.Mask = 1ull << ProcessorNumber.Number;
		//切换当前线程到指定的CPU内核中去
		KeSetSystemGroupAffinityThread(&Affinity, &PreviousAffinity);

		__asm
		{
			push eax
			mov eax, fs:[20h]; //得到_KPRCB的地址
			mov KPRCB, eax
				pop eax
		}
		KeRevertToUserGroupAffinityThread(&PreviousAffinity);

		OldIrql = KeRaiseIrqlToDpcLevel();
		TimerEntries = ((PUCHAR)KPRCB + 0x1960 + 0x40);
		/*
		nt!_KPRCB
		 +0x1960 TimerTable       : _KTIMER_TABLE

		 0: kd> dt!_KTIMER_TABLE
nt!_KTIMER_TABLE
   +0x000 TimerExpiry      : [16] Ptr32 _KTIMER
   +0x040 TimerEntries     : [256] _KTIMER_TABLE_ENTRY


		*/
		//因为_KTIMER_TABLE 是一个256个结构的数组

		for (j = 0;j < 0x100;j++)
		{
			KTimerTableEntry1 = KTimerTableEntry2 =(PLIST_ENTRY)(TimerEntries + sizeof(KTIMER_TABLE_ENTRY)*j + sizeof(ULONG_PTR));
			//获取前一个
		
			if (MmIsAddressValid(KTimerTableEntry1) && MmIsAddressValid(KTimerTableEntry2))
			{
				do
				{
					v2 = CONTAINING_RECORD(KTimerTableEntry2, KTIMER, TimerListEntry);

					KDpc = v2->Dpc;
					if (MmIsAddressValid(KDpc) && MmIsAddressValid(v2) && MmIsAddressValid(KDpc->DeferredRoutine))
					{
						//判断该DPC是否有效
						if (((ULONG_PTR)v2 >= (ULONG_PTR)TargetModuleBase) &&
							((ULONG_PTR)v2 <= ((ULONG_PTR)TargetModuleBase + (ULONG_PTR)TargetModuleSize)))
						{
							*KTimer = v2;
							KeLowerIrql(OldIrql);
							return STATUS_SUCCESS;

						}

					}
					KTimerTableEntry2 = KTimerTableEntry2->Blink;

				} while (KTimerTableEntry1 != KTimerTableEntry2);
			
			}
		}
		KeLowerIrql(OldIrql);
	}
	

	return Status;
}

NTSTATUS GetKernelModuleInfoByDriverName(PDRIVER_OBJECT DriverObject, WCHAR* TargetModuleName,
	PVOID* TargetModuleBase, ULONG* TargetModuleSize)
{
	NTSTATUS Status = STATUS_UNSUCCESSFUL;
	ULONG32 ModuleNameLength = 0;
	PLDR_DATA_TABLE_ENTRY LdrDataTableEntry1 = NULL;
	PLDR_DATA_TABLE_ENTRY LdrDataTableEntry2 = NULL;

	if (DriverObject)
	{
		ModuleNameLength = wcslen(TargetModuleName) * sizeof(WCHAR);
		LdrDataTableEntry1 = LdrDataTableEntry2 = (PLDR_DATA_TABLE_ENTRY)DriverObject->DriverSection;

		/*
		1: kd> dt _LDR_DATA_TABLE_ENTRY32  0x87a764b8
HookRing0!_LDR_DATA_TABLE_ENTRY32
   +0x000 InLoadOrderLinks : LIST_ENTRY32
   +0x008 InMemoryOrderLinks : LIST_ENTRY32
   +0x010 InInitializationOrderLinks : LIST_ENTRY32
   +0x018 DllBase          : 0xab074000 Void
   +0x01c EntryPoint       : 0xab07a000 Void
   +0x020 SizeOfImage      : 0x8000
   +0x024 FullDllName      : _STRING32
   +0x02c BaseDllName      : _STRING32
   +0x034 Flags            : 0x49104000
   +0x038 LoadCount        : 1
   +0x03a TlsIndex         : 0x69
   +0x03c HashLinks        : LIST_ENTRY32
   +0x044 TimeDateStamp    : 0x5c0073
1: kd> db 0x87a76514
87a76514  48 00 6f 00 6f 00 6b 00-52 00 69 00 6e 00 67 00  H.o.o.k.R.i.n.g.
87a76524  30 00 2e 00 73 00 79 00-73 00 00 00 10 00 03 00  0...s.y.s.......

		*/
		do
		{
			if (LdrDataTableEntry2->BaseDllName.Buffer &&
				MmIsAddressValid((PVOID)LdrDataTableEntry2->BaseDllName.Buffer) &&
				!_wcsnicmp(TargetModuleName, (WCHAR*)LdrDataTableEntry2->BaseDllName.Buffer, ModuleNameLength / sizeof(WCHAR)))
			{
				*TargetModuleBase = LdrDataTableEntry2->DllBase;
				*TargetModuleSize = LdrDataTableEntry2->SizeOfImage;
				break;
			}
			LdrDataTableEntry2 = LdrDataTableEntry2->InLoadOrderLinks.Flink;

		} while (LdrDataTableEntry2 != LdrDataTableEntry1);

		Status = STATUS_SUCCESS;
	}
	else
	{

	}

	return Status;
}

 

 

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值