#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)
没有评论:
发表评论