枚举和隐藏内核模块

在 WIN64 上枚举内核模块有两种方法:使用 ZwQuerySystemInformation 的第 11 号功能(SystemModuleInformation)和枚举 KLDR_DATA_TABLE_ENTRY 中的 InLoadOrderLinks 双向链表;
隐藏内核模块的通用方法是把指定的驱动对象从 KLDR_DATA_TABLE_ENTRY中的 InLoadOrderLinks 双向链表上摘除。

#include <ntddk.h>
#include <ntimage.h>

// dt _LDR_DATA_TABLE_ENTRY 
typedef struct _KLDR_DATA_TABLE_ENTRY
{
	LIST_ENTRY InLoadOrderLinks;//这个成员把系统所有加载(可能是停止没被卸载)已经读取到内存中 我们关心第一个  我们要遍历链表 双链表 不管中间哪个节点都可以遍历整个链表 本驱动的驱动对象就是一个节点
	LIST_ENTRY InMemoryOrderLinks;//系统已经启动 没有被初始化 没有调用DriverEntry这个历程的时候 通过这个链表进程串接起来
	LIST_ENTRY InInitializationOrderLinks;//已经调用DriverEntry这个函数的所有驱动程序
	PVOID DllBase;
	PVOID EntryPoint;//驱动的进入点 DriverEntry
	ULONG SizeOfImage;
	UNICODE_STRING FullDllName;//驱动的满路径
	UNICODE_STRING BaseDllName;//不带路径的驱动名字
	ULONG Flags;
	USHORT LoadCount;
	USHORT TlsIndex;
	union {
		LIST_ENTRY HashLinks;
		struct {
			PVOID SectionPointer;
			ULONG CheckSum;
		};
	};
	union {
		struct {
			ULONG TimeDateStamp;
		};
		struct {
			PVOID LoadedImports;
		};
	};
} KLDR_DATA_TABLE_ENTRY, *PKLDR_DATA_TABLE_ENTRY;
//系统所有程序 驱动对象里都有这个结构 是驱动对象的成员qudongduixiang1->DriverSection(PVOID DriverSection) 这个结构体在什么时候有的 io管理器在加载我们驱动的时候 
//调用DriverEntry这个历程的时候 把我们驱动对象也加入到系统的一个全局链表中 
//就是为了方便io管理器进行维护或者方便对象管理器进行维护 为了查找方便 这个全局链表呢 把系统所有驱动程序串起来就是连接起来

VOID EnumDriver(PDRIVER_OBJECT pDriverObject)
{
	PKLDR_DATA_TABLE_ENTRY entry = (PKLDR_DATA_TABLE_ENTRY)pDriverObject->DriverSection;
	PKLDR_DATA_TABLE_ENTRY firstEntry;
	ULONG64 pDrvBase = 0;
	KIRQL OldIrql;
	firstEntry = entry;
	while ((PKLDR_DATA_TABLE_ENTRY)entry->InLoadOrderLinks.Flink != firstEntry)
	{
		DbgPrint("BASE=%p\tPATH=%wZ", entry->DllBase, entry->FullDllName);
		entry = (PKLDR_DATA_TABLE_ENTRY)entry->InLoadOrderLinks.Flink;
	}
}

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////
//隐藏驱动

NTSYSAPI NTSTATUS NTAPI ZwQuerySystemInformation
(
	IN ULONG	SystemInformationClass,
	OUT PVOID	SystemInformation,
	IN ULONG	Length,
	OUT PULONG	ReturnLength
);

typedef struct _SYSTEM_MODULE_INFORMATION_ENTRY
{
	ULONG Unknow1;
	ULONG Unknow2;
	ULONG Unknow3;
	ULONG Unknow4;
	PVOID Base;
	ULONG Size;
	ULONG Flags;
	USHORT Index;
	USHORT NameLength;
	USHORT LoadCount;
	USHORT ModuleNameOffset;
	char ImageName[256];
} SYSTEM_MODULE_INFORMATION_ENTRY, *PSYSTEM_MODULE_INFORMATION_ENTRY;

typedef struct _SYSTEM_MODULE_INFORMATION
{
	ULONG Count;//内核中以加载的模块的个数
	SYSTEM_MODULE_INFORMATION_ENTRY Module[1];
} SYSTEM_MODULE_INFORMATION, *PSYSTEM_MODULE_INFORMATION;

