2014-09-11 1 views
7

C++에서 VS 2013을 사용하는 사용자 모드 CMD 응용 프로그램을 만들고 있는데 여기에 기본 레지스트리 편집 기능을 사용하려고합니다. 나는 'NtOpenKey'로 특정 키를 열려고하지만 'STATUS_OBJECT_NAME_NOT_FOUND'로 항상 실패하고 그 이유가 어딘가에 있어야하므로 '객체'가 그 장소에 있다고 확신합니다. '숨겨진 레지스트리 키'를 처리 할 수 ​​있기 때문에 기본 레지스트리 API를 사용하고 싶습니다. 자세한 내용은 here을 참조하십시오.NtOpenKey가 0xC0000034와 함께 실패합니다. 어떻게 해결할 수 있습니까?

#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를 사용하지 않는 이유는 그렇게 묻지 마십시오 교육 prupose을 위해입니다.

+5

"개체 이름을 찾을 수 없습니다"물론 물론 * 매우 * 일반적인 문제. 왜 지구상에서 이런 일을하는지, RegOpenKeyEx()에 아무 것도 추가하지 않고, 불행과 혼란을 혼자서 옮기는 것입니다. –

+1

그것은 교육적인 목적을위한 것입니다. 더 잘 처리하도록 도와주세요. – AnArrayOfFunctions

+1

이것은 다른 사람을 교육하지 않으며 유해합니다. 이것은 포럼이 아닙니다. –

답변

19

NB : 사용자 모드에서 커널 API를 사용하여이지원되지 않는입니다. 필요한 이유가 아닌 한 그렇게하지 말 것을 강력히 권장합니다. documentation for UNICODE_STRING에서

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

:

가 여기에 문제의 문자열이 null로 끝나는 경우

, 길이는 후행 null 문자를 포함하지 않습니다.

그래서 당신은 당신의 코드가 키라는 이름의 L "밸브 \ 0"대신 키 이름 L "밸브"를 열려고 시도했다,

서면으로
UNICODE_STRING uStrTmp = { sizeof(strRegSteam) - sizeof(wchar_t), 
          sizeof(strRegSteam), 
          strRegSteam }; 

같은 말을한다.


부록 : 소위 "숨겨진"키 (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부터는 적어도 여전히 작동합니다. (당신은이 코드를 구축하기 위해, DDK/WDK에서 사용할 수 ntdll.lib의 사본을해야합니다.)

생산 코드 또는 다른 사람의 컴퓨터에서이 작업을 수행하지 마십시오.

+4

제쳐두고, 많은 작업을 통해 지원되는 방식으로이 작업을 수행 할 수 있습니다. 드라이버를 만듭니다. 드라이버에서이 API가 지원됩니다. 사용자 공간에서 드라이버로 통신을 중계하고이 작업을 수행하십시오. – Yakk

관련 문제