在线教育网站html模板/百度推广投诉电话
准备
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隐藏导入表_loader函数导入表隐藏-CSDN博客
在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 IA64PVOID 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 IA64PVOID 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 IA64PVOID 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 IA64PVOID 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 IA64PVOID 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 IA64PVOID 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 IA64PVOID 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 IA64PVOID 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 IA64PVOID 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 IA64PVOID 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 IA64PVOID 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 IA64PVOID 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 IA64PVOID 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 IA64PVOID 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给隐藏了
、
相关文章:

驱动断链的研究
准备 source insight 从现在开始我们正式进入内核编程,但是很多内核里面的结构和类型是需要我们额外声明的,我们就需要一个工具来快速的阅读WIn内核源码。这里我贴出我所参考的博客 羽夏看Win系统内核——SourceInsight 配置 WRK - 寂静的羽夏 - 博客…...

在 Windows WSL 上部署 Ollama 和大语言模型:从镜像冗余问题看 Docker 最佳实践20241208
🛠️ 在 Windows WSL 上部署 Ollama 和大语言模型:从镜像冗余问题看 Docker 最佳实践 ⭐ 引言 随着大语言模型(LLM)和人工智能技术的迅猛发展,开发者们越来越多地尝试在本地环境中部署模型进行实验。 但部署过程中常…...

做题时HashSet、TreeSet、LinkedHashSet的选择
一、HashSet 此类实现 Set 接口,由哈希表(实际上是一个 HashMap 实例)支持。它不保证 set 的迭代顺序;特别是它不保证该顺序恒久不变。 代码: import java.util.HashSet; import java.util.LinkedHashSet; import ja…...

Manus手套动作捕捉AI训练灵巧手
随着人工智能(AI)和机器人技术的融合日益紧密,使用真实动作数据AI扩容训练机器人的方式正在被用于开发更富表现力的机器人。Manus手套凭借精准的动作捕捉技术和导出数据的强大兼容性,在灵巧手的研发和应用中发挥了重要作用。 手部…...

嵌入式驱动开发详解4(内核定时器)
文章目录 前言通用定时器系统节拍节拍数与时间转换基本框架定时器使用代码展示通用定时器特点 高精度定时器 前言 LInux内核定时器是一种基于未来时间点的计时方式,以当前时刻来启动的时间点,以未来的某一时刻为终止点。比如,现在是10点5分&…...

Linux:信号的预备和产生
引入: 比如当前快递小哥需要通知你下来取快递(产生信号),然后通过电话或短信告知了你(发送信号),但是当前你正在打游戏,所以你并不会马上去处理,但是你会记得这件事&…...

国城杯2024——Curve
相关知识链接:https://tangcuxiaojikuai.xyz/post/187210a7.html #sagemath from Crypto.Util.number import *def add(P, Q):(x1, y1) P(x2, y2) Qx3 (x1*y2 y1*x2) * inverse(1 d*x1*x2*y1*y2, p) % py3 (y1*y2 - a*x1*x2) * inverse(1 - d*x1*x2*y1*y2, p…...

AI生成不了复杂前端页面?也许有解决方案了
在2024年,编程成为了人工智能领域最热门的赛道。AI编程技术正以惊人的速度进步,但在生成前端页面方面,AI的能力还是饱受质疑。自从ScriptEcho平台上线以来,我们收到了不少用户的反馈,他们表示:“生成的页面…...

常见矩阵分析法(BCG、GE、IE、SPACE、TOWS、优先、战略优先级、安索夫、风险矩阵):如何通过系统化方法助力战略决策与数据驱动决策
在快速变化的商业环境中,企业决策者面临着诸多复杂的选择与挑战。矩阵分析法作为战略分析的重要工具,能够系统化地分析企业的内外部环境,帮助管理层做出更加科学、合理的决策。本文将全面解析常见的矩阵分析法,并探讨它们在数据驱…...

JWT 在 SaaS 系统中的作用与分布式 SaaS 系统设计的最佳实践
在现代 SaaS(软件即服务) 系统中,随着服务规模的扩大和用户需求的多样化,如何高效、安全地进行用户身份验证、权限控制以及租户隔离,成为了系统架构中的核心问题之一。**JWT(JSON Web Token)**作…...

基于C#和Sql Server的网上书店管理系统
基于C#和Sql Server的网上书店管理系统 摘要 本系统是建立在 Windows 平台上,基于 B/S 结构的一个网上书店。通过这个网上书店,可以实 现简单的电子商务功能。 整个网站风格一致,较为美观,有完善的导航机制。普通用户从前台首页…...

特高频局放装置在现代配电设施中的应用
引言 随着电力系统的快速发展,尤其是现代配电系统的不断升和智能化,配电网的安全、稳定和运行变得愈发重要。为了确保电力系统能够及时应对各种运行问题,并提高故障诊断和监控的能力,现代配电系统中的监测技术也不断得到创新与提…...

FSC认证是什么?FSC认证费用
FSC认证是指森林管理委员会(Forest Stewardship Council)颁发的一种认证,以下是对FSC认证的详细介绍: 一、FSC认证的定义与目的 FSC认证标志着一件产品来自经过环境友好、社会有益和经济可行的可持续管理的森林。FSC是一个独立的…...

