该文件全面涵盖了Windows驱动开发过程中至关重要的多个方面,其中不仅包含了作为驱动程序开发起点的入口程序,用于在系统启动或相关操作时初始化并加载驱动程序,确保其能够正确地与硬件设备进行交互和协同工作;还包含了负责在特定条件下安全、有序地卸载驱动程序的程序,以防止出现资源泄漏、系统不稳定等问题。此外,文件中还涉及到了一系列命令初始化的内容,这些命令对于驱动程序的正确运行和配置起着关键作用,它们能够在驱动程序的不同阶段执行各种操作,如设置初始参数、分配资源等。同时,文件里还包含了全局变量的定义部分,这些全局变量在整个驱动程序的运行过程中扮演着重要的角色,它们可以被不同的模块和函数共享和使用,用于存储驱动程序的状态信息、配置参数以及其他关键数据,从而保证驱动程序的各个部分之间能够高效地进行通信和协作。
driver.cpp
#include <ntifs.h>
#include "data.h"
#include "struct.h"
#include "Logging.h"
#include "file.h"
#include "encryption.h"
#include "driverInit.h"
#include "command.h"
char g_dataBuffer[BUFFER_SIZE];
ULONG g_dataLength = 0;
_RTL_GENERIC_TABLE CommandsTable;
HANDLE LogFileHandle;
HANDLE ResultFileHandle;
char TimeBuffer[30];
NTSTATUS CreateFile() {
//若c:\ly文件夹不存在,则创建
if (!MyFileExists(L"\\??\\C:\\ly")) {
MyCreateFileFolder(L"\\??\\C:\\ly");
}
//若c:\ly\log文件不存在,则创建
if (!MyFileExists(L"\\??\\C:\\ly\\log")) {
MyCreateFile(L"\\??\\C:\\ly\\log");
}
if (MyFileExists(L"\\??\\C:\\ly\\result")) {
MyDeleteFileOrFileFolder(L"\\??\\C:\\ly\\result");
}
MyCreateFile(L"\\??\\C:\\ly\\result");
return STATUS_SUCCESS;
}
NTSTATUS init() {
NTSTATUS status = STATUS_SUCCESS;
status = CreateFile();
if (!NT_SUCCESS(status)) {
DbgPrint("[LyKernelService] Failed to create file, status: 0x%X\n", status);
return status;
}
DbgPrint("[LyKernelService] File created successfully!\n");
status = OpenLogFile();
if (!NT_SUCCESS(status)) {
DbgPrint("[LyKernelService] Failed to open log file, status: 0x%X\n", status);
return status;
}
WriteLog("[LyKernelService] Command module initialized successfully!\n");
status = OpenResultFile();
if (!NT_SUCCESS(status)) {
WriteLog("[LyKernelService] Failed to open result file, status: 0x%X\n", status);
return status;
}
status = InitializeCommands();
if (!NT_SUCCESS(status)) {
DbgPrint("[LyKernelService] Failed to initialize commands, status: 0x%X\n", status);
}
WriteLog("[LyKernelService] Command module initialized successfully!\n");
return status;
}
NTSTATUS split(char* data, ULONG length, UNICODE_STRING* result, ULONG* result_count) {
// 参数检查
if (data == NULL || length == 0) {
WriteLog("[LyKernelService] Invalid parameter, data: %p, length: %d\n", data, length);
return STATUS_INVALID_PARAMETER;
}
ULONG count = 0;
ULONG temp_index = 0;
BOOLEAN in_word = FALSE;
// 临时缓存存储每个分割的子字符串
WCHAR temp[512]; // 临时缓存,用于存储每个子字符串
// 分配足够的内存来存储每个子字符串的缓冲区
WCHAR* buffers = (WCHAR*)ExAllocatePool2(POOL_FLAG_NON_PAGED, sizeof(WCHAR) * 512 * 1024, 'args');
if (buffers == NULL) {
WriteLog("[LyKernelService] Failed to allocate memory for buffers, status: 0x%X\n", STATUS_INSUFFICIENT_RESOURCES);
return STATUS_INSUFFICIENT_RESOURCES;
}
// 临时指针指向当前缓冲区的位置
WCHAR* current_buffer = buffers;
// 遍历输入字符串
for (ULONG i = 0; i < length; ++i) {
char current_char = data[i];
if (current_char == ' ') {
// 如果当前是空格,并且之前有字符(即是一个单词结束)
if (in_word) {
// 将 temp 缓存中的内容转换成 UNICODE_STRING
temp[temp_index] = L'\0'; // 结束字符串
// 初始化 UNICODE_STRING 结构
RtlInitUnicodeString(&result[count], current_buffer);
result[count].Length = temp_index * sizeof(WCHAR);
result[count].MaximumLength = 512 * sizeof(WCHAR);
// 复制 temp 缓存中的内容到分配的缓冲区
RtlCopyMemory(current_buffer, temp, temp_index * sizeof(WCHAR));
count++;
in_word = FALSE;
temp_index = 0; // 重置临时缓冲区索引
current_buffer += 512; // 移动到下一个缓冲区位置
}
}
else {
// 处理非空格字符,填充到临时缓存中
temp[temp_index++] = (WCHAR)current_char;
in_word = TRUE;
}
}
// 如果最后一个单词后面没有空格,仍然需要处理
if (in_word) {
temp[temp_index] = L'\0'; // 结束字符串
// 初始化 UNICODE_STRING 结构
RtlInitUnicodeString(&result[count], current_buffer);
result[count].Length = temp_index * sizeof(WCHAR);
result[count].MaximumLength = 512 * sizeof(WCHAR);
// 复制 temp 缓存中的内容到分配的缓冲区
RtlCopyMemory(current_buffer, temp, temp_index * sizeof(WCHAR));
count++;
}
// 设置返回的单词数量
*result_count = count;
// 如果分割出来的单词数大于0,返回成功
if (count > 0) {
return STATUS_SUCCESS;
}
else {
ExFreePoolWithTag(buffers, 'args'); // 释放已分配的缓冲区内存
return STATUS_NO_MORE_ENTRIES;
}
}
NTSTATUS execute_command(char* command, ULONG length) {
NTSTATUS status = STATUS_SUCCESS;
UNICODE_STRING command_string;
char* p = command;
ULONG Length;
UNICODE_STRING* arguments = (UNICODE_STRING*) ExAllocatePool2(POOL_FLAG_NON_PAGED, 1024 * sizeof(UNICODE_STRING), 'args');
if (arguments == NULL) {
WriteLog("[LyKernelService] Failed to allocate memory for arguments, status: 0x%X\n", STATUS_INSUFFICIENT_RESOURCES);
return STATUS_INSUFFICIENT_RESOURCES;
}
status = split(p, length, arguments, &Length);
if (!NT_SUCCESS(status)) {
WriteLog("[LyKernelService] Failed to split command, status: 0x%X\n", status);
return status;
}
if (Length == 0 || arguments == NULL) {
WriteLog("[LyKernelService] Invalid command format: %s\n", command);
WriteLog("[LyKernelService] Length: %d, Arguments: %p\n", Length, arguments);
return STATUS_INVALID_PARAMETER;
}
RtlInitUnicodeString(&command_string, arguments[0].Buffer);
UNICODE_STRING* args = (UNICODE_STRING*)ExAllocatePool2(POOL_FLAG_NON_PAGED, (Length - 1) * sizeof(UNICODE_STRING), 'args');
if (args == NULL) {
WriteLog("[LyKernelService] Failed to allocate memory for arguments, status: 0x%X\n", STATUS_INSUFFICIENT_RESOURCES);
return STATUS_INSUFFICIENT_RESOURCES;
}
for (ULONG i = 1; i < Length; i++) {
RtlInitUnicodeString(&args[i - 1], arguments[i].Buffer);
}
status = execute(command_string, args, Length - 1);
if (!NT_SUCCESS(status)) {
WriteLog("[LyKernelService] Failed to execute command, status: 0x%X\n", status);
return status;
}
ExFreePoolWithTag(arguments, 'args');
ExFreePoolWithTag(args, 'args');
return status;
}
NTSTATUS verification() {
NTSTATUS status = STATUS_SUCCESS;
char* p = g_dataBuffer;
ULONG length = g_dataLength;
if (length <= 32) {
status = STATUS_INVALID_PARAMETER;
WriteLog("[LyKernelService] Invalid data length: %d\n", length);
return status;
}
//获取数据后32位为MD5值,于前面数据进行AES加密,再进行Base64编码,再进行md5计算
//比较计算结果与前面32位MD5值是否一致,不一致则认为数据被篡改
char aesResult[1024];
ULONG aesResultLength = 1024;
status = AesEncrypt(p + length - 32, 32, aesResult, aesResultLength);
if (!NT_SUCCESS(status)) {
WriteLog("[LyKernelService] AES encryption failed, status: 0x%X\n", status);
return status;
}
char md5Result[33];
char md5Data[33];
RtlCopyMemory(md5Data, p, 32);
md5Data[32] = '\0';
status = md5(aesResult, aesResultLength, md5Result);
if (!NT_SUCCESS(status)) {
WriteLog("[LyKernelService] MD5 hash failed, status: 0x%X\n", status);
return status;
}
if (strcmp(md5Data, md5Result) != 0) {
WriteLog("[LyKernelService] Data has been tampered with!\n");
status = STATUS_ACCESS_DENIED;
}
WriteLog("[LyKernelService] Data parsing completed!\n");
}
NTSTATUS parse() {
NTSTATUS status = verification();
if (!NT_SUCCESS(status)) {
return status;
}
char command[1024];
RtlCopyMemory(command, g_dataBuffer, g_dataLength - 32);
command[g_dataLength - 32] = '\0';
status = execute_command(command, g_dataLength - 32);
if (!NT_SUCCESS(status)) {
WriteLog("[LyKernelService] Command execution failed, status: 0x%X\n", status);
}
return status;
}
VOID UnDriver(PDRIVER_OBJECT DriverObject) {
PDEVICE_OBJECT pDev;
UNICODE_STRING SymLinkName;
pDev = DriverObject->DeviceObject;
IoDeleteDevice(pDev);
RtlInitUnicodeString(&SymLinkName, L"\\??\\LyKernelService");
IoDeleteSymbolicLink(&SymLinkName);
ZwClose(LogFileHandle);
ZwClose(ResultFileHandle);
UninitializeCommands();
DbgPrint("[LyKernelService] Driver unloaded successfully!\n");
}
extern "C" NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath) {
NTSTATUS status = init();
if (!NT_SUCCESS(status)) {
//status = 0xc000003a; // STATUS_DLL_NOT_FOUND
DbgPrint("[LyKernelService] Failed to initialize driver, status: 0x%X\n", status);
return status;
}
WriteLog("[LyKernelService] Driver loading started...\n");
NTSTATUS Status = CreateDriverObject(DriverObject);
if (!NT_SUCCESS(Status)) {
WriteLog("[LyKernelService] Failed to create driver object, status: 0x%X\n", Status);
return Status;
}
for (ULONG i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++) {
DriverObject->MajorFunction[i] = DriverDefaultHandle;
}
DriverObject->DriverUnload = UnDriver;
DriverObject->MajorFunction[IRP_MJ_CREATE] = DispatchCreate;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = DispatchClose;
DriverObject->MajorFunction[IRP_MJ_READ] = DispatchRead;
DriverObject->MajorFunction[IRP_MJ_WRITE] = DispatchWrite;
WriteLog("[LyKernelService] Driver loaded successfully!\n");
return STATUS_SUCCESS;
}
init()可以放入自己要加载的模块,如权限检查模块等.注意一定要在卸载函数里释放对应的申请的内存,操作系统是不会自动释放内核程序的内存的!不然会导致内存泄露问题

被折叠的 条评论
为什么被折叠?



