方法一:使用测试签名模式

在windows中设置测试签名模式:

  • 按下 Windows + X 键打开快捷菜单

  • 选择”Windows PowerShell (管理员)”

  • 在 PowerShell 中输入以下命令并回车:

    1
    bcdedit /set testsigning on
  • 重启电脑以使更改生效

方法二:禁用windows驱动签名

  • 在启动windows操作系统时禁用驱动签名。

  • 命令行关闭签名验证,重启后生效。

开启与关闭命令

1
2
3
4
#禁用您设备上的驱动程序签名
bcdedit.exe / set nointegritychecks on
#启用此功能,请运行以下命令
bcdedit.exe / set nointegritychecks off

方法四:使用驱动漏洞关闭签名验证

  1. 下载kdu软件。

  2. 在kdu同目录下运行命令关闭签名验证(无需重启,立即生效)。

    1
    kdu -dse 0
  3. 成功加载驱动后可选择重新打开签名验证。

    1
    kdu -dse 6

方法五:在系统启动阶段加载内核工具可开关驱动签名验证

EfiGuard

方法六:绕过驱动强制签名加载未签名驱动

  1. 编写驱动程序代码时,修改驱动入口点。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    //entry.c
    #define Log(X) DbgPrint("qi: %s\n", X)

    NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
    {
    DriverObject->DriverUnload = NULL; // 取消卸载函数
    Log("Loaded Successfully!"); // 输出日志信息
    return STATUS_SUCCESS;
    }
  2. 使用现有的工具映射未签名驱动。

    • 工具一:使用kde(利用漏洞驱动)

      1
      kdu -prv 6 -scv 3 -drvn edrv -drvr e3600bl -map c:\install\e3600bl.sys 
    • 工具二:使用kdmapper

      1
      kdmapper HelloWorld.sys

      使用 kdmapper 进行驱动映射时,确实需要对现有驱动程序做一定的修改,因为它并不是标准的 SCManager 驱动加载流程,而是通过漏洞/绕过方式直接将驱动映射进内核,并执行其入口点。下面我详细讲讲哪些部分可能需要调整:


      ✅ 一、必须注意的修改点

      1. DriverEntry 函数必须保留

      kdmapper 映射驱动时,会模拟调用 DriverEntry,因此:

      • 不要删掉 DriverEntry

      • 保证它的签名是:

        1
        NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath);

      但由于不是通过 Service Manager 加载的,**DriverObjectRegistryPath 可能为空或无效**,不能依赖它们。


      1. 不能调用 IoCreateDevice / IoCreateSymbolicLink 等通信接口初始化函数

      使用 kdmapper 映射驱动时:

      • 系统没有正式注册这个驱动,所以创建设备对象(如 \\Device\\MyDrv) 和符号链接通常会失败;
      • 无法通过 CreateFile 打开设备 → 无法使用标准 DeviceIoControl 通信方式。

      🔧 如果需要通信,使用共享内存、全局变量、Hook 等非常规通信方式,或用一个额外的驱动/用户层代理进行通信桥接。


      1. 不建议使用 Unload 函数

      因为 kdmapper 映射的驱动并没有被 SCManager 管理,调用 IoDeleteDeviceIoDeleteSymbolicLink 很可能会异常或蓝屏。推荐:

      1
      DriverObject->DriverUnload = NULL;

      ✅ 二、推荐的驱动结构(供 kdmapper 使用)

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      tNTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
      {
      UNREFERENCED_PARAMETER(DriverObject);
      UNREFERENCED_PARAMETER(RegistryPath);

      // 不要创建设备或符号链接
      // 不要依赖 IRP 分发函数

      // 直接执行功能逻辑(例如 Patch、Hook、注入、修改内存等)

      DbgPrint("kdmapper loaded driver.\n");

      return STATUS_SUCCESS;
      }

      ✅ 三、通信方式建议

      由于无法使用标准设备通信,可以考虑:

      • 使用共享内存或映射内存区(例如 ZwMapViewOfSection);
      • 用户层写一个程序,将任务写入一个预定义的内核全局变量或结构;
      • 或者通过 SSDT/Inline Hook 等方式,拦截现有函数 + 传递控制指令。

      ✅ 四、调试建议

      • DbgPrint 写日志(用 WinDbg 或 DebugView 查看);
      • 使用 kdmapper 参数 --free 自动释放映射内存,或 --no-clean 保留驱动;
      • 断点/日志观察 DriverEntry 是否真的被执行。

