内核测试模式过DSE签名
微软在x64系统中推出了DSE保护机制,DSE全称(Driver Signature Enforcement),该保护机制的核心就是任何驱动程序或者是第三方驱动如果想要在正常模式下被加载则必须要经过微软的认证,当驱动程序被加载到内存时会验证签名的正确性,如果签名不正常则系统会拒绝运行驱动,这种机制也被称为驱动强制签名,该机制的作用是保护系统免受恶意软件的破坏,是提高系统安全性的一种手段。
在Windows操作系统中,为了保护系统安全性,有一个叫做驱动程序签名验证的机制,它的作用是验证驱动程序是否来自受信任的发行者(也就是签名)。验证失败的驱动程序不能加载到系统中,这个机制加强了对操作系统的保护和对恶意软件的防范。
在驱动程序开发中,如果没有有效的签名,将会遇到签名验证的问题。为了规避这些问题,开发者可能会尝试在调试模式下修改 KLDR_DATA_TABLE_ENTRY 结构体中的 Flags 标志。
KLDR_DATA_TABLE_ENTRY 结构体是内核中用于表示加载的驱动程序的数据结构之一。其中的 Flags 标志用于指示加载过程中的各种属性,包括签名验证。它定义在 ntddk.h 头文件中,具体的结构如下:
typedef struct _KLDR_DATA_TABLE_ENTRY {
LIST_ENTRY InLoadOrderLinks;
PVOID ExceptionTable;
ULONG ExceptionTableSize;
PVOID GpValue;
PVOID NonPagedDebugInfo;
PVOID ImageBase;
PVOID EntryPoint;
ULONG SizeOfImage;
UNICODE_STRING FullDllName;
UNICODE_STRING BaseDllName;
ULONG Flags;
USHORT LoadCount;
USHORT TlsIndex;
LIST_ENTRY HashLinks;
PVOID SectionPointer;
ULONG CheckSum;
ULONG TimeDateStamp;
PVOID LoadedImports;
PVOID EntryPointActivationContext;
PVOID PatchInformation;
} KLDR_DATA_TABLE_ENTRY, *PKLDR_DATA_TABLE_ENTRY;
在调试模式下,可以通过修改 KLDR_DATA_TABLE_ENTRY 结构体中的 Flags 标志来规避签名验证。具体而言,可以将 pLdrData->Flags 的值与 0x20 进行按位或操作,将 Flags 的对应位置位,以绕过签名验证。这样驱动程序将不再进行签名验证,避免了重复签名的麻烦。
代码的实现非常容易,如下所示:
// 署名权
// right to sign one's name on a piece of work
// PowerBy: LyShark
#include <ntifs.h>
// 绕过签名检查
BOOLEAN BypassCheckSign(PDRIVER_OBJECT pDriverObject)
{
#ifdef _WIN64
typedef struct _KLDR_DATA_TABLE_ENTRY
{
LIST_ENTRY listEntry;
ULONG64 __Undefined1;
ULONG64 __Undefined2;
ULONG64 __Undefined3;
ULONG64 NonPagedDebugInfo;
ULONG64 DllBase;
ULONG64 EntryPoint;
ULONG SizeOfImage;
UNICODE_STRING path;
UNICODE_STRING name;
ULONG Flags;
USHORT LoadCount;
USHORT __Undefined5;
ULONG64 __Undefined6;
ULONG CheckSum;
ULONG __padding1;
ULONG TimeDateStamp;
ULONG __padding2;
} KLDR_DATA_TABLE_ENTRY, *PKLDR_DATA_TABLE_ENTRY;
#else
typedef struct _KLDR_DATA_TABLE_ENTRY
{
LIST_ENTRY listEntry;
ULONG unknown1;
ULONG unknown2;
ULONG unknown3;
ULONG unknown4;
ULONG unknown5;
ULONG unknown6;
ULONG unknown7;
UNICODE_STRING path;
UNICODE_STRING name;
ULONG Flags;
} KLDR_DATA_TABLE_ENTRY, *PKLDR_DATA_TABLE_ENTRY;
#endif
PKLDR_DATA_TABLE_ENTRY pLdrData = (PKLDR_DATA_TABLE_ENTRY)pDriverObject->DriverSection;
pLdrData->Flags = pLdrData->Flags | 0x20;
return TRUE;
}
VOID UnDriver(PDRIVER_OBJECT driver)
{
}
NTSTATUS DriverEntry(IN PDRIVER_OBJECT Driver, PUNICODE_STRING RegistryPath)
{
NTSTATUS status;
// 绕过签名检查
// LINKER_FLAGS=/INTEGRITYCHECK
BypassCheckSign(Driver);
DbgPrint("[驱动已加载] hello lyshark.com \n");
Driver->DriverUnload = UnDriver;
return STATUS_SUCCESS;
}
将程序拖入到虚拟机,直接运行即可加载,无需再继续签名.
当然这种方式只能在测试模式下使用,在正常模式也是无效的,只是为了方便测试驱动。