typedef struct _KLDR_DATA_TABLE_ENTRY_64
{
	LIST_ENTRY64 InLoadOrderLinks;
	ULONG64 __Undefined1;
	ULONG64 __Undefined2;
	ULONG64 __Undefined3;
	ULONG64 NonPagedDebugInfo;
	ULONG64 DllBase;
	ULONG64 EntryPoint;
	ULONG SizeOfImage;
	UNICODE_STRING FullDllName;
	UNICODE_STRING BaseDllName;
	ULONG   Flags;
	USHORT  LoadCount;
	USHORT  __Undefined5;
	ULONG64 __Undefined6;
	ULONG   CheckSum;
	ULONG   __padding1;
	ULONG   TimeDateStamp;
	ULONG   __padding2;
}KLDR_DATA_TABLE_ENTRY_64, *PKLDR_DATA_TABLE_ENTRY_64;


ULONG64 GetSystemModuleBase(char* lpModuleName)
{
	ULONG NeedSize, i, ModuleCount, BufferSize = 0x5000;
	PVOID pBuffer = NULL;
	PCHAR pDrvName = NULL;
	NTSTATUS Result;
	PSYSTEM_MODULE_INFORMATION pSystemModuleInformation;
	do
	{
		//分配内存
		pBuffer = kmalloc(BufferSize);
		if (pBuffer == NULL)
			return 0;
		//查询模块信息  SystemModuleInformation
		Result = ZwQuerySystemInformation(11, pBuffer, BufferSize, &NeedSize);
		if (Result == STATUS_INFO_LENGTH_MISMATCH)
		{
			kfree(pBuffer);
			BufferSize *= 2;
		}
		else if (!NT_SUCCESS(Result))
		{
			//查询失败则退出
			kfree(pBuffer);
			return 0;
		}
	} while (Result == STATUS_INFO_LENGTH_MISMATCH);
	pSystemModuleInformation = (PSYSTEM_MODULE_INFORMATION)pBuffer;
	//获得模块的总数量
	ModuleCount = pSystemModuleInformation->Count;
	//遍历所有的模块
	for (i = 0; i < ModuleCount; i++)
	{
		if ((ULONG64)(pSystemModuleInformation->Module[i].Base) >(ULONG64)0x8000000000000000)
		{
			pDrvName = pSystemModuleInformation->Module[i].ImageName + pSystemModuleInformation->Module[i].ModuleNameOffset;
			if (_stricmp(pDrvName, lpModuleName) == 0)
				return (ULONG64)pSystemModuleInformation->Module[i].Base;
		}
	}
	kfree(pBuffer);
	return 0;
}