方法七:使用驱动加载未签名驱动。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
#include <ntddk.h>

typedef struct _PE_HEADER {
UCHAR Signature[4]; // "PE\0\0"
USHORT Machine;
USHORT NumberOfSections;
ULONG TimeDateStamp;
ULONG PointerToSymbolTable;
ULONG NumberOfSymbols;
USHORT SizeOfOptionalHeader;
USHORT Characteristics;
} PE_HEADER, * PPE_HEADER;

typedef struct _PE_OPTIONAL_HEADER {
USHORT Magic;
UCHAR MajorLinkerVersion;
UCHAR MinorLinkerVersion;
ULONG SizeOfCode;
ULONG SizeOfInitializedData;
ULONG SizeOfUninitializedData;
ULONG AddressOfEntryPoint; // 入口点地址
ULONG BaseOfCode;
ULONG BaseOfData;
ULONG ImageBase;
ULONG SectionAlignment;
ULONG FileAlignment;
USHORT MajorOperatingSystemVersion;
USHORT MinorOperatingSystemVersion;
USHORT MajorImageVersion;
USHORT MinorImageVersion;
USHORT MajorSubsystemVersion;
USHORT MinorSubsystemVersion;
ULONG Win32VersionValue;
ULONG SizeOfImage;
ULONG SizeOfHeaders;
ULONG CheckSum;
USHORT Subsystem;
USHORT DllCharacteristics;
ULONG SizeOfStackReserve;
ULONG SizeOfStackCommit;
ULONG SizeOfHeapReserve;
ULONG SizeOfHeapCommit;
ULONG LoaderFlags;
ULONG NumberOfRvaAndSizes;
} PE_OPTIONAL_HEADER, * PPE_OPTIONAL_HEADER;

typedef struct _PE_SECTION_HEADER {
UCHAR Name[8];
union {
ULONG PhysicalAddress;
ULONG VirtualSize;
};
ULONG VirtualAddress;
ULONG SizeOfRawData;
ULONG PointerToRawData;
ULONG PointerToRelocations;
ULONG PointerToLinenumbers;
USHORT NumberOfRelocations;
USHORT NumberOfLinenumbers;
ULONG Characteristics;
} PE_SECTION_HEADER, * PPE_SECTION_HEADER;

// 获取入口点地址
PVOID GetDriverEntryPoint(PVOID BaseAddress) {
PPE_HEADER peHeader = (PPE_HEADER)BaseAddress;

// 检查 PE 文件头
if (peHeader->Signature[0] != 'P' || peHeader->Signature[1] != 'E' || peHeader->Signature[2] != '\0' || peHeader->Signature[3] != '\0') {
DbgPrint("Invalid PE file signature\n");
return NULL;
}

// 获取可选头
PPE_OPTIONAL_HEADER optionalHeader = (PPE_OPTIONAL_HEADER)((ULONG_PTR)BaseAddress + sizeof(PE_HEADER));

// 检查 Magic 字段来确认这是一个 PE32+ 文件
if (optionalHeader->Magic != 0x20b) {
DbgPrint("Invalid PE file magic\n");
return NULL;
}

// 获取入口点地址
ULONG entryPointRVA = optionalHeader->AddressOfEntryPoint;

// 将入口点 RVA 转换为 VA
PVOID entryPoint = (PVOID)((ULONG_PTR)BaseAddress + entryPointRVA);

return entryPoint;
}


