四、文件 注册表 多线程

文件 注册表 多线程

1、文件操作

文件操作,内核模式下打开、创建、拷贝文件

#include <ntddk.h>


VOID DriverUnload(PDRIVER_OBJECT pDriverObject)
{
	KdPrint(("驱动成功卸载\n"));
}

void MyCopyFile(HANDLE source, HANDLE dest)
{
	NTSTATUS status;
	PVOID buffer = NULL;
	LARGE_INTEGER offset = { 0 };
	IO_STATUS_BLOCK io_status = { 0 };
	buffer = ExAllocatePool(PagedPool, 4*1024*sizeof(char));
	if (buffer == NULL)
	{
		KdPrint(("分配读写buffer空间失败"));
		return;
	}
	int length = 1024 * 4;
	do
	{
		while (1)
		{
			status = ZwReadFile(source, NULL, NULL, NULL, &io_status, buffer, length, &offset, NULL);
			if (!NT_SUCCESS(status))
			{
				if (status == STATUS_END_OF_FILE)
					status = STATUS_SUCCESS;
				break;
			}
			
			length = io_status.Information;
			
			status = ZwWriteFile(dest, NULL, NULL, NULL, &io_status,buffer, length, &offset, NULL);
			if (!NT_SUCCESS(status))
				break;
			offset.QuadPart += length;
		}
	} while (0);
	if (buffer != NULL)
		ExFreePool(buffer);

}

NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING reg_path)
{
	NTSTATUS status;

	KdPrint(("%wZ",reg_path));
	UNICODE_STRING unicSourceName, unicDestName;
	RtlInitUnicodeString(&unicSourceName, L"\\??\\c:\\test\\sql.txt");
	KdPrint(("source file is: %wZ", &unicSourceName));

	RtlInitUnicodeString(&unicDestName, L"\\??\\c:\\test\\sqltest.txt");
	KdPrint(("dest file is: %wZ", &unicDestName));

	HANDLE hSourceHandle = NULL;
	HANDLE hDestHandle = NULL;
	OBJECT_ATTRIBUTES object_attributes1, object_attributes2;
	IO_STATUS_BLOCK iostatus;
	//初始化文件属性
	InitializeObjectAttributes(
		&object_attributes1,
		&unicSourceName,
		OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
		NULL,
		NULL
	);

	InitializeObjectAttributes(
		&object_attributes2,
		&unicDestName,
		OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
		NULL,
		NULL
	);

	status = ZwCreateFile(
		&hSourceHandle,
		GENERIC_READ | GENERIC_WRITE,
		&object_attributes1,
		&iostatus,
		NULL,
		FILE_ATTRIBUTE_NORMAL,
		FILE_SHARE_READ,
		FILE_OPEN_IF,
		FILE_NON_DIRECTORY_FILE|FILE_RANDOM_ACCESS|FILE_SYNCHRONOUS_IO_NONALERT,
		NULL,
		0
	);
	if (!NT_SUCCESS(status))
	{
		KdPrint(("文件打开失败"));
		KdPrint(("失败原因:%d", iostatus.Information));
	}
	status = ZwCreateFile(
		&hDestHandle,
		GENERIC_READ | GENERIC_WRITE,
		&object_attributes2,
		&iostatus,
		NULL,
		FILE_ATTRIBUTE_NORMAL,
		FILE_SHARE_READ,
		FILE_OPEN_IF,
		FILE_NON_DIRECTORY_FILE|FILE_RANDOM_ACCESS | FILE_SYNCHRONOUS_IO_NONALERT,
		NULL,
		0
	);
	if (!NT_SUCCESS(status))
	{
		KdPrint(("创建文件失败"));
		KdPrint(("失败原因:%d", iostatus.Information));
	}

	MyCopyFile(hSourceHandle, hDestHandle);
	ZwClose(hDestHandle);
	ZwClose(hSourceHandle);

	pDriverObject->DriverUnload = DriverUnload;
	return STATUS_SUCCESS;
}

2、注册表操作

内核程序读写注册表跟应用程序API大致相似,应用程序根子键句柄与内核注册表路径对应表如下:

应用程序对应的子键驱动编程中的路径写法
HKEY_LOCAL_MACHINE\Registry\Machine
KEY_USERS\Registry\User
HEY_CLASSES_ROOT没有对应的路径
HKEY_CURRENT_USER没有对应的路径,但是可以求得

内核程序读写注册表步骤为:InitilizeObjectAttributes初始化OBJECT_ATTRIBUTES,ZwCreateKey或者ZwOpenKey打开注册表键获取句柄,ZwQueryValueKey第一次调用获取注册表键值需要存储的空间大小,ZwQueryValueKey第二次调用会把注册表键值信息(类型、值数据)保存在KEY_VALUE_PARTIAL_INFORMATION结构中。根据该结构中的Type分类解析数据,REG_DWORD、REG_SZ,常用的是双字节和字符串型,如何取值参考完整代码,写入注册表值使用ZwSetValueKey,关闭注册表句柄ZwClose,API参数如下:

InitializeObjectAttributes参数初始化OBJECT_ATTRIBUTES

VOID
InitializeObjectAttributes(
    OUT POBJECT_ATTRIBUTES InitializedAttributes ,
    IN PUNICODE_STRING ObjectName ,
    IN ULONG Attributes ,
    IN HANDLE RootDirectory ,
    IN PSECURITY_DESCRIPTOR SecurityDescriptor
    );

ZwCreateKey以创建的方式打开注册表

NTSYSAPI NTSTATUS ZwCreateKey(
  PHANDLE            KeyHandle,
  ACCESS_MASK        DesiredAccess,
  POBJECT_ATTRIBUTES ObjectAttributes,
  ULONG              TitleIndex,
  PUNICODE_STRING    Class,
  ULONG              CreateOptions,
  PULONG             Disposition
);

ZwOpenKey打开注册表

NTSYSAPI NTSTATUS ZwOpenKey(
  PHANDLE            KeyHandle,
  ACCESS_MASK        DesiredAccess,
  POBJECT_ATTRIBUTES ObjectAttributes
);

ZwQueryValueKey查询注册表路径下的项值

NTSYSAPI NTSTATUS ZwQueryValueKey(
  HANDLE                      KeyHandle,
  PUNICODE_STRING             ValueName,
  KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass,
  PVOID                       KeyValueInformation,
  ULONG                       Length,
  PULONG                      ResultLength
);

ZwSetValueKey写注册表值

NTSYSAPI NTSTATUS ZwSetValueKey(
  HANDLE          KeyHandle,
  PUNICODE_STRING ValueName,
  ULONG           TitleIndex,
  ULONG           Type,
  PVOID           Data,
  ULONG           DataSize
);

ZwClose注册表操作完后关闭注册表句柄

NTSTATUS
NTAPI
ZwClose(
    _In_ HANDLE Handle
    );

完整操作注册表的函数如下

