首页
社区
课程
招聘
[旧帖] ZwQueryValueKey 返回的 buffer 如何处理 0.00雪花
发表于: 2016-3-30 15:57 4640

[旧帖] ZwQueryValueKey 返回的 buffer 如何处理 0.00雪花

2016-3-30 15:57
4640
在看注册表操作的章节,遇到一个问题是已经正常取到数据,但是打印数据不完整。请看下红色字体部分的内容。原因是什么呢?

现在返回的内容只有一部分,不完整:



#include <ntddk.h>

NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
{
	NTSTATUS status;
	HANDLE KeyHandle = NULL;
	OBJECT_ATTRIBUTES objAttr = { 0 };
	UNICODE_STRING KeyPath = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion");
	UNICODE_STRING ValueName = RTL_CONSTANT_STRING(L"RegisteredOwner");
	KEY_VALUE_PARTIAL_INFORMATION KeyValueInformation;
	PKEY_VALUE_PARTIAL_INFORMATION pKeyValueInformation;
	ULONG ResultLength;

	InitializeObjectAttributes(&objAttr, &KeyPath, OBJ_CASE_INSENSITIVE, NULL, NULL);

	status = ZwOpenKey(&KeyHandle, KEY_READ, &objAttr);
	if (!NT_SUCCESS(status))
	{
		return STATUS_UNSUCCESSFUL;
	}

	// 试探性的调用,主要根据返回值得到实际 buffer 的大小
	status = ZwQueryValueKey(
		KeyHandle,
		&ValueName,
		KeyValuePartialInformation,
		&KeyValueInformation,
		sizeof(KEY_VALUE_PARTIAL_INFORMATION),
		&ResultLength
		);

	// 如果说实际需要的长度比 Length 要大,那么返回 STATUS_BUFFER_ OVERFLOW
	// 或者 STATUS_BUFFER_TOO_SMALL。如果成功读出了全部数据,那么返回 STATUS_SUCCESS。
	// 其他的情况,返回一个错误码。
	if (!NT_SUCCESS(status) && 
		status != STATUS_BUFFER_OVERFLOW && 
		status != STATUS_BUFFER_TOO_SMALL)
	{
		ZwClose(KeyHandle);
	}

	// 根据实际返回所需的 buffer 大小分配空间
	pKeyValueInformation = (KEY_VALUE_PARTIAL_INFORMATION*)
		ExAllocatePool(NonPagedPool, ResultLength);
	if (NULL == pKeyValueInformation)
	{
		status = STATUS_INSUFFICIENT_RESOURCES;
		ZwClose(KeyHandle);
	}

	// 继续读取
	status = ZwQueryValueKey(
		KeyHandle,
		&ValueName,
		KeyValuePartialInformation,
		pKeyValueInformation,
		sizeof(KEY_VALUE_PARTIAL_INFORMATION),
		&ResultLength
		);

	[COLOR="Red"]UNICODE_STRING ResultString;
	RtlInitUnicodeString(&ResultString, (PCWSTR)pKeyValueInformation->Data);

	KdPrint(("pKeyValueInformation.Data = %S\r\n", pKeyValueInformation->Data));
	KdPrint(("ResultString = %wZ, Length = %ld\r\n", &ResultString, ResultString.Length));[/COLOR]

	ExFreePool((VOID*)pKeyValueInformation);
	ZwClose(KeyHandle);

	return STATUS_UNSUCCESSFUL;
}

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

上传的附件:
收藏
免费 0
支持
分享
最新回复 (3)
雪    币: 69
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
已经解决,红色位置为修改的地方,参见:ftp://ftp.lantronix.com/priv/cpr/Lantronix/4.3/4.3.0.0/Debug/DriverSource/registry.c

#include <ntddk.h>

NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
{
	NTSTATUS status;
	HANDLE KeyHandle = NULL;
	OBJECT_ATTRIBUTES objAttr = { 0 };
	UNICODE_STRING KeyPath = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion");
	UNICODE_STRING ValueName = RTL_CONSTANT_STRING(L"RegisteredOwner");
	PKEY_VALUE_PARTIAL_INFORMATION pKeyValueInformation;
	ULONG ResultLength;

	InitializeObjectAttributes(&objAttr, &KeyPath, OBJ_CASE_INSENSITIVE, NULL, NULL);

	status = ZwOpenKey(&KeyHandle, KEY_READ, &objAttr);
	if (!NT_SUCCESS(status))
	{
		return STATUS_UNSUCCESSFUL;
	}

	/* 写注册表代码
	UNICODE_STRING ValueName = RTL_CONSTANT_STRING(L"DriverWrited");
	PWCHAR Value = L"My Test Value";

	status = ZwSetValueKey(KeyHandle, &ValueName, 0, REG_SZ, Value,
		(wcslen(Value) + 1) * sizeof(WCHAR));
	if (!NT_SUCCESS(status))
	{
		ZwClose(KeyHandle);
		return STATUS_UNSUCCESSFUL;
	}*/

	// 试探性的调用,主要根据返回值得到实际 buffer 的大小
	status = ZwQueryValueKey(
		KeyHandle,					// key句柄
		&ValueName,					// 要获取的键名
		KeyValuePartialInformation,	// 获取类型和值
[COLOR="red"]		NULL,						// 首次 buffer 传 NULL 为了其失败返回实际需要空间
		0,							// buffer 长度传 0,同上目的[/COLOR]
		&ResultLength				// 用来返回实际需要空间的变量
		);

	// 如果说实际需要的长度比 Length 要大,那么返回 STATUS_BUFFER_ OVERFLOW
	// 或者 STATUS_BUFFER_TOO_SMALL。如果成功读出了全部数据,那么返回 STATUS_SUCCESS。
	// 其他的情况,返回一个错误码。
	if (!NT_SUCCESS(status) && 
		status != STATUS_BUFFER_OVERFLOW && 
		status != STATUS_BUFFER_TOO_SMALL)
	{
		ZwClose(KeyHandle);
	}

	// 根据实际返回所需的 buffer 大小分配空间
	pKeyValueInformation = (KEY_VALUE_PARTIAL_INFORMATION*)
		ExAllocatePool(NonPagedPool, ResultLength);
	if (NULL == pKeyValueInformation)
	{
		status = STATUS_INSUFFICIENT_RESOURCES;
		ZwClose(KeyHandle);
	}

	// 继续读取
	status = ZwQueryValueKey(
		KeyHandle,
		&ValueName,
		KeyValuePartialInformation,
[COLOR="Red"]		pKeyValueInformation,		// 传递已经分配了空间的 buffer
		ResultLength,				// 传递上一次 ZwQueryValueKey 返回的实际大小值[/COLOR]
		&ResultLength
		);

	UNICODE_STRING ResultString;
	RtlInitUnicodeString(&ResultString, (PCWSTR)pKeyValueInformation->Data);
	ResultString.Length = (USHORT)pKeyValueInformation->DataLength;
	ResultString.MaximumLength = (USHORT)pKeyValueInformation->DataLength;

	KdPrint(("pKeyValueInformation.Data = %S\r\n", pKeyValueInformation->Data));
	KdPrint(("ResultString = %wZ, Length = %ld\r\n", &ResultString, ResultString.Length));

	ExFreePool((VOID*)pKeyValueInformation);

	ZwClose(KeyHandle);

	return STATUS_UNSUCCESSFUL;
}
2016-3-31 00:53
0
雪    币: 1392
活跃值: (4867)
能力值: ( LV13,RANK:240 )
在线值:
发帖
回帖
粉丝
3
内核里面unicode不要直接 printf他的data .data不一定0结尾的,拷贝到某个地方再打印吧。好久没有看驱动了。
2016-3-31 21:34
0
雪    币: 69
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
好的,谢谢指点。这个在书中有看到,它并不是 \0 结尾的字符串,而是结构中的 Length 描述的长度,这个是我忽略了。
2016-4-4 16:18
0
游客
登录 | 注册 方可回帖
返回
//