驱动断链的研究
准备
source insight
从现在开始我们正式进入内核编程,但是很多内核里面的结构和类型是需要我们额外声明的,我们就需要一个工具来快速的阅读WIn内核源码。这里我贴出我所参考的博客
羽夏看Win系统内核——SourceInsight 配置 WRK - 寂静的羽夏 - 博客园
就怕以后文章挂了,我还是走一遍流程
首先安装好sourceinsight之后,新建项目
WRK
WRK(windows Research Kernel ) 是微软公开的一部分
windows 内核源码,用来供给开发人员学习。
下载地址:http://www.awarenetwork.org/home/iqlord/other/wrk.rar
在上面的步骤后一路ok,直到下面,选择add Tree
然后关掉这个窗口,按f7导入符号表,这就完成了
理论准备
关于断链,我之前已经写过了文章
在R3中有这么一个结构
3: kd> dt _PEB_LDR_DATA
nt!_PEB_LDR_DATA
+0x000 Length : Uint4B
+0x004 Initialized : UChar
+0x008 SsHandle : Ptr64 Void
+0x010 InLoadOrderModuleList : _LIST_ENTRY
+0x020 InMemoryOrderModuleList : _LIST_ENTRY
+0x030 InInitializationOrderModuleList : _LIST_ENTRY
+0x040 EntryInProgress : Ptr64 Void
+0x048 ShutdownInProgress : UChar
+0x050 ShutdownThreadId : Ptr64 Void
我们复习一下,这个结构中的InLoadOrderModuleList,InMemoryOrderModuleList,InInitializationOrderModuleList都指向了一个双向链表,这个链表里面存储了我们模块信息,如果我们给链表里面的节点断链,那么就可以让其他软件在遍历链表的时候找不到我们的模块
现在在R0里面也是同理的,只是结构变成了,在WRK的ntldr.h这个头文件中,且由于没有PNON_PAGED_DEBUG_INFO的定义,所以还要补上一个。
typedef struct _KLDR_DATA_TABLE_ENTRY {
LIST_ENTRY InLoadOrderLinks;
PVOID ExceptionTable;
ULONG ExceptionTableSize;
// ULONG padding on IA64
PVOID GpValue;
PNON_PAGED_DEBUG_INFO NonPagedDebugInfo;
PVOID DllBase;
PVOID EntryPoint;
ULONG SizeOfImage;
UNICODE_STRING FullDllName;
UNICODE_STRING BaseDllName;
ULONG Flags;
USHORT LoadCount;
USHORT __Unused5;
PVOID SectionPointer;
ULONG CheckSum;
// ULONG padding on IA64
PVOID LoadedImports;
PVOID PatchInformation;
} KLDR_DATA_TABLE_ENTRY, *PKLDR_DATA_TABLE_ENTRY;
typedef struct _NON_PAGED_DEBUG_INFO {
USHORT Signature;
USHORT Flags;
ULONG Size;
USHORT Machine;
USHORT Characteristics;
ULONG TimeDateStamp;
ULONG CheckSum;
ULONG SizeOfImage;
ULONGLONG ImageBase;
} NON_PAGED_DEBUG_INFO, *PNON_PAGED_DEBUG_INFO;
可以从上面的结构中看见R0中只保留了一个InLoadOrderLinks,但是思路也是一样的
代码实现
在知道了上面所提到的内核中的两个结构之后,我们首先要看下系统中的这个双向链表长什么样,这里用一个DbgBreakPoint来断下
#include<ntifs.h>
#include<ntstrsafe.h>//要用RtlStringCbPrintfA就别忘了这个库
typedef struct _NON_PAGED_DEBUG_INFO {
USHORT Signature;
USHORT Flags;
ULONG Size;
USHORT Machine;
USHORT Characteristics;
ULONG TimeDateStamp;
ULONG CheckSum;
ULONG SizeOfImage;
ULONGLONG ImageBase;
} NON_PAGED_DEBUG_INFO, *PNON_PAGED_DEBUG_INFO;
typedef struct _KLDR_DATA_TABLE_ENTRY {
LIST_ENTRY InLoadOrderLinks;
PVOID ExceptionTable;
ULONG ExceptionTableSize;
// ULONG padding on IA64
PVOID GpValue;
PNON_PAGED_DEBUG_INFO NonPagedDebugInfo;
PVOID DllBase;
PVOID EntryPoint;
ULONG SizeOfImage;
UNICODE_STRING FullDllName;
UNICODE_STRING BaseDllName;
ULONG Flags;
USHORT LoadCount;
USHORT __Unused5;
PVOID SectionPointer;
ULONG CheckSum;
// ULONG padding on IA64
PVOID LoadedImports;
PVOID PatchInformation;
} KLDR_DATA_TABLE_ENTRY, *PKLDR_DATA_TABLE_ENTRY;
VOID DriverUnload(PDRIVER_OBJECT DriverObject) {
DbgPrint("Driver has benn Unloaded");
}
int count = 0;
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING pReg) {
//DbgBreakPoint();
PKLDR_DATA_TABLE_ENTRY ldr = (PKLDR_DATA_TABLE_ENTRY)pDriver->DriverSection;
DbgBreakPoint();
pDriver->DriverUnload = DriverUnload;
return STATUS_SUCCESS;
}
同时在windbg中指定新的符号路径,并使用.reload /f 命令重载符号表,这样我们的调试就方便多了
如果没有符号表,有些结构我们是没有办法展现出来的
首先来看看我们的pDriver这个结构
0: kd> dt pDriver
Local var @ 0x903289e0 Type _DRIVER_OBJECT*
0x8be44160
+0x000 Type : 0n4
+0x002 Size : 0n168
+0x004 DeviceObject : (null)
+0x008 Flags : 2
+0x00c DriverStart : 0x9709c000 Void
+0x010 DriverSize : 0x6000
+0x014 DriverSection : 0x8898b7b8 Void
+0x018 DriverExtension : 0x8be44208 _DRIVER_EXTENSION
+0x01c DriverName : _UNICODE_STRING "\Driver\MyDriver2"
+0x024 HardwareDatabase : 0x841ab250 _UNICODE_STRING "\REGISTRY\MACHINE\HARDWARE\DESCRIPTION\SYSTEM"
+0x028 FastIoDispatch : (null)
+0x02c DriverInit : 0x970a0000 long MyDriver2!GsDriverEntry+0
+0x030 DriverStartIo : (null)
+0x034 DriverUnload : (null)
+0x038 MajorFunction : [28] 0x83ef4da3 long nt!IopInvalidDeviceRequest+0
着重关注两个值,DriverStart和DriverInit,分别是我们的模块基址和模块入口
之后我们根据之前得到的知识,pDriver中的DriverSection就是我们的_KLDR_DATA_TABLE_ENTRY结构存放的地址,我们在代码中把它转进变量ldr中,dt看一下,这里就可以看见DllBase和EntryPoint和我们的DriverStart和DriverInit相互对应
0: kd> dt ldr
Local var @ 0x903289d4 Type _KLDR_DATA_TABLE_ENTRY*
0x8898b7b8
+0x000 InLoadOrderLinks : _LIST_ENTRY [ 0x83f89850 - 0x889a4e98 ]//Flink和Blink
+0x008 ExceptionTable : 0xffffffff Void
+0x00c ExceptionTableSize : 0xffffffff
+0x010 GpValue : 0x00000005 Void
+0x014 NonPagedDebugInfo : (null)
+0x018 DllBase : 0x9709c000 Void
+0x01c EntryPoint : 0x970a0000 Void
+0x020 SizeOfImage : 0x6000
+0x024 FullDllName : _UNICODE_STRING "\??\C:\Users\su\Desktop\MyDriver2.sys"
+0x02c BaseDllName : _UNICODE_STRING "MyDriver2.sys"
+0x034 Flags : 0x49104000
+0x038 LoadCount : 1
+0x03a __Unused5 : 0
+0x03c SectionPointer : (null)
+0x040 CheckSum : 0xab05
+0x044 LoadedImports : 0x0034f110 Void
+0x048 PatchInformation : (null)
我们看见了第一个InLoadOrderLinks里面的双向链表,所以我们用它给的Flink来访问链表里面的下一个节点,由于我们的MyDriver2是最后一个加载的驱动,所以它的下一个也就是我们的第一个驱动,果不其然,是我们的内核
0: kd> dt PKLDR_DATA_TABLE_ENTRY 0x83f89850
MyDriver2!PKLDR_DATA_TABLE_ENTRY
0x86a4cc98
+0x000 InLoadOrderLinks : _LIST_ENTRY [ 0x86a4cc20 - 0x83f89850 ]
+0x008 ExceptionTable : 0x83eb7544 Void
+0x00c ExceptionTableSize : 0x12
+0x010 GpValue : (null)
+0x014 NonPagedDebugInfo : (null)
+0x018 DllBase : 0x83e3f000 Void
+0x01c EntryPoint : 0x83f5e4d8 Void
+0x020 SizeOfImage : 0x412000
+0x024 FullDllName : _UNICODE_STRING "\SystemRoot\system32\ntkrnlpa.exe"
+0x02c BaseDllName : _UNICODE_STRING "ntoskrnl.exe"
+0x034 Flags : 0x8004000
+0x038 LoadCount : 0x6b
+0x03a __Unused5 : 0
+0x03c SectionPointer : (null)
+0x040 CheckSum : 0x3c88ac
+0x044 LoadedImports : (null)
+0x048 PatchInformation : (null)
所以我们稍微修改一下我们的代码
#include<ntifs.h>
#include<ntstrsafe.h>//要用RtlStringCbPrintfA就别忘了这个库
typedef struct _NON_PAGED_DEBUG_INFO {
USHORT Signature;
USHORT Flags;
ULONG Size;
USHORT Machine;
USHORT Characteristics;
ULONG TimeDateStamp;
ULONG CheckSum;
ULONG SizeOfImage;
ULONGLONG ImageBase;
} NON_PAGED_DEBUG_INFO, *PNON_PAGED_DEBUG_INFO;
typedef struct _KLDR_DATA_TABLE_ENTRY {
LIST_ENTRY InLoadOrderLinks;
PVOID ExceptionTable;
ULONG ExceptionTableSize;
// ULONG padding on IA64
PVOID GpValue;
PNON_PAGED_DEBUG_INFO NonPagedDebugInfo;
PVOID DllBase;
PVOID EntryPoint;
ULONG SizeOfImage;
UNICODE_STRING FullDllName;
UNICODE_STRING BaseDllName;
ULONG Flags;
USHORT LoadCount;
USHORT __Unused5;
PVOID SectionPointer;
ULONG CheckSum;
// ULONG padding on IA64
PVOID LoadedImports;
PVOID PatchInformation;
} KLDR_DATA_TABLE_ENTRY, *PKLDR_DATA_TABLE_ENTRY;
VOID DriverUnload(PDRIVER_OBJECT DriverObject) {
DbgPrint("Driver has benn Unloaded");
}
int count = 0;
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING pReg) {
//DbgBreakPoint();
PKLDR_DATA_TABLE_ENTRY ldr = (PKLDR_DATA_TABLE_ENTRY)pDriver->DriverSection;
DbgBreakPoint();
PKLDR_DATA_TABLE_ENTRY pre = (PKLDR_DATA_TABLE_ENTRY)ldr->InLoadOrderLinks.Flink;
PKLDR_DATA_TABLE_ENTRY next = (PKLDR_DATA_TABLE_ENTRY)pre->InLoadOrderLinks.Flink;
while (next != pre)
{
DbgPrint("[%d] %wZ", count, &next->BaseDllName);
next = (PKLDR_DATA_TABLE_ENTRY)next->InLoadOrderLinks.Flink;
count++;
}
pDriver->DriverUnload = DriverUnload;
return STATUS_SUCCESS;
}
这样重新编译之后,用DbgView可以看见我们确实遍历所有模块
那既然我们已经正确的找到这个双向链表了,剩下的事情就好办多了,使用我们之前驱动篇基础里面介绍过的API来初始化一个Unicode字符串,然后用这个字符串去对比某个目标模块,如果一致,就按照链表断链的方式将其从双向链表中删除,继续修改我们的代码
#include<ntifs.h>
#include<ntstrsafe.h>//要用RtlStringCbPrintfA就别忘了这个库
typedef struct _NON_PAGED_DEBUG_INFO {
USHORT Signature;
USHORT Flags;
ULONG Size;
USHORT Machine;
USHORT Characteristics;
ULONG TimeDateStamp;
ULONG CheckSum;
ULONG SizeOfImage;
ULONGLONG ImageBase;
} NON_PAGED_DEBUG_INFO, *PNON_PAGED_DEBUG_INFO;
typedef struct _KLDR_DATA_TABLE_ENTRY {
LIST_ENTRY InLoadOrderLinks;
PVOID ExceptionTable;
ULONG ExceptionTableSize;
// ULONG padding on IA64
PVOID GpValue;
PNON_PAGED_DEBUG_INFO NonPagedDebugInfo;
PVOID DllBase;
PVOID EntryPoint;
ULONG SizeOfImage;
UNICODE_STRING FullDllName;
UNICODE_STRING BaseDllName;
ULONG Flags;
USHORT LoadCount;
USHORT __Unused5;
PVOID SectionPointer;
ULONG CheckSum;
// ULONG padding on IA64
PVOID LoadedImports;
PVOID PatchInformation;
} KLDR_DATA_TABLE_ENTRY, *PKLDR_DATA_TABLE_ENTRY;
VOID DriverUnload(PDRIVER_OBJECT DriverObject) {
DbgPrint("Driver has benn Unloaded");
}
int count = 0;
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING pReg) {
//DbgBreakPoint();
PKLDR_DATA_TABLE_ENTRY ldr = (PKLDR_DATA_TABLE_ENTRY)pDriver->DriverSection;
DbgBreakPoint();
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 target = { 0 };
RtlInitUnicodeString(&target, L"srv2.sys");
while (next != pre)
{
//gPrint("[%d] %wZ", count, &next->BaseDllName);
if (!RtlCompareUnicodeString(&target, &next->BaseDllName, TRUE)) {
DbgPrint("[db] target has been found,the num is %d\r\n",count);
//RemoveEntryList(&next);
DbgBreakPoint();
RemoveEntryList(&next->InLoadOrderLinks);//这个api和直接操作链表断链是等价的
//PKLDR_DATA_TABLE_ENTRY PreNode = (PKLDR_DATA_TABLE_ENTRY)next->InLoadOrderLinks.Blink;
//PKLDR_DATA_TABLE_ENTRY NextNode = (PKLDR_DATA_TABLE_ENTRY)next->InLoadOrderLinks.Flink;
//PreNode->InLoadOrderLinks.Flink = next->InLoadOrderLinks.Flink;
//NextNode->InLoadOrderLinks.Blink = next->InLoadOrderLinks.Blink;
break;
}
next = (PKLDR_DATA_TABLE_ENTRY)next->InLoadOrderLinks.Flink;
count++;
}
//DbgBreakPoint();
//ldr = (PKLDR_DATA_TABLE_ENTRY)pDriver->DriverSection;
//第二次遍历内核模块,看看有没有真的断链
pre = (PKLDR_DATA_TABLE_ENTRY)ldr->InLoadOrderLinks.Flink;
next = (PKLDR_DATA_TABLE_ENTRY)pre->InLoadOrderLinks.Flink;
DbgPrint("%wZ\r\n", &pre->BaseDllName);
DbgPrint("%wZ\r\n", &next->BaseDllName);
count = 0;
while (next != pre)
{
DbgPrint("[+] %d %wZ", count, &next->BaseDllName);
next = (PKLDR_DATA_TABLE_ENTRY)next->InLoadOrderLinks.Flink;
count++;
}
pDriver->DriverUnload = DriverUnload;
return STATUS_SUCCESS;
}
可以看见我们的模块在149,在DbgView中向下翻,可以看见149已经不是我们的模块了
继续深入的研究
这是真正的断掉了吗?我打开了我的PChunter,这种简单的断链即使已经没有办法被遍历出来,还是没有办法逃过它的检测,换句话说,如果这是一个AV或者那些Anti-Cheat程序,它还是有办法能找到你
这里我们就可以提到刚刚我们所强调的DriverInit和DriverSection,我们不仅要断掉双向链表,还要保证我们的驱动入口不被找到(这里先暂时不考虑我们的后续怎么找到自己的驱动)
ObReferenceObjectByName
介绍一个新的未导出的内核函数,这里函数后面ByName是我们可以通过名字来查询驱动对象,类似的还有句柄等等,只是我们这里已经定义了字符串
NTKERNELAPI
NTSTATUS
ObReferenceObjectByName(
__in PUNICODE_STRING ObjectName,
__in ULONG Attributes,
__in_opt PACCESS_STATE AccessState,
__in_opt ACCESS_MASK DesiredAccess,
__in POBJECT_TYPE ObjectType,
__in KPROCESSOR_MODE AccessMode,
__inout_opt PVOID ParseContext,
__out PVOID *Object
);
它的作用就是帮助我们去获取驱动对象的指针,方便我们进行操作,由于它未导出,我们得先声明一下
我们修改我们的代码
#include<ntifs.h>
#include<ntstrsafe.h>//要用RtlStringCbPrintfA就别忘了这个库
typedef struct _NON_PAGED_DEBUG_INFO {
USHORT Signature;
USHORT Flags;
ULONG Size;
USHORT Machine;
USHORT Characteristics;
ULONG TimeDateStamp;
ULONG CheckSum;
ULONG SizeOfImage;
ULONGLONG ImageBase;
} NON_PAGED_DEBUG_INFO, *PNON_PAGED_DEBUG_INFO;
typedef struct _KLDR_DATA_TABLE_ENTRY {
LIST_ENTRY InLoadOrderLinks;
PVOID ExceptionTable;
ULONG ExceptionTableSize;
// ULONG padding on IA64
PVOID GpValue;
PNON_PAGED_DEBUG_INFO NonPagedDebugInfo;
PVOID DllBase;
PVOID EntryPoint;
ULONG SizeOfImage;
UNICODE_STRING FullDllName;
UNICODE_STRING BaseDllName;
ULONG Flags;
USHORT LoadCount;
USHORT __Unused5;
PVOID SectionPointer;
ULONG CheckSum;
// ULONG padding on IA64
PVOID LoadedImports;
PVOID PatchInformation;
} KLDR_DATA_TABLE_ENTRY, *PKLDR_DATA_TABLE_ENTRY;
NTSTATUS ObReferenceObjectByName(
__in PUNICODE_STRING ObjectName,
__in ULONG Attributes,
__in_opt PACCESS_STATE AccessState,
__in_opt ACCESS_MASK DesiredAccess,
__in POBJECT_TYPE ObjectType,
__in KPROCESSOR_MODE AccessMode,
__inout_opt PVOID ParseContext,
__out PVOID *Object
);
extern POBJECT_TYPE *IoDriverObjectType;
VOID DriverUnload(PDRIVER_OBJECT DriverObject) {
DbgPrint("Driver has benn Unloaded");
}
int count = 0;
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING pReg) {
//DbgBreakPoint();
PKLDR_DATA_TABLE_ENTRY ldr = (PKLDR_DATA_TABLE_ENTRY)pDriver->DriverSection;
//DbgBreakPoint();
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 target = { 0 };
RtlInitUnicodeString(&target, L"srv2.sys");
UNICODE_STRING ObName = { 0 };
RtlInitUnicodeString(&ObName, L"\\FileSystem\\srv2");//这里如果不知道自己的驱动在什么路径可以在windbg中使用!drvobj srv2 1这个命令
while (next != pre)
{
//gPrint("[%d] %wZ", count, &next->BaseDllName);
if (!RtlCompareUnicodeString(&target, &next->BaseDllName, TRUE)) {
PDRIVER_OBJECT TargetDriver = NULL;
NTSTATUS status = ObReferenceObjectByName(&ObName, FILE_ALL_ACCESS, 0, 0, *IoDriverObjectType, KernelMode, NULL, &TargetDriver);
DbgPrint("[db] target has been found,the num is %d\r\n",count);
//RemoveEntryList(&next);
DbgBreakPoint();
if (NT_SUCCESS(status)) {
TargetDriver->DriverSection = NULL;//去除掉我们的驱动入口
TargetDriver->DriverInit = NULL;
RemoveEntryList(&next->InLoadOrderLinks);
}
//PKLDR_DATA_TABLE_ENTRY PreNode = (PKLDR_DATA_TABLE_ENTRY)next->InLoadOrderLinks.Blink;
//PKLDR_DATA_TABLE_ENTRY NextNode = (PKLDR_DATA_TABLE_ENTRY)next->InLoadOrderLinks.Flink;
//PreNode->InLoadOrderLinks.Flink = next->InLoadOrderLinks.Flink;
//NextNode->InLoadOrderLinks.Blink = next->InLoadOrderLinks.Blink;
break;
}
next = (PKLDR_DATA_TABLE_ENTRY)next->InLoadOrderLinks.Flink;
count++;
}
//DbgBreakPoint();
//ldr = (PKLDR_DATA_TABLE_ENTRY)pDriver->DriverSection;
//第二次遍历内核模块
pre = (PKLDR_DATA_TABLE_ENTRY)ldr->InLoadOrderLinks.Flink;
next = (PKLDR_DATA_TABLE_ENTRY)pre->InLoadOrderLinks.Flink;
DbgPrint("%wZ\r\n", &pre->BaseDllName);
DbgPrint("%wZ\r\n", &next->BaseDllName);
count = 0;
while (next != pre)
{
DbgPrint("[+] %d %wZ\r\n", count, &next->BaseDllName);
next = (PKLDR_DATA_TABLE_ENTRY)next->InLoadOrderLinks.Flink;
count++;
}
pDriver->DriverUnload = DriverUnload;
return STATUS_SUCCESS;
}
按照这个运行之后,再打开PCHunter,这下是彻底被藏住了
1: kd> g
Driver has benn Unloaded[db] target has been found,the num is 149//这次我们在149
Break instruction exception - code 80000003 (first chance)
Unable to load image MyDriver2.sys, Win32 error 0n2
MyDriver2+0x10bf:
9d17c0bf cc int 3
我们马上就可以想到,那能不能用这种方法隐藏自己呢?
继续稍微修改我们的代码
#include<ntifs.h>
#include<ntstrsafe.h>//要用RtlStringCbPrintfA就别忘了这个库
typedef struct _NON_PAGED_DEBUG_INFO {
USHORT Signature;
USHORT Flags;
ULONG Size;
USHORT Machine;
USHORT Characteristics;
ULONG TimeDateStamp;
ULONG CheckSum;
ULONG SizeOfImage;
ULONGLONG ImageBase;
} NON_PAGED_DEBUG_INFO, *PNON_PAGED_DEBUG_INFO;
typedef struct _KLDR_DATA_TABLE_ENTRY {
LIST_ENTRY InLoadOrderLinks;
PVOID ExceptionTable;
ULONG ExceptionTableSize;
// ULONG padding on IA64
PVOID GpValue;
PNON_PAGED_DEBUG_INFO NonPagedDebugInfo;
PVOID DllBase;
PVOID EntryPoint;
ULONG SizeOfImage;
UNICODE_STRING FullDllName;
UNICODE_STRING BaseDllName;
ULONG Flags;
USHORT LoadCount;
USHORT __Unused5;
PVOID SectionPointer;
ULONG CheckSum;
// ULONG padding on IA64
PVOID LoadedImports;
PVOID PatchInformation;
} KLDR_DATA_TABLE_ENTRY, *PKLDR_DATA_TABLE_ENTRY;
NTSTATUS ObReferenceObjectByName(
__in PUNICODE_STRING ObjectName,
__in ULONG Attributes,
__in_opt PACCESS_STATE AccessState,
__in_opt ACCESS_MASK DesiredAccess,
__in POBJECT_TYPE ObjectType,
__in KPROCESSOR_MODE AccessMode,
__inout_opt PVOID ParseContext,
__out PVOID *Object
);
extern POBJECT_TYPE *IoDriverObjectType;
VOID DriverUnload(PDRIVER_OBJECT DriverObject) {
DbgPrint("Driver has benn Unloaded");
}
int count = 0;
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING pReg) {
//DbgBreakPoint();
PKLDR_DATA_TABLE_ENTRY ldr = (PKLDR_DATA_TABLE_ENTRY)pDriver->DriverSection;
//DbgBreakPoint();
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 target = { 0 };
RtlInitUnicodeString(&target, L"MyDriver2.sys");
UNICODE_STRING ObName = { 0 };
RtlInitUnicodeString(&ObName, L"\\Driver\\MyDriver2");//这里路径改了
while (next != pre)
{
//gPrint("[%d] %wZ", count, &next->BaseDllName);
if (!RtlCompareUnicodeString(&target, &next->BaseDllName, TRUE)) {
PDRIVER_OBJECT TargetDriver = NULL;
NTSTATUS status = ObReferenceObjectByName(&ObName, FILE_ALL_ACCESS, 0, 0, *IoDriverObjectType, KernelMode, NULL, &TargetDriver);
DbgPrint("[db] target has been found,the num is %d\r\n",count);
//RemoveEntryList(&next);
DbgBreakPoint();
if (NT_SUCCESS(status)) {
TargetDriver->DriverSection = NULL;//去除掉我们的驱动入口
TargetDriver->DriverInit = NULL;
RemoveEntryList(&next->InLoadOrderLinks);
}
//PKLDR_DATA_TABLE_ENTRY PreNode = (PKLDR_DATA_TABLE_ENTRY)next->InLoadOrderLinks.Blink;
//PKLDR_DATA_TABLE_ENTRY NextNode = (PKLDR_DATA_TABLE_ENTRY)next->InLoadOrderLinks.Flink;
//PreNode->InLoadOrderLinks.Flink = next->InLoadOrderLinks.Flink;
//NextNode->InLoadOrderLinks.Blink = next->InLoadOrderLinks.Blink;
DbgPrint("%d", status);
break;
}
next = (PKLDR_DATA_TABLE_ENTRY)next->InLoadOrderLinks.Flink;
count++;
}
//DbgBreakPoint();
//ldr = (PKLDR_DATA_TABLE_ENTRY)pDriver->DriverSection;
//第二次遍历内核模块
pre = (PKLDR_DATA_TABLE_ENTRY)ldr->InLoadOrderLinks.Flink;
next = (PKLDR_DATA_TABLE_ENTRY)pre->InLoadOrderLinks.Flink;
DbgPrint("%wZ\r\n", &pre->BaseDllName);
DbgPrint("%wZ\r\n", &next->BaseDllName);
count = 0;
while (next != pre)
{
DbgPrint("[+] %d %wZ\r\n", count, &next->BaseDllName);
next = (PKLDR_DATA_TABLE_ENTRY)next->InLoadOrderLinks.Flink;
count++;
}
pDriver->DriverUnload = DriverUnload;
return STATUS_SUCCESS;
}
一运行,蓝屏了
*** Fatal System Error: 0x0000007e
(0xC0000005,0x83FE1943,0x9BF03900,0x9BF03360)
Break instruction exception - code 80000003 (first chance)
A fatal system error has occurred.
Debugger entered on first try; Bugcheck callbacks have not been invoked.
A fatal system error has occurred.
For analysis of this file, run !analyze -v
nt!RtlpBreakWithStatusInstruction:
83e99110 cc int 3
这是为什么呢,因为我们在把驱动的入口给抹掉了,但是还是有一些操作要用到这个驱动入口,所以我们不能加载自己的一瞬间就把自己的入口抹掉,还需要一点延时
线程延时
在内核中,我们一般不使用sleep函数,这其中当然也有sleep函数容易被Hook的原因
我们如果要想达成一个类似延时的效果,可以在自己的驱动模块中起一个内核线程,然后延时启动这个线程,延时是为了保证所有之前用过的驱动入口都正确的运行后释放(不知道怎么说,描述不清楚)
我们要新用到两个函数
NTSTATUS PsCreateSystemThread(
[out] PHANDLE ThreadHandle,
[in] ULONG DesiredAccess,
[in, optional] POBJECT_ATTRIBUTES ObjectAttributes,
[in, optional] HANDLE ProcessHandle,
[out, optional] PCLIENT_ID ClientId,
[in] PKSTART_ROUTINE StartRoutine,
[in, optional] PVOID StartContext
);
NTSTATUS KeDelayExecutionThread(
[in] KPROCESSOR_MODE WaitMode,
[in] BOOLEAN Alertable,
[in] PLARGE_INTEGER Interval
);
改进代码如下
#include<ntifs.h>
#include<ntstrsafe.h>//要用RtlStringCbPrintfA就别忘了这个库
typedef struct _NON_PAGED_DEBUG_INFO {
USHORT Signature;
USHORT Flags;
ULONG Size;
USHORT Machine;
USHORT Characteristics;
ULONG TimeDateStamp;
ULONG CheckSum;
ULONG SizeOfImage;
ULONGLONG ImageBase;
} NON_PAGED_DEBUG_INFO, *PNON_PAGED_DEBUG_INFO;
typedef struct _KLDR_DATA_TABLE_ENTRY {
LIST_ENTRY InLoadOrderLinks;
PVOID ExceptionTable;
ULONG ExceptionTableSize;
// ULONG padding on IA64
PVOID GpValue;
PNON_PAGED_DEBUG_INFO NonPagedDebugInfo;
PVOID DllBase;
PVOID EntryPoint;
ULONG SizeOfImage;
UNICODE_STRING FullDllName;
UNICODE_STRING BaseDllName;
ULONG Flags;
USHORT LoadCount;
USHORT __Unused5;
PVOID SectionPointer;
ULONG CheckSum;
// ULONG padding on IA64
PVOID LoadedImports;
PVOID PatchInformation;
} KLDR_DATA_TABLE_ENTRY, *PKLDR_DATA_TABLE_ENTRY;
NTSTATUS ObReferenceObjectByName(
__in PUNICODE_STRING ObjectName,
__in ULONG Attributes,
__in_opt PACCESS_STATE AccessState,
__in_opt ACCESS_MASK DesiredAccess,
__in POBJECT_TYPE ObjectType,
__in KPROCESSOR_MODE AccessMode,
__inout_opt PVOID ParseContext,
__out PVOID *Object
);
extern POBJECT_TYPE *IoDriverObjectType;
void DriverHide(PWCH ObName) {
LARGE_INTEGER in = { 0 };
in.QuadPart = -10000 * 20000;//规定时间
KeDelayExecutionThread(KernelMode, FALSE, &in);//不到时间不启动
UNICODE_STRING ObjName = { 0 };
RtlInitUnicodeString(&ObjName, ObName);
PDRIVER_OBJECT TargetDriver = NULL;
NTSTATUS status = ObReferenceObjectByName(&ObjName, FILE_ALL_ACCESS, 0, 0, *IoDriverObjectType, KernelMode, NULL, &TargetDriver);
if (NT_SUCCESS(status)) {
//DbgBreakPoint();
PKLDR_DATA_TABLE_ENTRY ldr = (PKLDR_DATA_TABLE_ENTRY)TargetDriver->DriverSection;
RemoveEntryList(&ldr->InLoadOrderLinks);
TargetDriver->DriverSection = NULL;//去除掉我们的驱动入口
TargetDriver->DriverInit = NULL;
ObDereferenceObject(TargetDriver);
DbgPrint("Success!!\r\n");
}
return;
}
VOID DriverUnload(PDRIVER_OBJECT DriverObject) {
DbgPrint("Driver has benn Unloaded");
}
int count = 0;
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING pReg) {
HANDLE pThread = NULL;
NTSTATUS status = PsCreateSystemThread(&pThread, THREAD_ALL_ACCESS,NULL, NULL, NULL, DriverHide, L"\\Driver\\MyDriver2");
DbgBreakPoint();
if (NT_SUCCESS(status)) {
NtClose(pThread);
}
pDriver->DriverUnload = DriverUnload;
return STATUS_SUCCESS;
}
最后是成功的将我们的自己的驱动MyDriver2.sys给隐藏了
、
原文地址:https://blog.csdn.net/m0_68259687/article/details/144349758
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!