win7-32、驱动模块遍历、驱动模块隐藏

一、DebugView 过滤打印
打印日志前缀,过滤掉不是我们的日志,只会显示我们自己的日志
在这里插入图片描述
二、内核遍历驱动模块

首先需要先了解一下双向循环链表

typedef struct _KLDR_DATA_TABLE_ENTRY
{
	typedef  struct LIST_ENTRY InLoadOrderLinks
	{
		0x00	struct _LIST_ENTRY *Flink;	//相当于_KLDR_DATA_TABLE_ENTRY这个结构体的首地址,是一个指针占用4个字节
		0x04	struct _LIST_ENTRY *Blink;
	} LIST_ENTRY, *PLIST_ENTRY, *RESTRICTED_POINTER PRLIST_ENTRY;
	
	LIST_ENTRY InMemoryOrderLinks;
	LIST_ENTRY InInitializationOrderLinks;
	...
	...
	PVOID PatchInformation;
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
2.
遍历驱动模块
首先我们看一下PDRIVER_OBJECT这个结构体

NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING pReg)
{
}
kd > dt  _DRIVER_OBJECT
ntdll!_DRIVER_OBJECT
+ 0x000 Type             : Int2B
+ 0x002 Size : Int2B
+ 0x004 DeviceObject : Ptr32 _DEVICE_OBJECT
+ 0x008 Flags : Uint4B
+ 0x00c DriverStart : Ptr32 Void
+ 0x010 DriverSize : Uint4B
+ 0x014 DriverSection : Ptr32 Void
+ 0x018 DriverExtension : Ptr32 _DRIVER_EXTENSION
+ 0x01c DriverName : _UNICODE_STRING
+ 0x024 HardwareDatabase : Ptr32 _UNICODE_STRING
+ 0x028 FastIoDispatch : Ptr32 _FAST_IO_DISPATCH
+ 0x02c DriverInit : Ptr32     long			//【DriverEntry】例程的入口点,被【I/O管理器】调用;
+ 0x030 DriverStartIo : Ptr32     void
+ 0x034 DriverUnload : Ptr32     void
+ 0x038 MajorFunction : [28] Ptr32     long

其中DriverSection这个就是指向_LDR_DATA_TABLE_ENTRY这个结构体的指针,这是个驱动内核双向链表,可以通过遍历这个链表获得所有的驱动程序;或者通过断链进行隐藏驱动程序;

    dt _LDR_DATA_TABLE_ENTRY 0x84356850
	ntdll!_LDR_DATA_TABLE_ENTRY
   +0x000 InLoadOrderLinks : _LIST_ENTRY [ 0x86741c20 - 0x84356850 ]	//这个就是指向上一个/下一个驱动程序的结构体指针
   +0x008 InMemoryOrderLinks : _LIST_ENTRY [ 0x84284544 - 0x12 ]
   +0x010 InInitializationOrderLinks : _LIST_ENTRY [ 0x0 - 0x0 ]
   +0x018 DllBase          : 0x8420c000 Void
   +0x01c EntryPoint       : 0x8432b4d8 Void
   +0x020 SizeOfImage      : 0x412000
   +0x024 FullDllName      : _UNICODE_STRING "\SystemRoot\system32\ntkrnlpa.exe"
   +0x02c BaseDllName      : _UNICODE_STRING "ntoskrnl.exe"
   +0x034 Flags            : 0x8004000
   +0x038 LoadCount        : 0x6f
   +0x03a TlsIndex         : 0
   +0x03c HashLinks        : _LIST_ENTRY [ 0x0 - 0x3c88ac ]
   +0x03c SectionPointer   : (null)
   +0x040 CheckSum         : 0x3c88ac
   +0x044 TimeDateStamp    : 0
   +0x044 LoadedImports    : (null)
   +0x048 EntryPointActivationContext : (null)
   +0x04c PatchInformation : (null)
   +0x050 ForwarderLinks   : _LIST_ENTRY [ 0x0 - 0x412000 ]
   +0x058 ServiceTagLinks  : _LIST_ENTRY [ 0x4ce78a09 - 0x74006e ]
   +0x060 StaticLinks      : _LIST_ENTRY [ 0x73006f - 0x72006b ]
   +0x068 ContextInformation : 0x006c006e Void
   +0x06c OriginalBase     : 0x65002e
   +0x070 LoadTime         : _LARGE_INTEGER 0x650078

驱动遍历源代码

#include <ntifs.h>