// 定义驱动程序路径
#define DRIVER_PATH L"\\??\\C:\\path\\to\\unsigned_driver.sys"

// 定义结构体以存储文件数据
typedef struct _DRIVER_FILE_DATA {
PVOID BaseAddress;
SIZE_T FileSize;
} DRIVER_FILE_DATA, * PDRIVER_FILE_DATA;

// 辅助函数:读取文件
NTSTATUS ReadDriverFile(PUNICODE_STRING FilePath, PDRIVER_FILE_DATA DriverFileData) {
HANDLE fileHandle = NULL;
OBJECT_ATTRIBUTES objAttr;
IO_STATUS_BLOCK ioStatusBlock;
NTSTATUS status;

// 初始化对象属性
InitializeObjectAttributes(&objAttr, FilePath, OBJ_CASE_INSENSITIVE, NULL, NULL);

// 打开驱动程序文件
status = ZwOpenFile(&fileHandle, GENERIC_READ, &objAttr, &ioStatusBlock, FILE_SHARE_READ, 0);
if (!NT_SUCCESS(status)) {
DbgPrint("Failed to open driver file\n");
return status;
}

// 获取文件大小
status = ZwQueryInformationFile(fileHandle, &ioStatusBlock, &DriverFileData->FileSize, sizeof(DriverFileData->FileSize), FileStandardInformation);
if (!NT_SUCCESS(status)) {
DbgPrint("Failed to query file size\n");
ZwClose(fileHandle);
return status;
}

// 分配内存以存储文件内容
DriverFileData->BaseAddress = ExAllocatePoolWithTag(NonPagedPool, DriverFileData->FileSize, 'drvr');
if (DriverFileData->BaseAddress == NULL) {
DbgPrint("Memory allocation failed\n");
ZwClose(fileHandle);
return STATUS_INSUFFICIENT_RESOURCES;
}

// 读取文件内容到内存
status = ZwReadFile(fileHandle, NULL, NULL, NULL, &ioStatusBlock, DriverFileData->BaseAddress, DriverFileData->FileSize, NULL, NULL);
if (!NT_SUCCESS(status)) {
DbgPrint("Failed to read driver file into memory\n");
ExFreePoolWithTag(DriverFileData->BaseAddress, 'drvr');
ZwClose(fileHandle);
return status;
}

// 关闭文件句柄
ZwClose(fileHandle);
return STATUS_SUCCESS;
}


NTSYSAPI NTSTATUS NTAPI ZwWaitForSingleObject(
IN HANDLE ObjectHandle,
IN BOOLEAN WaitAll,
IN PLARGE_INTEGER Timeout
);


// 辅助函数:执行驱动程序的入口点
NTSTATUS ExecuteDriver(PVOID DriverBaseAddress) {
PVOID entryPoint = GetDriverEntryPoint(DriverBaseAddress);

// 在内核模式下执行入口点代码
// 创建一个内核线程执行 DriverEntry
HANDLE threadHandle;
NTSTATUS status = PsCreateSystemThread(&threadHandle, THREAD_ALL_ACCESS, NULL, NULL, NULL, (PKSTART_ROUTINE)entryPoint, NULL);
if (!NT_SUCCESS(status)) {
DbgPrint("Failed to create thread\n");
return status;
}

// 等待线程执行完成
ZwWaitForSingleObject(threadHandle, FALSE, NULL);
ZwClose(threadHandle);
return STATUS_SUCCESS;
}

