Windows用户层使用指令操作内核程序执行指令!(6) 驱动程序入口

该文件全面涵盖了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()可以放入自己要加载的模块,如权限检查模块等.注意一定要在卸载函数里释放对应的申请的内存,操作系统是不会自动释放内核程序的内存的!不然会导致内存泄露问题

Windows用户层使用指令操作内核程序执行指令! (7) 命令执行

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值