#include <ntifs.h>
#include <windef.h>
/*
Zw层次的注册表操作很简单。
但是做与不做还是有点区别的。
made by correy
made at 2014.07.24
homepage:http://correy.webs.com
*/
NTSTATUS ZwEnumerateKeyEx(IN UNICODE_STRING * Name)
/*
显示一个注册表的键下的:子键,名字,类型,数据。
注意:没有递归显示。
*/
{
NTSTATUS Status = STATUS_UNSUCCESSFUL;
OBJECT_ATTRIBUTES ObjectAttributes;
HANDLE KeyHandle;
PKEY_FULL_INFORMATION pfi;
ULONG ResultLength;
ULONG i = 0;
InitializeObjectAttributes(&ObjectAttributes, Name, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);
Status = ZwOpenKey(&KeyHandle, KEY_READ, &ObjectAttributes);
if( !NT_SUCCESS( Status ) )
{
return Status;
}
/*
注意ZwQueryKey的第一个参数。
The KeyHandle passed to ZwQueryKey must have been opened with KEY_QUERY_VALUE access.
This is accomplished by passing KEY_QUERY_VALUE, KEY_READ, or KEY_ALL_ACCESS as the DesiredAccess parameter to ZwCreateKey or ZwOpenKey.
*/
// 第一次调用是为了获取需要的长度
Status = ZwQueryKey(KeyHandle, KeyFullInformation, NULL, 0, &ResultLength);
if( !NT_SUCCESS( Status ) )
{
if (Status == STATUS_BUFFER_TOO_SMALL || Status == STATUS_BUFFER_OVERFLOW) //STATUS_BUFFER_OVERFLOW这个情况应该不会发生在这种情况下。
{
//在下面申请内存。
}
else
{
ZwClose(KeyHandle);
return Status;
}
}
//ResultLength += MAX_PATH ;
//ResultLength *= 2;//多申请一半。
pfi = (PKEY_FULL_INFORMATION)ExAllocatePool(NonPagedPool, ResultLength);
if (pfi == NULL)
{
//If ExAllocatePool returns NULL, the caller should return the NTSTATUS value STATUS_INSUFFICIENT_RESOURCES or should delay processing to another point in time.
Status = STATUS_INSUFFICIENT_RESOURCES;
ZwClose(KeyHandle);
return Status;
}
// 第二次调用是为了获取数据
Status = ZwQueryKey(KeyHandle, KeyFullInformation, pfi, ResultLength, &ResultLength);//少了赋值。这等低级的错误。
if( !NT_SUCCESS( Status ) )
{
ExFreePool(pfi);
ZwClose(KeyHandle);
return Status;
}
//枚举子键。
for (i = 0; i < pfi->SubKeys; i++)
{
PKEY_BASIC_INFORMATION pbi;
UNICODE_STRING us;
// 获取第i个子项的长度
Status = ZwEnumerateKey(KeyHandle, i, KeyBasicInformation, NULL, 0, &ResultLength);
if( !NT_SUCCESS( Status ) )
{
if (Status == STATUS_BUFFER_TOO_SMALL || Status == STATUS_BUFFER_OVERFLOW) //STATUS_BUFFER_OVERFLOW这个情况应该不会发生在这种情况下。
{
//在下面申请内存。
}
else
{
break;
}
}
pbi = (PKEY_BASIC_INFORMATION)ExAllocatePool(NonPagedPool, ResultLength);
if (pbi == NULL)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
break;
}
// 获取第i个子项的数据
Status = ZwEnumerateKey(KeyHandle, i, KeyBasicInformation, pbi, ResultLength, &ResultLength);
if( !NT_SUCCESS( Status ) )
{
ExFreePool(pbi);
break;
}
us.Buffer = pbi->Name;
us.Length = (USHORT)pbi->NameLength;
us.MaximumLength = us.Length;
DbgPrint("subkey:%wZ\n", &us);
/*
在这里组合字符串,可以考虑递归枚举。
*/
ExFreePool(pbi);// 释放内存
}
//枚举名字,类型,数据。
for (i = 0; i < pfi->Values; i++) //可以考虑用ZwQueryValueKey获取数量。MSDN关于这个成员的解释是:The number of value entries for this key.
{
PKEY_VALUE_BASIC_INFORMATION pkvbi;
UNICODE_STRING us;
PKEY_VALUE_PARTIAL_INFORMATION pkvpi;
UNICODE_STRING data;
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// 获取名字及类型。
Status = ZwEnumerateValueKey(KeyHandle, i, KeyValueBasicInformation, NULL, 0, &ResultLength);
if( !NT_SUCCESS( Status ) )
{
if (Status == STATUS_BUFFER_TOO_SMALL || Status == STATUS_BUFFER_OVERFLOW) //STATUS_BUFFER_OVERFLOW这个情况应该不会发生在这种情况下。
{
//在下面申请内存。
}
else
{
break;
}
}
pkvbi = (PKEY_VALUE_BASIC_INFORMATION)ExAllocatePool(NonPagedPool, ResultLength);
if (pkvbi == NULL)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
break;
}
Status = ZwEnumerateValueKey(KeyHandle, i, KeyValueBasicInformation, pkvbi, ResultLength, &ResultLength);
if( !NT_SUCCESS( Status ) )
{
ExFreePool(pkvbi);
break;
}
us.Buffer = pkvbi->Name;
us.Length = (USHORT)pkvbi->NameLength;
us.MaximumLength = us.Length;
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// 获取数据
Status = ZwEnumerateValueKey(KeyHandle, i, KeyValuePartialInformation, NULL, 0, &ResultLength);
if( !NT_SUCCESS( Status ) )
{
if (Status == STATUS_BUFFER_TOO_SMALL || Status == STATUS_BUFFER_OVERFLOW) //STATUS_BUFFER_OVERFLOW这个情况应该不会发生在这种情况下。
{
//在下面申请内存。
}
else
{
ExFreePool(pkvbi);
break;
}
}
pkvpi = (PKEY_VALUE_PARTIAL_INFORMATION)ExAllocatePool(NonPagedPool, ResultLength);
if (pkvpi == NULL)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
ExFreePool(pkvbi);
break;
}
Status = ZwEnumerateValueKey(KeyHandle, i, KeyValuePartialInformation, pkvpi, ResultLength, &ResultLength);
if( !NT_SUCCESS( Status ) )
{
ExFreePool(pkvpi);
ExFreePool(pkvbi);
break;
}
data.Buffer = (PWCH)pkvpi->Data;//有的数据可能无法显示。
data.Length = (USHORT)pkvpi->DataLength;
data.MaximumLength = data.Length;
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
DbgPrint("name:%wZ,type:%d,data:%wZ\n", &us, pkvbi->Type, &data);
ExFreePool(pkvbi);// 释放内存
ExFreePool(pkvpi);
}
ExFreePool(pfi);
ZwClose(KeyHandle);
return Status;
}
DRIVER_UNLOAD Unload;
VOID Unload(__in PDRIVER_OBJECT DriverObject)
{
}
DRIVER_INITIALIZE DriverEntry;
NTSTATUS DriverEntry( __in struct _DRIVER_OBJECT * DriverObject, __in PUNICODE_STRING RegistryPath)
{
NTSTATUS status = STATUS_UNSUCCESSFUL;
UNICODE_STRING test = RTL_CONSTANT_STRING(L"\\REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\Control");//\\Session Manager
KdBreakPoint();
DriverObject->DriverUnload = Unload;
status = ZwEnumerateKeyEx(&test);
if( !NT_SUCCESS( status ) )
{
DbgPrint("ZwEnumerateKeyEx fail with 0x%x\n", status);
}
return status;//STATUS_SUCCESS
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#include <ntifs.h>
#include <windef.h>
#define TAG 'tset' //test
NTSTATUS ZwCopyKey(IN UNICODE_STRING * Name, IN UNICODE_STRING * Name2)
/*
复制一个注册表的键下的:子键,名字,类型,数据。
注意:
1.没有递归复制。
2.没有复制(安全)属性。
3.没有对参数的有效性进行检查。字符串的末尾不要带L'\\'.
4.确认使用前这两个路径是存在的。
5.更多的缺陷,请你补充纠正。更多的功能等待你的发挥。
*/
{
NTSTATUS Status = STATUS_UNSUCCESSFUL;
OBJECT_ATTRIBUTES ObjectAttributes;
HANDLE KeyHandle;
HANDLE KeyHandle3;
PKEY_FULL_INFORMATION pfi;
ULONG ResultLength;
ULONG i = 0;
InitializeObjectAttributes(&ObjectAttributes, Name, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);
Status = ZwOpenKey(&KeyHandle, KEY_ALL_ACCESS, &ObjectAttributes);
if( !NT_SUCCESS( Status ) )
{
return Status;
}
/*
注意ZwQueryKey的第一个参数。
The KeyHandle passed to ZwQueryKey must have been opened with KEY_QUERY_VALUE access.
This is accomplished by passing KEY_QUERY_VALUE, KEY_READ, or KEY_ALL_ACCESS as the DesiredAccess parameter to ZwCreateKey or ZwOpenKey.
*/
// 第一次调用是为了获取需要的长度
Status = ZwQueryKey(KeyHandle, KeyFullInformation, NULL, 0, &ResultLength);
if( !NT_SUCCESS( Status ) )
{
if (Status == STATUS_BUFFER_TOO_SMALL || Status == STATUS_BUFFER_OVERFLOW) //STATUS_BUFFER_OVERFLOW这个情况应该不会发生在这种情况下。
{
//在下面申请内存。
}
else
{
ZwClose(KeyHandle);
return Status;
}
}
//ResultLength += MAX_PATH ;
//ResultLength *= 2;//多申请一半。
pfi = (PKEY_FULL_INFORMATION)ExAllocatePool(NonPagedPool, ResultLength);
if (pfi == NULL)
{
//If ExAllocatePool returns NULL, the caller should return the NTSTATUS value STATUS_INSUFFICIENT_RESOURCES or should delay processing to another point in time.
Status = STATUS_INSUFFICIENT_RESOURCES;
ZwClose(KeyHandle);
return Status;
}
// 第二次调用是为了获取数据
Status = ZwQueryKey(KeyHandle, KeyFullInformation, pfi, ResultLength, &ResultLength);//少了赋值。这等低级的错误。
if( !NT_SUCCESS( Status ) )
{
ExFreePool(pfi);
ZwClose(KeyHandle);
return Status;
}
//枚举子键。
for (i = 0; i < pfi->SubKeys; i++)
{
PKEY_BASIC_INFORMATION pbi;
UNICODE_STRING us;
UNICODE_STRING new_key ;
OBJECT_ATTRIBUTES ob;
HANDLE KeyHandle2 = 0;
PUNICODE_STRING Class = NULL;
ULONG Disposition;
// 获取第i个子项的长度
Status = ZwEnumerateKey(KeyHandle, i, KeyBasicInformation, NULL, 0, &ResultLength);
if( !NT_SUCCESS( Status ) )
{
if (Status == STATUS_BUFFER_TOO_SMALL || Status == STATUS_BUFFER_OVERFLOW) //STATUS_BUFFER_OVERFLOW这个情况应该不会发生在这种情况下。
{
//在下面申请内存。
}
else
{
break;
}
}
pbi = (PKEY_BASIC_INFORMATION)ExAllocatePool(NonPagedPool, ResultLength);
if (pbi == NULL)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
break;
}
// 获取第i个子项的数据
Status = ZwEnumerateKey(KeyHandle, i, KeyBasicInformation, pbi, ResultLength, &ResultLength);
if( !NT_SUCCESS( Status ) )
{
ExFreePool(pbi);
break;
}
us.Buffer = pbi->Name;
us.Length = (USHORT)pbi->NameLength;
us.MaximumLength = us.Length;
DbgPrint("subkey:%wZ\n", &us);
//开始新建。
new_key.Buffer = (wchar_t *)ExAllocatePoolWithTag(NonPagedPool, MAX_PATH, TAG);
if (new_key.Buffer == NULL) {
ExFreePool(pbi);
Status = STATUS_INSUFFICIENT_RESOURCES;
break;
}
RtlZeroMemory(new_key.Buffer, MAX_PATH);
RtlInitEmptyUnicodeString(&new_key, new_key.Buffer,MAX_PATH);
RtlCopyUnicodeString(&new_key,Name2);
Status = RtlAppendUnicodeToString(&new_key, L"\\");
if (!NT_SUCCESS (Status)) {
ExFreePool(new_key.Buffer);
ExFreePool(pbi);
Status = STATUS_INSUFFICIENT_RESOURCES;
break;
}
Status = RtlAppendUnicodeStringToString(&new_key, &us);
if (!NT_SUCCESS (Status)) {
ExFreePool(new_key.Buffer);
ExFreePool(pbi);
Status = STATUS_INSUFFICIENT_RESOURCES;
break;
}
InitializeObjectAttributes(&ob, &new_key, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 0, 0);
Status = ZwCreateKey(&KeyHandle2, KEY_WRITE, &ob, 0, Class, REG_OPTION_NON_VOLATILE, &Disposition);//KEY_ALL_ACCESS KEY_READ
if (!NT_SUCCESS (Status))
{
//如果子键已经存在,返回正确。
ExFreePool(new_key.Buffer);
ExFreePool(pbi);
Status = STATUS_INSUFFICIENT_RESOURCES;
break;
}
else
{
if (KeyHandle2)//断言FileHandle不等于0也不是无效的句柄。
{
Status = ZwClose(KeyHandle2);
if (!NT_SUCCESS (Status))
{
KdPrint(("ZwClose fail with 0x%x.\n", Status));
}
}
}
/*
在这里组合字符串,可以考虑递归。
*/
ExFreePool(pbi);// 释放内存
ExFreePool(new_key.Buffer);
}
//处理上面失败的情况。主要是for 循环。
if( !NT_SUCCESS( Status ) )
{
ExFreePool(pfi);
ZwClose(KeyHandle);
return Status;
}
InitializeObjectAttributes(&ObjectAttributes, Name2, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);
Status = ZwOpenKey(&KeyHandle3, KEY_ALL_ACCESS, &ObjectAttributes);
if( !NT_SUCCESS( Status ) )
{
ExFreePool(pfi);
ZwClose(KeyHandle);
return Status;
}
//枚举名字,类型,数据。
for (i = 0; i < pfi->Values; i++) //可以考虑用ZwQueryValueKey获取数量。MSDN关于这个成员的解释是:The number of value entries for this key.
{
PKEY_VALUE_BASIC_INFORMATION pkvbi;
UNICODE_STRING us;
PKEY_VALUE_PARTIAL_INFORMATION pkvpi;
UNICODE_STRING data;
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// 获取名字及类型。
Status = ZwEnumerateValueKey(KeyHandle, i, KeyValueBasicInformation, NULL, 0, &ResultLength);
if( !NT_SUCCESS( Status ) )
{
if (Status == STATUS_BUFFER_TOO_SMALL || Status == STATUS_BUFFER_OVERFLOW) //STATUS_BUFFER_OVERFLOW这个情况应该不会发生在这种情况下。
{
//在下面申请内存。
}
else
{
break;
}
}
pkvbi = (PKEY_VALUE_BASIC_INFORMATION)ExAllocatePool(NonPagedPool, ResultLength);
if (pkvbi == NULL)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
break;
}
Status = ZwEnumerateValueKey(KeyHandle, i, KeyValueBasicInformation, pkvbi, ResultLength, &ResultLength);
if( !NT_SUCCESS( Status ) )
{
ExFreePool(pkvbi);
break;
}
us.Buffer = pkvbi->Name;
us.Length = (USHORT)pkvbi->NameLength;
us.MaximumLength = us.Length;
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// 获取数据
Status = ZwEnumerateValueKey(KeyHandle, i, KeyValuePartialInformation, NULL, 0, &ResultLength);
if( !NT_SUCCESS( Status ) )
{
if (Status == STATUS_BUFFER_TOO_SMALL || Status == STATUS_BUFFER_OVERFLOW) //STATUS_BUFFER_OVERFLOW这个情况应该不会发生在这种情况下。
{
//在下面申请内存。
}
else
{
ExFreePool(pkvbi);
break;
}
}
pkvpi = (PKEY_VALUE_PARTIAL_INFORMATION)ExAllocatePool(NonPagedPool, ResultLength);
if (pkvpi == NULL)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
ExFreePool(pkvbi);
break;
}
Status = ZwEnumerateValueKey(KeyHandle, i, KeyValuePartialInformation, pkvpi, ResultLength, &ResultLength);
if( !NT_SUCCESS( Status ) )
{
ExFreePool(pkvpi);
ExFreePool(pkvbi);
break;
}
data.Buffer = (PWCH)pkvpi->Data;//有的数据可能无法显示。
data.Length = (USHORT)pkvpi->DataLength;
data.MaximumLength = data.Length;
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Status = ZwSetValueKey(KeyHandle3, &us, 0, pkvbi->Type, data.Buffer, data.Length);
if( !NT_SUCCESS( Status ) ) //如果句柄的权限是KEY_READ这里成功,但是实际是没有成功的。
{
ExFreePool(pkvpi);
ExFreePool(pkvbi);
break;
}
DbgPrint("name:%wZ,type:%d,data:%wZ\n", &us, pkvbi->Type, &data);
ExFreePool(pkvbi);// 释放内存
ExFreePool(pkvpi);
}
ExFreePool(pfi);
ZwClose(KeyHandle);
ZwClose(KeyHandle3);
return Status;
}
DRIVER_UNLOAD Unload;
VOID Unload(__in PDRIVER_OBJECT DriverObject)
{
}
DRIVER_INITIALIZE DriverEntry;
NTSTATUS DriverEntry( __in struct _DRIVER_OBJECT * DriverObject, __in PUNICODE_STRING RegistryPath)
{
NTSTATUS status = STATUS_UNSUCCESSFUL;
UNICODE_STRING test = RTL_CONSTANT_STRING(L"\\REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Session Manager");
UNICODE_STRING test2 = RTL_CONSTANT_STRING(L"\\REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Session Manager2");
KdBreakPoint();
DriverObject->DriverUnload = Unload;
status = ZwCopyKey(&test, &test2);
if( !NT_SUCCESS( status ) )
{
DbgPrint("ZwEnumerateKeyEx fail with 0x%x\n", status);
}
return status;//STATUS_SUCCESS
}
2014年7月24日星期四
内核中的注册表操作
订阅:
博文评论 (Atom)
没有评论:
发表评论