// 主加载函数
NTSTATUS LoadAndExecuteDriver() {
UNICODE_STRING filePath = RTL_CONSTANT_STRING(DRIVER_PATH);
DRIVER_FILE_DATA driverFileData = { 0 };

// 读取驱动程序文件
NTSTATUS status = ReadDriverFile(&filePath, &driverFileData);
if (!NT_SUCCESS(status)) {
DbgPrint("Failed to read the driver file\n");
return status;
}

// 执行驱动程序
status = ExecuteDriver(driverFileData.BaseAddress);
if (!NT_SUCCESS(status)) {
DbgPrint("Failed to execute driver\n");
ExFreePoolWithTag(driverFileData.BaseAddress, 'drvr');
return status;
}

// 清理
ExFreePoolWithTag(driverFileData.BaseAddress, 'drvr');
return STATUS_SUCCESS;
}

// DriverEntry
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath) {
DbgPrint("Driver Loaded Successfully\n");

// 加载并执行未签名驱动程序
NTSTATUS status = LoadAndExecuteDriver();
if (!NT_SUCCESS(status)) {
DbgPrint("Failed to load and execute the driver\n");
}

return STATUS_SUCCESS;
}

方法八 使用C语言编写应用程序加载未签名驱动。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
#include <windows.h>
#include <winternl.h>
#include <stdio.h>

#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)

typedef NTSTATUS(WINAPI* ZwLoadDriver_t)(PUNICODE_STRING DriverServiceName);

void Log(const char* Message) {
printf("%s\n", Message);
}

void LoadDriver(const wchar_t* driverPath) {
// 1. 打开驱动文件
HANDLE fileHandle = CreateFileW(driverPath, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (fileHandle == INVALID_HANDLE_VALUE) {
Log("Failed to open driver file.");
return;
}

// 2. 获取文件大小
DWORD fileSize = GetFileSize(fileHandle, NULL);
if (fileSize == INVALID_FILE_SIZE) {
Log("Failed to get driver file size.");
CloseHandle(fileHandle);
return;
}

// 3. 将驱动文件映射到内存
HANDLE mappingHandle = CreateFileMapping(fileHandle, NULL, PAGE_READONLY, 0, fileSize, NULL);
if (mappingHandle == NULL) {
Log("Failed to create file mapping.");
CloseHandle(fileHandle);
return;
}

LPVOID mappedMemory = MapViewOfFile(mappingHandle, FILE_MAP_READ, 0, 0, fileSize);
if (mappedMemory == NULL) {
Log("Failed to map view of file.");
CloseHandle(mappingHandle);
CloseHandle(fileHandle);
return;
}

Log("Driver file successfully mapped to memory.");

// 4. 构造 UNICODE_STRING 结构
UNICODE_STRING driverServiceName;
driverServiceName.Length = wcslen(driverPath) * sizeof(wchar_t);
driverServiceName.MaximumLength = driverServiceName.Length + sizeof(wchar_t);
driverServiceName.Buffer = (PWSTR)driverPath;

// 5. 获取 ZwLoadDriver 函数地址
HMODULE ntdllModule = GetModuleHandleW(L"ntdll.dll");
if (ntdllModule == NULL) {
Log("Failed to load ntdll.dll.");
UnmapViewOfFile(mappedMemory);
CloseHandle(mappingHandle);
CloseHandle(fileHandle);
return;
}

ZwLoadDriver_t ZwLoadDriver = (ZwLoadDriver_t)GetProcAddress(ntdllModule, "ZwLoadDriver");
if (ZwLoadDriver == NULL) {
Log("Failed to find ZwLoadDriver.");
UnmapViewOfFile(mappedMemory);
CloseHandle(mappingHandle);
CloseHandle(fileHandle);
return;
}

// 6. 加载驱动
NTSTATUS status = ZwLoadDriver(&driverServiceName);
if (NT_SUCCESS(status)) {
Log("Driver loaded successfully.");
}
else {
Log("Failed to load driver.");
}

// 7. 清理资源
UnmapViewOfFile(mappedMemory);
CloseHandle(mappingHandle);
CloseHandle(fileHandle);
}

int main() {
// 输入未签名驱动的路径
const wchar_t* driverPath = L"C:\\path\\to\\your\\unsigned\\driver.sys";

LoadDriver(driverPath);

return 0;
}