void GetKeyValue(PKEY_VALUE_PARTIAL_INFORMATION pKeyValue_infor, PUNICODE_STRING unicString, PULONG ulVaule)
{
	switch (pKeyValue_infor->Type)
	{
		case REG_BINARY:
		{
			break;
		}
		case REG_DWORD:
		{
			*ulVaule = *(PULONG)(pKeyValue_infor->Data);
			break;
		}
		case REG_DWORD_BIG_ENDIAN:
		{
			break;
		}
		case REG_EXPAND_SZ:
		{
			break;
		}
		case REG_MULTI_SZ:
		{
			break;
		}
		case REG_SZ:
		{
			RtlInitUnicodeString(unicString, (PCWSTR)(pKeyValue_infor->Data));
			break;
		}
		default:
		{
			break;
		}
	}
}
void RegReadWrite()
{
	HANDLE my_key = NULL;
	NTSTATUS status;

	//注册表路径
	UNICODE_STRING my_key_path = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion");

	//UNICODE_STRING my_key_newPath = RTL_CONSTANT_STRING(L"")

	OBJECT_ATTRIBUTES my_object_attr = {0};
	InitializeObjectAttributes(&my_object_attr, &my_key_path, OBJ_CASE_INSENSITIVE,NULL,NULL);

	//打开key
	status = ZwOpenKey(&my_key, GENERIC_ALL, &my_object_attr);
	if (!NT_SUCCESS(status))
	{
		KdPrint(("打开注册表项失败"));
	}
	UNICODE_STRING my_key_name = RTL_CONSTANT_STRING(L"UBR");

	KEY_VALUE_PARTIAL_INFORMATION key_infor; //试探需要的空间
	PKEY_VALUE_PARTIAL_INFORMATION ac_key_infor; //重新分配的空间

	ULONG ac_length; //实际返回的字节长度
	status = ZwQueryValueKey(
		my_key,
		&my_key_name,
		KeyValuePartialInformation,
		&key_infor,
		sizeof(KEY_VALUE_PARTIAL_INFORMATION),
		&ac_length
	);
	if (!NT_SUCCESS(status) && status != STATUS_BUFFER_OVERFLOW && status != STATUS_BUFFER_TOO_SMALL)
	{
		//错误处理
		ZwClose(my_key);
		return;
	}
	ac_key_infor = (PKEY_VALUE_PARTIAL_INFORMATION)ExAllocatePoolWithTag(NonPagedPool, ac_length, 'TEST');
	if (ac_key_infor == NULL)
	{
		status = STATUS_INSUFFICIENT_RESOURCES;
		//错误处理
		ZwClose(my_key);
		return;
	}
	status = ZwQueryValueKey(
		my_key,
		&my_key_name,
		KeyValuePartialInformation,
		ac_key_infor,
		ac_length,
		&ac_length
	);

	if (!NT_SUCCESS(status))
	{
		KdPrint(("Get key error"));
		//错误处理
		ZwClose(my_key);
		return;
	}
	UNICODE_STRING keyString;
	ULONG	lKeyValue;
	//解析值
	GetKeyValue(ac_key_infor, &keyString, &lKeyValue);

	if (ac_key_infor->Type == REG_DWORD)
		KdPrint(("DWORD %d",lKeyValue ));
	else if (ac_key_infor->Type == REG_SZ)
		KdPrint(("UNICODE STRING %wZ", &keyString));

	//写注册表数据
	UNICODE_STRING writeRegName1, writeRegName2;
	RtlInitUnicodeString(&writeRegName1, L"test1");
	RtlInitUnicodeString(&writeRegName2, L"test2");

	PWCHAR pData1 = { L"test set value" };
	status = ZwSetValueKey(my_key, &writeRegName1, 0, REG_SZ, pData1, (wcslen(pData1)+1)*sizeof(WCHAR));
	if (!NT_SUCCESS(status))
	{
		KdPrint(("set key value1 error"));
		ZwClose(my_key);
		return;
	}

	ULONG ulValue = 0x1008;
	status = ZwSetValueKey(my_key, &writeRegName2, 0, REG_DWORD, &ulValue, sizeof(ulValue));
	if (!NT_SUCCESS(status))
	{
		KdPrint(("set key value2 error"));
		ZwClose(my_key);
		return;
	}

	ZwClose(my_key);
}

运行截图

在这里插入图片描述

4、线程使用

​ 内核模式下创建线程跟应用程序类似,创建线程函数,传参数,同步事件等,下面是一个例子可以传结构体参数,同步等待事件

线程函数部分


static KEVENT event;
typedef struct addParam
{
	ULONG param1;
	ULONG param2;
}ADD_PARAM;

void MyThread(PVOID param)
{
	ADD_PARAM * stParam = (ADD_PARAM*)param;
	ULONG ulRet;
	ulRet = stParam->param1 + stParam->param2;
	KdPrint(("%d + %d = %d", stParam->param1, stParam->param2, ulRet));

	KeSetEvent(&event, 0, TRUE);
	PsTerminateSystemThread(STATUS_SUCCESS);
}

线程创建代码

	//创建线程
	HANDLE hThread = NULL;
	KeInitializeEvent(&event, SynchronizationEvent, FALSE);

	ADD_PARAM stThreadData = {1,5};
	status = PsCreateSystemThread(&hThread, 0, NULL, NULL, NULL, MyThread, (PVOID)&stThreadData);
	if (!NT_SUCCESS(status))
	{
		KdPrint(("创建系统线程失败"));
	}
	ZwClose(hThread);
	KeWaitForSingleObject(&event, Executive, KernelMode, 0, 0);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

feng_blog6688

只需一个赞,谢谢你的鼓励

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值