//内核驱动链表的结构体
typedef struct _KLDR_DATA_TABLE_ENTRY
{
	LIST_ENTRY InLoadOrderLinks;					//驱动链表、双向循环链表
	LIST_ENTRY InMemoryOrderLinks;
	LIST_ENTRY InInitializationOrderLinks;
	PVOID DllBase;									//PE头
	PVOID EntryPoint;								//入口点
	UINT32 SizeOfImage;
	UNICODE_STRING FullDllName;						//驱动路径名字
	UNICODE_STRING BaseDllName;						//驱动名字
	UINT32 Flags;
	UINT16 LoadCount;
	UINT16 TlsIndex;
	LIST_ENTRY HashLinks;
	PVOID SectionPointer;
	UINT32 CheckSum;								//PE文件校验和时间戳
	UINT32 TimeDateStamp;
	PVOID LoadedImports;
	PVOID EntryPointActivationContext;
	PVOID PatchInformation;
} KLDR_DATA_TABLE_ENTRY, *PKLDR_DATA_TABLE_ENTRY;

//驱动卸载函数
VOID DriverUnload(PDRIVER_OBJECT pDriver)
{
    return;
}

//驱动主函数
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING pReg)
{
    //DbgBreakPoint();
	PKLDR_DATA_TABLE_ENTRY ldr = (PKLDR_DATA_TABLE_ENTRY)pDriver->DriverSection;
	PKLDR_DATA_TABLE_ENTRY pre = (PKLDR_DATA_TABLE_ENTRY)ldr->InLoadOrderLinks.Flink;	//用作头链表,用来判断是否遍历到了起始位置
	PKLDR_DATA_TABLE_ENTRY next = (PKLDR_DATA_TABLE_ENTRY)pre->InLoadOrderLinks.Flink;
	
    UINT32 count = 1;
    DbgPrintEx((PCSTR)77, 0, "[db]: 0 driver name = %wZ\n", &pre->FullDllName);
    while (next != pre)
    {
		DbgPrintEx((PCSTR)77, 0, "[db]: %d driver name = %wZ\n", count++, &next->FullDllName);
		next = (PKLDR_DATA_TABLE_ENTRY)next->InLoadOrderLinks.Flink;
    }

    pDriver->DriverUnload = DriverUnload;
    return STATUS_SUCCESS;
}

三、驱动断链

驱动断链源码

通过找到_KLDR_DATA_TABLE_ENTRY这个结构体进行断链,但是无法做到完全隐藏

#include <ntifs.h>

typedef struct _KLDR_DATA_TABLE_ENTRY
{
	LIST_ENTRY InLoadOrderLinks;
	LIST_ENTRY InMemoryOrderLinks;
	LIST_ENTRY InInitializationOrderLinks;
	PVOID DllBase;
	PVOID EntryPoint;
	UINT32 SizeOfImage;
	UNICODE_STRING FullDllName;
	UNICODE_STRING BaseDllName;
	UINT32 Flags;
	UINT16 LoadCount;
	UINT16 TlsIndex;
	LIST_ENTRY HashLinks;
	PVOID SectionPointer;
	UINT32 CheckSum;
	UINT32 TimeDateStamp;
	PVOID LoadedImports;
	PVOID EntryPointActivationContext;
	PVOID PatchInformation;
} KLDR_DATA_TABLE_ENTRY, *PKLDR_DATA_TABLE_ENTRY;


VOID DriverUnload(PDRIVER_OBJECT pDriver)
{

    return;
}

NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING pReg)
{
    DbgBreakPoint();
	//新创建的驱动,增加在链表的末尾
	PKLDR_DATA_TABLE_ENTRY ldr = (PKLDR_DATA_TABLE_ENTRY)pDriver->DriverSection;
	//这个是空的,因为这是链表头
	//Flink指向下一个LIST_ENTRY
	//Blink指向上一个LIST_ENTRY
	//用作头链表,用来判断是否遍历到了起始位置,这个位置没有驱动程序
	PKLDR_DATA_TABLE_ENTRY pre = (PKLDR_DATA_TABLE_ENTRY)ldr->InLoadOrderLinks.Flink;	
	PKLDR_DATA_TABLE_ENTRY next = (PKLDR_DATA_TABLE_ENTRY)pre->InLoadOrderLinks.Flink;

   
	UNICODE_STRING driverName = { 0 };

	//有两个PCHunter32am.sys模块,PCHunter32aq.sys的意思是断链两个驱动模块
	RtlInitUnicodeString(&driverName, L"PCHunter32aq.sys");
	
    UINT32 count = 1;
    DbgPrintEx((PCSTR)77, 0, "[db]: 0 driver name = %wZ\n", &pre->FullDllName);
    while (next != pre)
    {
		DbgPrintEx((PCSTR)77, 0, "[db]: %d driver name = %wZ\n", count++, &next->FullDllName);

		//字符串的长度不是0,并且按照规则比较结果返回有符号数值
		if (next->BaseDllName.Length != 0 && RtlCompareUnicodeString(&driverName, &next->BaseDllName, TRUE) == 0)
		{
			//进行断链接
			//next->InLoadOrderLinks相当于是这个驱动自身的_KLDR_DATA_TABLE_ENTRY
			RemoveEntryList(&next->InLoadOrderLinks);
			break;
		}

		next = (PKLDR_DATA_TABLE_ENTRY)next->InLoadOrderLinks.Flink;
    }

    pDriver->DriverUnload = DriverUnload;
    return STATUS_SUCCESS;
}

