2014-09-11 16 views
7

Tôi đang tạo ứng dụng CMD chế độ người dùng bằng VS 2013 trong C++ và tôi đang cố gắng sử dụng các chức năng chỉnh sửa đăng ký gốc trong đó. Tôi đang cố gắng để mở khóa nhất định với 'NtOpenKey' nhưng nó luôn luôn thất bại với 'STATUS_OBJECT_NAME_NOT_FOUND' và tôi chắc chắn rằng 'đối tượng' là ở nơi nó vì vậy lý do phải ở một nơi khác. Tôi muốn sử dụng API đăng ký gốc bởi vì họ có thể xử lý 'Khoá đăng ký ẩn' - xem here để biết thêm thông tin. Dưới đây là một đoạn mã của tôi:NtOpenKey không thành công với 0xC0000034 - cách sửa lỗi này?

#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; 
    } 

//.... 
} 

Và 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 
); 

LƯU Ý: Đó là cho prupose giáo dục vì vậy xin đừng hỏi tôi tại sao tôi không sử dụng Win32 API.

+5

"không tìm thấy tên đối tượng", điều đó tất nhiên là * rất * phổ biến. Tại sao trên trái đất là bạn làm điều này, nó không thêm bất cứ điều gì để RegOpenKeyEx(), chỉ porting đau khổ và tự gây ra sự nhầm lẫn. –

+1

Đó là cho prupose giáo dục - vì vậy hãy cố gắng tốt hơn để giúp tôi xử lý này. – AnArrayOfFunctions

+1

Điều này không giáo dục bất kỳ ai, nó có hại. Đây không phải là một diễn đàn. –

Trả lời

19

NB: sử dụng API hạt nhân từ chế độ người dùng là không được hỗ trợ. Tôi khuyên bạn không nên làm như vậy, trừ khi có một lý do thuyết phục tại sao nó là cần thiết.

Dưới đây là các vấn đề:

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

Từ documentation for UNICODE_STRING:

Nếu chuỗi là null-terminated, Chiều dài không bao gồm các ký tự null trailing.

Vì vậy, bạn nên nói cái gì đó như

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

Theo văn bản, mã của bạn đã cố gắng để mở một khóa có tên L "Van \ 0" thay vì khóa có tên L "Van".


Phụ Lục: nó đã được tranh cãi cho dù cái gọi là phím "ẩn" (một cái tên không may IMO; các phím có thể nhìn thấy mã Win32, họ chỉ đơn giản là không thể được thao tác) là thực sự tốt , vì vậy, đây là mã hoạt động để tạo một tài khoản:

#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 
} 

Kể từ Windows 7, ít nhất, tính năng này vẫn hoạt động. (Bạn sẽ cần một bản sao của ntdll.lib, có sẵn từ DDK/WDK, để xây dựng mã này.)

Xin đừng không làm điều này trong mã sản xuất hoặc trên máy của người khác.

+4

Là một sang một bên, với rất nhiều công việc bạn có thể làm điều này một cách được hỗ trợ. Tạo trình điều khiển. Từ trình điều khiển, API này được hỗ trợ. Chuyển tiếp thông tin liên lạc của bạn từ không gian người dùng đến trình điều khiển của bạn và thực hiện công việc này. – Yakk

Các vấn đề liên quan