//抹去pe头,参数:驱动对象
BOOL HideDriverFromPeHeader(PDRIVER_OBJECT pDriverObject)
{
	PMDL pHeaderMdl;
	PIMAGE_DOS_HEADER ImageDosHeader;
	PIMAGE_NT_HEADERS ImageNtHeaders;
	BYTE *ImageBaseShadow;
	ULONG ImageBase;
	DWORD dwLdrDataTableEntry = 0;
	BOOL bRetOK = FALSE;

	//判断当前的irql是否高于PASSIVE_LEVEL
	if (KeGetCurrentIrql() > PASSIVE_LEVEL)
	{
		return bRetOK;
	}
	//就是驱动的起始地址
	ImageBase = (ULONG)pDriverObject->DriverStart;
	__try
	{
		//判断是否是有效的pe文件内存
		ImageDosHeader = (PIMAGE_DOS_HEADER)ImageBase;
		if (ImageDosHeader->e_magic != IMAGE_DOS_SIGNATURE)
		{
			return bRetOK;
		}
		DbgPrint("ImageDosHeader  %x", (DWORD)ImageDosHeader);
		ImageNtHeaders = (PIMAGE_NT_HEADERS)(ImageBase + ImageDosHeader->e_lfanew);
		if (ImageNtHeaders->Signature != IMAGE_NT_SIGNATURE)
		{
			return bRetOK;
		}
		//到这里就得到了pe的nt结构体
		DbgPrint("ImageNtHeaders  %x", (DWORD)ImageNtHeaders);

		//利用MDL的方式来修改这个PE
		//创建映射
		pHeaderMdl = IoAllocateMdl((PVOID)ImageBase, ImageNtHeaders->OptionalHeader.SizeOfHeaders, FALSE, FALSE, NULL);
		if (pHeaderMdl)
		{
			//锁住KernelMode,IoWriteAccess
			MmProbeAndLockPages(pHeaderMdl, KernelMode, IoWriteAccess);  //锁住,避免被page out,直接会导致MmGetSystemAddressForMdl蓝屏  - -。
			MmMapLockedPagesSpecifyCache(pHeaderMdl, KernelMode, MmWriteCombined, NULL, FALSE, NormalPagePriority);

			//到这里呢,我们就得到了一个安全的可以操作的映射地址
			//我们对这个映射地址的操作,就相当于对xuetr的驱动基址进行操作一样
			//MDL的方式在SSDT那几节课已经说明
			ImageBaseShadow = MmGetSystemAddressForMdlSafe(pHeaderMdl, NormalPagePriority);
			if (ImageBaseShadow)
			{
				//得到pe头
				ImageDosHeader = (PIMAGE_DOS_HEADER)ImageBaseShadow;
				ImageNtHeaders = (PIMAGE_NT_HEADERS)(ImageBaseShadow + ImageDosHeader->e_lfanew);

				//整个PE头清零
				*(PUSHORT)ImageDosHeader = 0x00;
				*(PULONG)ImageNtHeaders = 0x00;

				//抹掉DriverObject结构的中的信息
				DbgPrint("pDriverObject:%08x\r\n", pDriverObject);

				*(PUSHORT)pDriverObject = 0;

				DbgPrint("Size:%d\r\n", pDriverObject->Size);

				//0x168,抹去,清零
				pDriverObject->Size = 0x0;
				pDriverObject->DriverStart = 0x0;
				pDriverObject->DriverSize = 0x0;
				bRetOK = TRUE;
			}
			//解除映射
			MmUnmapLockedPages(ImageBaseShadow, pHeaderMdl);
			MmUnlockPages(pHeaderMdl);
			IoFreeMdl(pHeaderMdl);
		}
	}
	__except (EXCEPTION_EXECUTE_HANDLER)
	{
		DbgPrint("PeHeader Error \r\n");
	}
	return bRetOK;
}


// 隐藏驱动
VOID HideDriver(PDRIVER_OBJECT pDriverObject)
{
	PKLDR_DATA_TABLE_ENTRY_64 entry = (PKLDR_DATA_TABLE_ENTRY_64)pDriverObject->DriverSection;
	PKLDR_DATA_TABLE_ENTRY_64 firstentry;
	ULONG64 pDrvBase = 0;
	KIRQL OldIrql;
	firstentry = entry;
	pDrvBase = GetSystemModuleBase("win32k.sys");
	while ((PKLDR_DATA_TABLE_ENTRY_64)entry->InLoadOrderLinks.Flink != firstentry)
	{
		if (entry->DllBase == pDrvBase)
		{
			//typedef struct LIST_ENTRY64 {
			//	ULONGLONG Flink;
			//	ULONGLONG Blink;
			//} LIST_ENTRY64;
			//typedef LIST_ENTRY64 *PLIST_ENTRY64;
			//le->Flink->Blink=le->Blink;
			//le->Blink->Flink=le->Flink;
			OldIrql = KeRaiseIrqlToDpcLevel();
			((LIST_ENTRY64*)(entry->InLoadOrderLinks.Flink))->Blink = entry->InLoadOrderLinks.Blink;
			((LIST_ENTRY64*)(entry->InLoadOrderLinks.Blink))->Flink = entry->InLoadOrderLinks.Flink;
			entry->InLoadOrderLinks.Flink = 0;
			entry->InLoadOrderLinks.Blink = 0;
			KeLowerIrql(OldIrql);
			DbgPrint("Remove LIST_ENTRY64 OK!");
			break;
		}
		//kprintf("%llx\t%wZ\t%wZ",entry->DllBase,entry->BaseDllName,entry->FullDllName);
		entry = (PKLDR_DATA_TABLE_ENTRY_64)entry->InLoadOrderLinks.Flink;
	}

	// 抹掉PE的文件信息
	if (HideDriverFromPeHeader(pDriverObject))
	{
		DbgPrint("HideDriverFromPeHeader failed!");
	}
	else
	{
		DbgPrint("HideDriverFromPeHeader success!");
	}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值