gpt4 book ai didi

c++ - NtOpenKey 失败并显示 0xC0000034 - 如何解决这个问题?

转载 作者:可可西里 更新时间:2023-11-01 18:08:55 25 4
gpt4 key购买 nike

我正在使用 C++ 中的 VS 2013 创建一个用户模式 ​​CMD 应用程序,我正在尝试使用其中的 native 注册表编辑功能。我正在尝试使用“NtOpenKey”打开某些 key ,但它总是因“STATUS_OBJECT_NAME_NOT_FOUND”而失败,而且我确信“对象”就在它的位置,所以原因一定是在其他地方。我想使用 native 注册表 API,因为它们可以处理“隐藏的注册表项”- 查看 here获取更多信息。这是我的代码片段:

#include <Windows.h>
#include <tchar.h>

#include <wininet.h>

#include <iostream>

#include <stdio.h>
#include <string.h>
#include <assert.h>

#include "Nt_Funcs_declr.h" //here I have manually included the native api declarations as normally I'm denied to use them but they're exported in ntdll.dll so basically it is possible

#include <zlib.h>

//Obitain Steam folder path

wchar_t *GetSteamPathBuffer()
{
//Open the Sofware Steam registry

OBJECT_ATTRIBUTES objAttrs;

objAttrs.Length = sizeof(OBJECT_ATTRIBUTES);

objAttrs.RootDirectory = NULL;

wchar_t strRegSteam [] = L"\\Registry\\Machine\\SOFTWARE\\Valve";

UNICODE_STRING uStrTmp = { sizeof(strRegSteam), sizeof(strRegSteam), strRegSteam };

objAttrs.ObjectName = &uStrTmp;

objAttrs.Attributes = OBJ_CASE_INSENSITIVE; //

objAttrs.SecurityDescriptor = NULL;

objAttrs.SecurityQualityOfService = NULL;

HANDLE pKey;

ULONG tmmp = NtOpenKey(&pKey, GENERIC_READ, &objAttrs); //here it fails with 'STATUS_OBJECT_NAME_NOT_FOUND'
if(tmmp)
{
cout << "Error: " << GetLastError();
return NULL;
}

//....
}

和 Nt_Funcs_declr.h:

#pragma once


//NTDLL import declarations

#define STATUS_BUFFER_TOO_SMALL ((NTSTATUS)0xC0000023L)

//
// Unicode strings are counted 16-bit character strings. If they are
// NULL terminated, Length does not include trailing NULL.
//

typedef struct _UNICODE_STRING {
USHORT Length;
USHORT MaximumLength;
#ifdef MIDL_PASS
[size_is(MaximumLength / 2), length_is((Length) / 2)] USHORT * Buffer;
#else // MIDL_PASS
_Field_size_bytes_part_(MaximumLength, Length) PWCH Buffer;
#endif // MIDL_PASS
} UNICODE_STRING;
typedef UNICODE_STRING *PUNICODE_STRING;
typedef const UNICODE_STRING *PCUNICODE_STRING;

//
// Valid values for the Attributes field
//

#define OBJ_INHERIT 0x00000002L
#define OBJ_PERMANENT 0x00000010L
#define OBJ_EXCLUSIVE 0x00000020L
#define OBJ_CASE_INSENSITIVE 0x00000040L
#define OBJ_OPENIF 0x00000080L
#define OBJ_OPENLINK 0x00000100L
#define OBJ_KERNEL_HANDLE 0x00000200L
#define OBJ_FORCE_ACCESS_CHECK 0x00000400L
#define OBJ_VALID_ATTRIBUTES 0x000007F2L

typedef struct _OBJECT_ATTRIBUTES {
ULONG Length;
HANDLE RootDirectory;
PUNICODE_STRING ObjectName;
ULONG Attributes;
PVOID SecurityDescriptor; // Points to type SECURITY_DESCRIPTOR
PVOID SecurityQualityOfService; // Points to type SECURITY_QUALITY_OF_SERVICE
} OBJECT_ATTRIBUTES;
typedef OBJECT_ATTRIBUTES *POBJECT_ATTRIBUTES;
typedef CONST OBJECT_ATTRIBUTES *PCOBJECT_ATTRIBUTES;


extern "C"
NTSYSAPI
NTSTATUS
NTAPI
NtOpenKey(
_Out_ PHANDLE KeyHandle,
_In_ ACCESS_MASK DesiredAccess,
_In_ POBJECT_ATTRIBUTES ObjectAttributes
);

typedef enum _KEY_INFORMATION_CLASS {
KeyBasicInformation,
KeyNodeInformation,
KeyFullInformation,
KeyNameInformation,
KeyCachedInformation,
KeyFlagsInformation,
KeyVirtualizationInformation,
KeyHandleTagsInformation,
KeyTrustInformation,
MaxKeyInfoClass // MaxKeyInfoClass should always be the last enum
} KEY_INFORMATION_CLASS;

extern "C"
NTSYSAPI
NTSTATUS
NTAPI
NtQueryKey(
_In_ HANDLE KeyHandle,
_In_ KEY_INFORMATION_CLASS KeyInformationClass,
_Out_writes_bytes_opt_(Length) PVOID KeyInformation,
_In_ ULONG Length,
_Out_ PULONG ResultLength
);

