c++registryntdllnt-native-api

Creating a new registry key using the NtCreateKey() NTAPI function [NtOpenKey() function returns a NTSTATUS error value of -1073741772]


I am written the following code to create a new key in the registry but an NTSTATUS error value of -1073741772 is returned by the NtOpenKey() function when attempting to fetch the handle of the base key to create a new key.

typedef NTSTATUS(*LPCREATEKEY) (PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, ULONG, PUNICODE_STRING, ULONG, PULONG);
typedef NTSTATUS(*LPOPENKEY) (PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES);

HINSTANCE dllHandle = nullptr;
LPCREATEKEY createKey = nullptr;
LPOPENKEY openKey = nullptr;

NTSTATUS opStatus = NULL;
HANDLE key = nullptr, baseKey = nullptr;
OBJECT_ATTRIBUTES keyAttributes;
WCHAR keyStr[] = L"XYZ", baseKeyStr[] = L"\\REGISTRY\\MACHINE\\SOFTWARE";
UNICODE_STRING keyName, baseKeyName;
ULONG keyDispositionValue = NULL;

dllHandle = LoadLibrary(L"Ntdll.dll");
if (nullptr != dllHandle) {
    // Fetch the function to create a new registry key
    createKey = (LPCREATEKEY)GetProcAddress(dllHandle, "NtCreateKey");
    openKey = (LPOPENKEY)GetProcAddress(dllHandle, "NtOpenKey");
    if (nullptr != createKey && nullptr != openKey) {
        baseKeyName.Buffer = baseKeyStr;
        baseKeyName.Length = wcslen(baseKeyStr);
        baseKeyName.MaximumLength = wcslen(baseKeyStr);
        InitializeObjectAttributes(&keyAttributes, 
            &baseKeyName,
            OBJ_CASE_INSENSITIVE, 
            NULL, 
            NULL);
        opStatus = openKey(&baseKey, KEY_ALL_ACCESS, &keyAttributes);
        if (NT_SUCCESS(opStatus)) {
            keyName.Buffer = keyStr;
            keyName.Length = wcslen(keyStr);
            keyName.MaximumLength = wcslen(keyStr);
            InitializeObjectAttributes(&keyAttributes,
                &keyName,
                OBJ_CASE_INSENSITIVE,
                &baseKey,
                NULL);
            opStatus = createKey(
                &key,
                KEY_ALL_ACCESS,
                &keyAttributes,
                NULL,
                NULL,
                REG_OPTION_NON_VOLATILE,
                &keyDispositionValue);
            if (NT_SUCCESS(opStatus)) {
                cout << "Key successfully created!\n";
                //NtClose()
                if (!NT_SUCCESS(CloseHandle(key)))
                    cout << "Error closing created key handle\n";
            }
            if (!NT_SUCCESS(CloseHandle(baseKey)))
                cout << "Error closing base key handle\n";
        }
        else {
            if (NT_ERROR(opStatus))
                cout << "Error opening the base key (" << opStatus << ")\n";
        }
    }
    else {
        cout << "Could not fetch the functions from the DLL\n";
    }
    FreeLibrary(dllHandle);
}
else {
    cout << "Could not access Ntdll.dll\n";
}

Thanks in advance.


Solution

  • This is how a new key is created in the registry using the NTAPI functions.

    #include <winternl.h>
    
    typedef NTSTATUS(*LPCREATEKEY) (PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, ULONG, PUNICODE_STRING, ULONG, PULONG);
    
    HINSTANCE dll = nullptr;
    LPCREATEKEY ntCreateKey = nullptr;
    HANDLE createdKey = nullptr;
    UNICODE_STRING newKeyName;
    OBJECT_ATTRIBUTES attributes;
    WCHAR name[] = L"\\REGISTRY\\MACHINE\\SOFTWARE\\NewKeyName";
    NTSTATUS opStatus = NULL;
    ULONG keyDispositionValue = NULL;
    dll = LoadLibrary(L"Ntdll.dll");
    if (nullptr != dll) {
        ntCreateKey = (LPCREATEKEY) GetProcAddress(dll, "NtCreateKey");
        if (nullptr != ntCreateKey) {
            newKeyName.Buffer = name;
            newKeyName.Length = sizeof(name) - sizeof(WCHAR);
            newKeyName.MaximumLength = wcslen(name);
            InitializeObjectAttributes(&attributes, &newKeyName, OBJ_CASE_INSENSITIVE, NULL, NULL);
            opStatus = ntCreateKey(&createdKey, KEY_ALL_ACCESS, &attributes, 0, NULL, REG_OPTION_NON_VOLATILE, &keyDispositionValue);
            if (NT_SUCCESS(opStatus)) {
                if (keyDispositionValue == REG_CREATED_NEW_KEY)
                    cout << "New key created!\n";
                else if (keyDispositionValue == REG_OPENED_EXISTING_KEY)
                    cout << "Key already exists!\n";
                if (!CloseHandle(createdKey))
                    cout << "Error closing handle!";
            }
            else {
                printf("%X", opStatus);
            }
        }
        else {
            cout << "Could not fetch NtCreateKey() from Ntdll.dll\n";
        }
        FreeLibrary(dll);
    }
    else {
        cout << "Could not access Ntdll.dll\n";
    }