我们来看一下RemoveEntryList()这个函数
在这里插入图片描述

四、上面的方法无法做到完全隐藏驱动模块断链,需要另一种方法:找到驱动对象进行断链而不是_KLDR_DATA_TABLE_ENTRY这个结构体

#include <ntifs.h>

typedef struct _KLDR_DATA_TABLE_ENTRY
{
	LIST_ENTRY InLoadOrderLinks;
	LIST_ENTRY InMemoryOrderLinks;
	LIST_ENTRY InInitializationOrderLinks;
	PVOID DllBase;
	PVOID EntryPoint;
	UINT32 SizeOfImage;
	UNICODE_STRING FullDllName;
	UNICODE_STRING BaseDllName;
	UINT32 Flags;
	UINT16 LoadCount;
	UINT16 TlsIndex;
	LIST_ENTRY HashLinks;
	PVOID SectionPointer;
	UINT32 CheckSum;
	UINT32 TimeDateStamp;
	PVOID LoadedImports;
	PVOID EntryPointActivationContext;
	PVOID PatchInformation;
} KLDR_DATA_TABLE_ENTRY, *PKLDR_DATA_TABLE_ENTRY;

//未导出的函数
NTKERNELAPI NTSTATUS ObReferenceObjectByName(
	IN PUNICODE_STRING ObjectName,
	IN ULONG Attributes,
	IN PACCESS_STATE PassedAccessState OPTIONAL,
	IN ACCESS_MASK DesiredAccess OPTIONAL,
	IN POBJECT_TYPE ObjectType,
	IN KPROCESSOR_MODE AccessMode,
	IN OUT PVOID ParseContext OPTIONAL,
	OUT PVOID *Object
	);

extern POBJECT_TYPE *IoDriverObjectType;

void DriverHide(PWCH ObjName)
{
	LARGE_INTEGER in = { 0 };
	//这里的负数表示的是相对时间,正数拒说表示绝对时间,我没试出效果。
	//单位是100nm,此处乘以10000是让单位变为s,很多代码都是乘以10,即传入的单位是ms;
	in.QuadPart = -10000 * 1000;	

	//该函数将当前执行线程置于等待状态,当时间过后被唤醒。
	KeDelayExecutionThread(KernelMode, FALSE, &in);	
	
	UNICODE_STRING driverName1 = { 0 };
	//PCHunter32am.sys模块
	//驱动对象路径
	RtlInitUnicodeString(&driverName1, ObjName);
	
	//通过  L"\\Driver\\DriverA" 找到驱动对象
	PDRIVER_OBJECT httpDriver = NULL;
	NTSTATUS status = ObReferenceObjectByName(
											&driverName1, 
											FILE_ALL_ACCESS, 
											0, 
											0, 
											*IoDriverObjectType, 
											KernelMode, 
											NULL,
											&httpDriver
											);

	if (NT_SUCCESS(status))
	{
		//获取 PKLDR_DATA_TABLE_ENTRY 这个结构体,进行打印
		PKLDR_DATA_TABLE_ENTRY ldr = (PKLDR_DATA_TABLE_ENTRY)httpDriver->DriverSection;
		DbgPrintEx(77, 0, "[db]:  %wZ\n", &ldr->FullDllName);
		
		//进行断链接
		httpDriver->DriverSection = ldr->InLoadOrderLinks.Flink;	//在没有断链之前,给他填充一下;
//指向下一个PKLDR_DATA_TABLE_ENTRY 结构结构体
		//ldr->InLoadOrderLinks 相当于是这个驱动自身的_KLDR_DATA_TABLE_ENTRY
		RemoveEntryList(&ldr->InLoadOrderLinks);
		//【DriverEntry】例程的入口点,被【I/O管理器】调用;进行清零
		httpDriver->DriverInit = NULL;
	
		//关闭驱动对象引用
		ObDereferenceObject(httpDriver);
	}
}

VOID DriverUnload(PDRIVER_OBJECT pDriver)
{
    return;
}

NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING pReg)
{
	HANDLE hThread = NULL;

	//创建系统线程
	//C:\Users\PNDGMCSY\Desktop\PCHunter驱动模块查看\PCHunter32am.sys
	NTSTATUS status = PsCreateSystemThread(
											&hThread, 
											THREAD_ALL_ACCESS, 
											NULL, 
											NULL, 
											NULL, 
											DriverHide, 		//调用的函数
											L"\\driver\\PCHunter32am"	//传递给函数的参数
											);			
										
	if (NT_SUCCESS(status))
	{

		NtClose(hThread);
	}

    pDriver->DriverUnload = DriverUnload;
    return STATUS_SUCCESS;
}
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值