typedef enum _KEY_VALUE_INFORMATION_CLASS {
KeyValueBasicInformation,
KeyValueFullInformation,
KeyValuePartialInformation,
KeyValueFullInformationAlign64,
KeyValuePartialInformationAlign64,
MaxKeyValueInfoClass // MaxKeyValueInfoClass should always be the last enum
} KEY_VALUE_INFORMATION_CLASS;

typedef struct _KEY_VALUE_PARTIAL_INFORMATION {
ULONG TitleIndex;
ULONG Type;
ULONG DataLength;
_Field_size_bytes_(DataLength) UCHAR Data[1]; // Variable size
} KEY_VALUE_PARTIAL_INFORMATION, *PKEY_VALUE_PARTIAL_INFORMATION;

extern "C"
NTSYSAPI
NTSTATUS
NTAPI
NtQueryValueKey(
_In_ HANDLE KeyHandle,
_In_ PUNICODE_STRING ValueName,
_In_ KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass,
_Out_writes_bytes_opt_(Length) PVOID KeyValueInformation,
_In_ ULONG Length,
_Out_ PULONG ResultLength
);

注意:这是出于教育目的,所以请不要问我为什么不使用 WIN32 API。

最佳答案

注意:不支持从用户模式使用内核 API。我强烈建议不要这样做,除非有令人信服的理由证明这是必要的。

问题是:

UNICODE_STRING uStrTmp = { sizeof(strRegSteam), sizeof(strRegSteam), strRegSteam };

来自documentation for UNICODE_STRING :

If the string is null-terminated, Length does not include the trailing null character.

所以你应该这样说

UNICODE_STRING uStrTmp = { sizeof(strRegSteam) - sizeof(wchar_t), 
sizeof(strRegSteam),
strRegSteam };

如所写,您的代码试图打开名为 L"Valve\0"的键,而不是名为 L"Valve"的键。


附录: 一直存在争议的是所谓的“隐藏”键(IMO 的一个不幸名称;键对 Win32 代码可见,它们根本不能被操纵)实际上是可能的,所以这里是创建一个的工作代码:

#include <Windows.h>

#include <stdio.h>

typedef struct _UNICODE_STRING {
USHORT Length;
USHORT MaximumLength;
PWCH Buffer;
} UNICODE_STRING;
typedef UNICODE_STRING *PUNICODE_STRING;
typedef const UNICODE_STRING *PCUNICODE_STRING;

typedef struct _OBJECT_ATTRIBUTES {
ULONG Length;
HANDLE RootDirectory;
PUNICODE_STRING ObjectName;
ULONG Attributes;
PVOID SecurityDescriptor;
PVOID SecurityQualityOfService;
} OBJECT_ATTRIBUTES;
typedef OBJECT_ATTRIBUTES *POBJECT_ATTRIBUTES;
typedef CONST OBJECT_ATTRIBUTES *PCOBJECT_ATTRIBUTES;

#define OBJ_CASE_INSENSITIVE 0x00000040L

#pragma comment(lib, "ntdll.lib")

__declspec(dllimport) NTSTATUS NTAPI NtCreateKey(
__out PHANDLE KeyHandle,
__in ACCESS_MASK DesiredAccess,
__in POBJECT_ATTRIBUTES ObjectAttributes,
__reserved ULONG TitleIndex,
__in_opt PUNICODE_STRING Class,
__in ULONG CreateOptions,
__out_opt PULONG Disposition
);

NTSYSAPI NTSTATUS NTAPI NtOpenKey(
__out PHANDLE KeyHandle,
__in ACCESS_MASK DesiredAccess,
__in POBJECT_ATTRIBUTES ObjectAttributes
);

NTSYSAPI NTSTATUS NTAPI NtDeleteKey(
__out HANDLE KeyHandle
);

int main(int argc, char ** argv)
{
HANDLE pKey;
NTSTATUS result;

OBJECT_ATTRIBUTES objAttrs;
wchar_t strSoftwareKey [] = L"\\Registry\\Machine\\SOFTWARE\\Test\0Key";

// If you use this string instead, the key functions normally, proving that the
// issue isn't because we're using UTF-16 rather than ANSI strings:
//
// wchar_t strSoftwareKey [] = L"\\Registry\\Machine\\SOFTWARE\\Test\u2D80Key";

UNICODE_STRING uStrSoftwareKey = {
sizeof(strSoftwareKey) - sizeof(wchar_t),
sizeof(strSoftwareKey),
strSoftwareKey };

objAttrs.Length = sizeof(OBJECT_ATTRIBUTES);
objAttrs.RootDirectory = NULL;
objAttrs.ObjectName = &uStrSoftwareKey;
objAttrs.Attributes = OBJ_CASE_INSENSITIVE;
objAttrs.SecurityDescriptor = NULL;
objAttrs.SecurityQualityOfService = NULL;

result = NtCreateKey(&pKey, GENERIC_ALL, &objAttrs, 0, NULL, 0, NULL);
if(result)
{
printf("NtCreateKey: %x\n", result);
return NULL;
}

#if 0 // enable this section to delete the key
// you won't be able to use regedit!
result = NtDeleteKey(pKey);
if(result)
{
printf("NtDeleteKey: %x\n", result);
return NULL;
}
#endif
}

至少在 Windows 7 中,这仍然有效。 (您需要一份 ntdll.lib 的拷贝,可从 DDK/WDK 获得,以便构建此代码。)

不要在生产代码或其他人的机器上这样做。

关于c++ - NtOpenKey 失败并显示 0xC0000034 - 如何解决这个问题?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25791542/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com