JAVA数据结构
1.数组 (Array): 固定大小的容器,用于存储相同类型的元素,数组在内存中是连续存储的,支持通过索引快 速访问元素。 int[] numbers = new int[10]; numbers[0] = 1;2.Java Collections Framework (JCF) JCF提供了一组接口和类用于管理和操作集合(如列表,集合,…...

mysql8 主从复制一直失败
问题描述: 开启同步后从服务器一直失败,报错如下: Last_SQL_Error: Coordinator stopped because there were error(s) in the worker(s). The most recent failure being: Worker 1 failed executing transaction ANONYMOUS at source log …...

EDA - Spring Boot构建基于事件驱动的消息系统
文章目录 概述事件驱动架构的基本概念工程结构Code创建事件和事件处理器创建事件总线创建消息通道和发送逻辑创建事件处理器消息持久化创建消息发送事件配置 Spring Boot 启动类测试运行项目 概述 在微服务架构和大规模分布式系统中,事件驱动架构(EDA&a…...

使用vue-seamless-scroll实现echarts图表大屏滚动,出现空白间隔的解决方案
一、背景介绍 最近的业务开发需求,想要实现echarts图表大屏滚动,小编首先采用vue-seamless-scroll进行实现,结果发现第二屏出现空白间隔,尝试了多种解决方案均不生效,最终选择换一个方案。 二、封装的ScrollList组件…...

ios使用UIScrollView和PageControl创建图片轮播
1.创建cocoa touch class 2.同时创建xib页面 3.SceneDelegate设置根视图控制器 // // SceneDelegate.m // iosstudy2024 // // Created by figo on 2024/8/5. //#import "SceneDelegate.h" #import "WidgetViewController.h"interface SceneDelegate …...

3D 生成重建024-LGM第一个开源的3D生成大模型!
3D 生成重建024-LGM第一个开源的3D生成大模型 文章目录 0 论文工作1 论文方法2 实验效果 0 论文工作 这篇论文介绍了一种名为LGM(大型多视角高斯模型)的新方法,用于从单视角图像或文本提示生成高分辨率的三维内容。该方法的核心思想是双重的…...

linux目录权限
一、目录权限的基本概念 Linux中的每个文件和目录都有与之关联的权限,这些权限决定了谁可以读取、写入或执行它们。权限分为三组: 所有者(Owner)权限:目录所有者的权限群组(Group)权限&#x…...

语言模型使用心得
使用像文心一言这样的语言模型,在撰写文章时确实能提供极大的帮助。然而,重要的是我们要明确主次关系:自己的创意和内容应当是文章的核心,而语言模型则扮演着一个辅助角色,帮助我们梳理思路,使文章条理更加…...

ChatGPT客户端安装教程(附下载链接)
用惯了各类AI的我们发现每天打开网页还挺不习惯和麻烦,突然发现客户端上架了,懂摸鱼的人都知道这里面的道行有多深,话不多说,开整! 以下是ChatGPT客户端的详细安装教程,适用于Windows和Mac系统:…...

Electron 基础+传值+引用+安全
文章目录 概要elctron 生命周期及窗口应用主进程与渲染进程交互技术细节electron 中需要注意的安全问题 概要 一、Electron简介 Electron是一个开源框架,它允许开发者使用JavaScript、HTML和CSS构建跨平台的桌面应用程序。它基于Chromium(谷歌浏览器的…...

手机租赁系统全面解析与开发指南
内容概要 手机租赁系统已经成为现代商业中不可或缺的一部分,尤其是在智能手机普及的时代。随着消费者对新机型兴趣的不断增加,大家纷纷走上了“试一试再买”的道路,手机租赁这条路因此越走越宽。这部分的市场需求让创业者们看到了机会。不仅…...

mongoDb的读session和写session权限报错问题
go在使用mongoDb时用到了全局会话,发现在创建的session的逻辑相同,首先会进行数据的查询,此时获取了全局session执行读操作,查询所有文档,则当前会话为读会话,当再去插入时发现会报错,此时sessi…...

Centos在2024年6月30日停止维护后如何换yum源安装组件
现象: 在centos7里使用yum安装报错: Loading mirror speeds from cached hostfile Could not retrieve mirrorlist http://mirrorlist.centos.org/?release7&archx86_64&repoos&infrastock error was 14: curl#6 - “Could not resolve…...

阿里云ACP云计算模拟试题(附答案解析)
1、将基础设施作为服务的云计算服务类型是_____服务。 A.laas B.Paas C.SaaS D.Daas 答案:A 解析:基础设施即服务有时缩写为 IaaS,包含云 IT 的基本构建块,通常提供对联网功能、计算机(虚拟或专用硬件&#x…...

简单的爬虫脚本编写
一、数据来源分析 想爬取一个网站的数据,我们首先要进行数据分析。通过浏览器F12开发者工具栏进行抓包,可以分析我们想要的数据来源。 通过关键字搜索,可以找到相对应的数据包 二、爬虫实现 需要用到的模块为:request…...

[MySQL基础](三)SQL--图形化界面+DML
本专栏内容为:MySQL学习专栏 💓博主csdn个人主页:小小unicorn ⏩专栏分类:MySql 🚚代码仓库:小小unicorn的代码仓库🚚 🌹🌹🌹关注我带你学习编程知识 目录 图…...

11.23[大数据]
PRO1:LSTM模型预测输出都是同一个值? 画出来的图像就是一条横线 这个搜了搜,原因可能有很多,但感觉最主要的原因极可能是激活函数选择不当,以及层的搭建不合适 原模型是 REF https://zhuanlan.zhihu.com/p/654325094 https:/…...