Calling NtCreateProcessEx fails without exception - c++

I want to call NtCreateProcessEx, But i get no exception and error and nothing happens. Also i don't want to use CreateProcess. My intention is to create and run a process from a file with this specific function.
This what i have tried so far:
#include <Windows.h>
#include <bcrypt.h>
#include "winternl.h"
#pragma comment(lib, "ntdll")
NTSTATUS NTAPI NtCreateProcessEx(
OUT HANDLE ProcessHandle,
IN ACCESS_MASK DesiredAccess,
IN OBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
IN HANDLE ParentProcess,
IN BOOLEAN InheritObjectTable,
IN HANDLE SectionHandle OPTIONAL,
IN HANDLE DebugPort OPTIONAL,
IN HANDLE ExceptionPort OPTIONAL,
IN BOOLEAN InJob);
int main()
{
const HANDLE ph = nullptr;
OBJECT_ATTRIBUTES oa;
UNICODE_STRING fileName;
RtlInitUnicodeString(&fileName, PCWSTR(L"\\??\\C:\\Windows\\System32\\calc.exe"));
(&oa)->Length = sizeof(OBJECT_ATTRIBUTES);
(&oa)->RootDirectory = nullptr;
(&oa)->Attributes = 0x00000040L;
(&oa)->ObjectName = &fileName;
(&oa)->SecurityDescriptor = nullptr;
(&oa)->SecurityQualityOfService = nullptr;;
NtCreateProcessEx(ph, PROCESS_ALL_ACCESS, oa, nullptr, FALSE, nullptr, nullptr, nullptr, FALSE);
return 0;
}
There is no document and example on whole internet about this specific function. I am able to do something somewhat similar to this for NtCreateFile, But this is my closest try for NtCreateProcessEx and no luck.
I work with Visual Studio 2019 and windows 10 1909.
These are some resources that i tried:
NtCreateProcess(Ex) - Can I have a child process inherit the parents address space while running under a different process name?
http://www.rohitab.com/discuss/topic/40191-ntcreateuserprocess/
https://github.com/Microwave89/createuserprocess/blob/master/createuserprocess/main.c
http://www.rohitab.com/discuss/topic/42229-start-a-process-using-ntcreateprocessex-usermode/
https://hshrzd.wordpress.com/2017/12/18/process-doppelganging-a-new-way-to-impersonate-a-process/

First of all, the 3rd parameter is a pointer to the OBJECT_ATTRIBUTES:
typedef NTSTATUS(NTAPI* fpNtCreateProcessEx)
(
PHANDLE ProcessHandle,
ACCESS_MASK DesiredAccess,
POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
HANDLE ParentProcess,
ULONG Flags,
HANDLE SectionHandle OPTIONAL,
HANDLE DebugPort OPTIONAL,
HANDLE ExceptionPort OPTIONAL,
BOOLEAN InJob
);
A sample to use(remove error checking):
#include <windows.h>
#include <iostream>
using namespace std;
#define NtCurrentProcess() ( (HANDLE)(LONG_PTR) -1 )
typedef struct _LSA_UNICODE_STRING {
USHORT Length;
USHORT MaximumLength;
PWSTR Buffer;
} LSA_UNICODE_STRING, * PLSA_UNICODE_STRING, UNICODE_STRING, * PUNICODE_STRING;
typedef struct _OBJECT_ATTRIBUTES {
ULONG Length;
HANDLE RootDirectory;
PUNICODE_STRING ObjectName;
ULONG Attributes;
PVOID SecurityDescriptor;
PVOID SecurityQualityOfService;
} OBJECT_ATTRIBUTES, * POBJECT_ATTRIBUTES;
typedef NTSTATUS(NTAPI* fpNtCreateProcessEx)
(
PHANDLE ProcessHandle,
ACCESS_MASK DesiredAccess,
POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
HANDLE ParentProcess,
ULONG Flags,
HANDLE SectionHandle OPTIONAL,
HANDLE DebugPort OPTIONAL,
HANDLE ExceptionPort OPTIONAL,
BOOLEAN InJob
);
typedef NTSTATUS(NTAPI* fpNtCreateTransaction)
(
PHANDLE TransactionHandle,
ACCESS_MASK DesiredAccess,
POBJECT_ATTRIBUTES ObjectAttributes,
LPGUID Uow,
HANDLE TmHandle,
ULONG CreateOptions,
ULONG IsolationLevel,
ULONG IsolationFlags,
PLARGE_INTEGER Timeout,
PUNICODE_STRING Description
);
typedef NTSTATUS (NTAPI *fpNtCreateSection)
(
PHANDLE SectionHandle,
ACCESS_MASK DesiredAccess,
POBJECT_ATTRIBUTES ObjectAttributes,
PLARGE_INTEGER MaximumSize,
ULONG SectionPageProtection,
ULONG AllocationAttributes,
HANDLE FileHandle
);
typedef NTSTATUS (NTAPI *fpNtClose)
(
HANDLE Handle
);
#define PS_INHERIT_HANDLES 4
int main()
{
HANDLE hProcess;
OBJECT_ATTRIBUTES objattr;
UNICODE_STRING objname;
NTSTATUS status;
WCHAR wstrObjName[MAX_PATH];
lstrcpyW(wstrObjName, L"C:\\test.exe");
HINSTANCE hinst = LoadLibrary(L"ntdll.dll");
fpNtCreateProcessEx _NtCreateProcessEx = (fpNtCreateProcessEx)GetProcAddress(hinst, "NtCreateProcessEx");
fpNtCreateTransaction _NtCreateTransaction = (fpNtCreateTransaction)GetProcAddress(hinst, "NtCreateTransaction");
fpNtCreateSection _NtCreateSection = (fpNtCreateSection)GetProcAddress(hinst, "NtCreateSection");
fpNtClose _NtClose = (fpNtClose)GetProcAddress(hinst, "NtClose");
// Initialize ObjectName UNICODE_STRING
objname.Buffer = wstrObjName;
objname.Length = wcslen(wstrObjName) * sizeof(WCHAR); // Length in bytes of string, without null terminator
objname.MaximumLength = MAX_PATH * sizeof(WCHAR);
// Initialize OBJECT_ATTRIBUTES
objattr.Length = sizeof(OBJECT_ATTRIBUTES);
objattr.Attributes = 0x00000040L; //OBJ_CASE_INSENSITIVE
objattr.ObjectName = NULL;
objattr.RootDirectory = NULL;
objattr.SecurityDescriptor = NULL;
objattr.SecurityQualityOfService = NULL;
HANDLE hTransaction = NULL;
status = _NtCreateTransaction(&hTransaction,
TRANSACTION_ALL_ACCESS,
&objattr,
NULL,
NULL,
0,
0,
0,
NULL,
NULL);
HANDLE hTransactedFile = CreateFileTransacted(wstrObjName,
GENERIC_WRITE | GENERIC_READ,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL,
hTransaction,
NULL,
NULL);
HANDLE hSection = NULL;
status = _NtCreateSection(&hSection,
SECTION_ALL_ACCESS,
NULL,
0,
PAGE_READONLY,
SEC_IMAGE,
hTransactedFile);
status = _NtCreateProcessEx(&hProcess, PROCESS_ALL_ACCESS, NULL, NtCurrentProcess(), PS_INHERIT_HANDLES, hSection, NULL, NULL, false);
DWORD pid = GetProcessId(hProcess);
printf("Pid = %d\n", pid);
CloseHandle(hTransactedFile);
_NtClose(hTransaction);
_NtClose(hSection);
_NtClose(hProcess);
return 0;
}

Do i have to change a specific flag or use another standard function to resume the process state?
You must create thread. New process doesn't have any thread. You must allocate memory for thread and then call ZwCreateThread. For details, see Garry Nebeth book for windows 2000.

Related

How to get logical drive handle using NtCreatefile

I am trying call IOCTL IOCTL_DISK_GET_DRIVE_LAYOUT_EX and I need the logical drive handle for it.
CreateFileW works fine but I need to achieve it using nt function like NtCreatefile.
It seems like I messed with arguments but I can't get it. I have not find any examples of opening logical drive with nt function as well
This one works:
auto handle = CreateFileW(
L"\\\\.\\D:", //
GENERIC_READ | GENERIC_WRITE, // no access to the drive
FILE_SHARE_READ | FILE_SHARE_WRITE, // share mode
NULL, // default security attributes
OPEN_EXISTING, // disposition
0, // file attributes
0 ); // do not copy file attributes
This gets me the error 1073741811 (STATUS_INVALID_PARAMETER)
include <Windows.h>
typedef ULONG( __stdcall* pNtReadFile )(
IN HANDLE FileHandle,
IN HANDLE Event OPTIONAL,
IN PVOID ApcRoutine OPTIONAL,
IN PVOID ApcContext OPTIONAL,
OUT PVOID IoStatusBlock,
OUT PVOID Buffer,
IN ULONG Length,
IN PLARGE_INTEGER ByteOffset OPTIONAL,
IN PULONG Key OPTIONAL );
typedef struct _UNICODE_STRING {
USHORT Length, MaximumLength;
PWCH Buffer;
} UNICODE_STRING, *PUNICODE_STRING;
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;
#define InitializeObjectAttributes( p, n, a, r, s ) { \
(p)->Length = sizeof( OBJECT_ATTRIBUTES ); \
(p)->RootDirectory = r; \
(p)->Attributes = a; \
(p)->ObjectName = n; \
(p)->SecurityDescriptor = s; \
(p)->SecurityQualityOfService = NULL; \
}
typedef void( __stdcall* RtlInitUnicodeString )(
PUNICODE_STRING DestinationString,
PCWSTR SourceString );
typedef ULONG( __stdcall* pNtCreateFile )(
PHANDLE FileHandle,
ULONG DesiredAccess,
PVOID ObjectAttributes,
PVOID IoStatusBlock,
PLARGE_INTEGER AllocationSize,
ULONG FileAttributes,
ULONG ShareAccess,
ULONG CreateDisposition,
ULONG CreateOptions,
PVOID EaBuffer,
ULONG EaLength
);
RtlInitUnicodeString RtlInitUnicodeStringStruct = (RtlInitUnicodeString)GetProcAddress( GetModuleHandleW( L"ntdll.dll" ), "RtlInitUnicodeString" );
pNtCreateFile NtCreatefile = (pNtCreateFile)GetProcAddress( GetModuleHandleW( L"ntdll.dll" ), "NtCreateFile" );
typedef struct _IO_STATUS_BLOCK
{
union
{
NTSTATUS Status;
VOID* Pointer;
};
ULONG_PTR Information;
} IO_STATUS_BLOCK, * PIO_STATUS_BLOCK;
#define FILE_DIRECTORY_FILE 0x00000001
#define FILE_SYNCHRONOUS_IO_NONALERT 0x00000020
#define FILE_NON_DIRECTORY_FILE 0x00000040
#define FILE_OPEN 0x00000001
#define OBJ_CASE_INSENSITIVE 0x00000040L
int main()
{
// Set up the parameters for the NtCreateFile call
UNICODE_STRING fileName{ 0 };
std::wstring path = L"\\\\.\\D:";
RtlInitUnicodeStringStruct( &fileName, path.c_str() );
OBJECT_ATTRIBUTES attributes{0};
InitializeObjectAttributes( &attributes, &fileName, OBJ_CASE_INSENSITIVE, NULL, NULL );
IO_STATUS_BLOCK ioStatusBlock;
HANDLE hFile;
// Call NtCreateFile to open the file
NTSTATUS status = NtCreatefile(
&hFile,
GENERIC_READ | GENERIC_WRITE,
&attributes,
&ioStatusBlock,
NULL,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ | FILE_SHARE_WRITE,
FILE_OPEN,
FILE_SYNCHRONOUS_IO_NONALERT,
NULL, 0 );
// Check the return status
if ( status != 0 )
{
std::cout << "err: " << status << std::endl;
return 0;
}
}

NtResumeThread after NtCreateUserProcess

I created the process through NtCreateUserProcess. This was successful and returned STATUS_SUCCESS.
This created process attempted to run through NtResumeThread in a suspended state.
But immediately the process was turned off.
In the same code, NtCreateUserProcess was replaced with CreateProcessW. NtResumeThread was used to create the same suspended process to normal process, which worked well.
How can I resume a process created with NtCreateUserProcess?
Edit: CreateProcess (Working) -> NtCreateUserProcess (Nop..) means process created with wrong code. Got it. I created process with following code.
HANDLE hProcess;
HANDLE hThread;
PS_CREATE_INFO procInfo;
PS_ATTRIBUTE_LIST attrList;
RTL_USER_PROCESS_PARAMETERS10 userParams;
RtlSecureZeroMemory(&userParams, sizeof(RTL_USER_PROCESS_PARAMETERS10));
RtlSecureZeroMemory(&attrList, sizeof(PS_ATTRIBUTE_LIST));
RtlSecureZeroMemory(&procInfo, sizeof(PS_CREATE_INFO));
userParams.Length = sizeof(RTL_USER_PROCESS_PARAMETERS10);
userParams.MaximumLength = sizeof(RTL_USER_PROCESS_PARAMETERS10);
attrList.TotalLength = sizeof(PS_ATTRIBUTE_LIST) - sizeof(PS_ATTRIBUTE);
procInfo.Size = sizeof(PS_CREATE_INFO);
userParams.Environment = (WCHAR *) data;
userParams.EnvironmentSize = sizeof(data);
userParams.EnvironmentVersion = 0;
userParams.Flags = 0x01;
userParams.ShowWindowFlags = SW_HIDE;
userParams.ImagePathName = filename2;
userParams.CommandLine = command;
attrList.Attributes[0].Attribute = PsAttributeValue(PsAttributeImageName, FALSE, TRUE, FALSE);
attrList.Attributes[0].Size = filename.Length;
attrList.Attributes[0].Value = (ULONG_PTR) filename.Buffer;
NTSTATUS status = INLINE_SYSCALL(NtCreateUserProcess)(&hProcess, &hThread, MAXIMUM_ALLOWED, MAXIMUM_ALLOWED,
NULL, NULL, 0, THREAD_CREATE_FLAGS_CREATE_SUSPENDED,
reinterpret_cast<_RTL_USER_PROCESS_PARAMETERS *>(&userParams), &procInfo, &attrList);
if (!NT_SUCCESS(status)) {
printf("%x\n", status);
return 1;
}
And using following struct.
typedef struct _RTL_USER_PROCESS_PARAMETERS10
{
ULONG MaximumLength; //6c0
ULONG Length;//6c0
ULONG Flags;//0
ULONG DebugFlags;//0
HANDLE ConsoleHandle;//NULL
ULONG ConsoleFlags;//0
HANDLE StandardInput;//NULL
HANDLE StandardOutput;//NULL
HANDLE StandardError;//NULL
CURDIR CurrentDirectory;
UNICODE_STRING DllPath;
UNICODE_STRING ImagePathName;
UNICODE_STRING CommandLine;
PWSTR Environment;
ULONG StartingX;
ULONG StartingY;
ULONG CountX;
ULONG CountY;
ULONG CountCharsX;
ULONG CountCharsY;
ULONG FillAttribute;
ULONG WindowFlags;
ULONG ShowWindowFlags;
UNICODE_STRING WindowTitle;
UNICODE_STRING DesktopInfo;
UNICODE_STRING ShellInfo;
UNICODE_STRING RuntimeData;
RTL_DRIVE_LETTER_CURDIR CurrentDirectories[32];
#if (NTDDI_VERSION >= NTDDI_LONGHORN)
SIZE_T EnvironmentSize;
#endif
#if (NTDDI_VERSION >= NTDDI_WIN7)
SIZE_T EnvironmentVersion;
#endif
} RTL_USER_PROCESS_PARAMETERS10, *PRTL_USER_PROCESS_PARAMETERS10;
I cant find any error in this process creation.
Sorry for bad english.. I'm not a native speaker so there can be some wrong grammer, graceless manner.

Resume a process created by NtCreateProcessEx

Here im trying to create and run calc but the process is created in suspended state. This is the main code:
#include <Windows.h>
#include <iostream>
using namespace std;
#define NtCurrentProcess() ( (HANDLE)(LONG_PTR) -1 )
typedef struct _LSA_UNICODE_STRING
{
USHORT Length;
USHORT MaximumLength;
PWSTR Buffer;
} LSA_UNICODE_STRING, * PLSA_UNICODE_STRING, UNICODE_STRING, * PUNICODE_STRING;
typedef struct _OBJECT_ATTRIBUTES
{
ULONG Length;
HANDLE RootDirectory;
PUNICODE_STRING ObjectName;
ULONG Attributes;
PVOID SecurityDescriptor;
PVOID SecurityQualityOfService;
} OBJECT_ATTRIBUTES, * POBJECT_ATTRIBUTES;
typedef NTSTATUS(NTAPI* fpNtCreateProcessEx)
(
PHANDLE ProcessHandle,
ACCESS_MASK DesiredAccess,
POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
HANDLE ParentProcess,
ULONG Flags,
HANDLE SectionHandle OPTIONAL,
HANDLE DebugPort OPTIONAL,
HANDLE ExceptionPort OPTIONAL,
BOOLEAN InJob
);
typedef NTSTATUS(NTAPI* fpNtCreateTransaction)
(
PHANDLE TransactionHandle,
ACCESS_MASK DesiredAccess,
POBJECT_ATTRIBUTES ObjectAttributes,
LPGUID Uow,
HANDLE TmHandle,
ULONG CreateOptions,
ULONG IsolationLevel,
ULONG IsolationFlags,
PLARGE_INTEGER Timeout,
PUNICODE_STRING Description
);
typedef NTSTATUS(NTAPI* fpNtCreateSection)
(
PHANDLE SectionHandle,
ACCESS_MASK DesiredAccess,
POBJECT_ATTRIBUTES ObjectAttributes,
PLARGE_INTEGER MaximumSize,
ULONG SectionPageProtection,
ULONG AllocationAttributes,
HANDLE FileHandle
);
typedef NTSTATUS(NTAPI* fpNtClose)
(
HANDLE Handle
);
typedef LONG(NTAPI* fpNtResumeProcess)
(
HANDLE ProcessHandle
);
typedef LONG(NTAPI* fpNtResumeThread)
(
HANDLE ProcessHandle
);
#define PS_INHERIT_HANDLES 4
int main()
{
HANDLE hProcess;
OBJECT_ATTRIBUTES objattr;
WCHAR wstrObjName[MAX_PATH];
lstrcpyW(wstrObjName, L"C:\\Windows\\System32\\calc.exe");
const HINSTANCE hinst = LoadLibrary(L"ntdll.dll");
const auto _NtCreateTransaction = fpNtCreateTransaction(GetProcAddress(hinst, "NtCreateTransaction"));
const auto _NtCreateSection = fpNtCreateSection(GetProcAddress(hinst, "NtCreateSection"));
const auto _NtCreateProcessEx = fpNtCreateProcessEx(GetProcAddress(hinst, "NtCreateProcessEx"));
const auto _NtResumeProcess = fpNtResumeProcess(GetProcAddress(hinst, "NtResumeProcess"));
const auto _NtResumeThread = fpNtResumeThread(GetProcAddress(hinst, "NtResumeThread"));
const auto _NtClose = fpNtClose(GetProcAddress(hinst, "NtClose"));
wcslen(wstrObjName) * sizeof(WCHAR);
objattr.Length = sizeof(OBJECT_ATTRIBUTES);
objattr.Attributes = 0x00000040L;
objattr.ObjectName = nullptr;
objattr.RootDirectory = nullptr;
objattr.SecurityDescriptor = nullptr;
objattr.SecurityQualityOfService = nullptr;
HANDLE hTransaction = nullptr;
_NtCreateTransaction(&hTransaction, TRANSACTION_ALL_ACCESS, &objattr, nullptr, nullptr, 0, 0, 0, nullptr, nullptr);
const HANDLE h_transacted_file = CreateFileTransacted(wstrObjName, GENERIC_WRITE | GENERIC_READ, 0, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr, hTransaction, nullptr, nullptr);
HANDLE hSection = nullptr;
_NtCreateSection(&hSection, SECTION_ALL_ACCESS, nullptr, nullptr, PAGE_READONLY, SEC_IMAGE, h_transacted_file);
_NtCreateProcessEx(&hProcess, PROCESS_ALL_ACCESS, nullptr, NtCurrentProcess(), PS_INHERIT_HANDLES, hSection, nullptr, nullptr, false);
const DWORD pid = GetProcessId(hProcess);
ResumeThread(hProcess);
printf("Pid = %d\n", pid);
CloseHandle(h_transacted_file);
_NtClose(hTransaction);
_NtClose(hSection);
_NtClose(hProcess);
return 0;
}
This is my ProcessExplorer:
What i have tried:
Changing #define PS_INHERIT_HANDLES 4 to something else like 2, 1 or 8 and no luck.
Tried to resume the process by ResumeThread(hProcess);, ResumeProcess(hProcess); or _NtResumeProcess(hProcess); but doesn't work.
Tried to manually resume the process with ProcessExplorer and Process goes back to suspended state immediately.
Changing my target file to something else.
My question is: Why i cannot resume this created process? How can i fix this?
In case you didn't figure it out, you need to create a thread using NtCreateThreadEx

NtConnectPort error

I try to call the function NtConnectPort - I create a section and then forward this section to NtConnectPort .
I get a running error from the function NtConnectPort. The return value is c000000d - The parameter is incorrect.
I don't understand why. Any ideas?
The code:
HANDLE hSection=0;
LARGE_INTEGER SecSize;
SecSize.LowPart=0x10000;
SecSize.HighPart=0x0;
if(NtCreateSection(&hSection, SECTION_ALL_ACCESS, NULL, &SecSize, PAGE_READWRITE,SEC_COMMIT ,NULL))
{
printf("couldn't create a section");
}
HANDLE hPort;
LPC_SECTION_OWNER_MEMORY sectionInfo;
LPC_SECTION_MEMORY mapInfo;
byte ConnectDataBuffer[0x100];
DWORD Size = sizeof(ConnectDataBuffer);
UNICODE_STRING uStr;
WCHAR * uString=L"\\SmApiPort";
DWORD maxSize;
SECURITY_QUALITY_OF_SERVICE qos;
for (int i=0 ; i < 0x100 ; i++)
{
ConnectDataBuffer[i]=0x0;
}
memset(&sectionInfo, 0, sizeof(sectionInfo));
memset(&mapInfo, 0, sizeof(mapInfo));
sectionInfo.Length = 24;
sectionInfo.SectionHandle =hSection;
sectionInfo.ViewSize = 0x10000;
mapInfo.Length = 0x0C;
uStr.Length = wcslen(uString)*2;
uStr.MaximumLength = wcslen(uString)*2+2;
uStr.Buffer =uString;
NTSTATUS res = NtConnectPort(&hPort,&uStr,&qos,(LPC_SECTION_OWNER_MEMORY*)&sectionInfo,(LPC_SECTION_MEMORY*)&mapInfo,&maxSize,(DWORD*)ConnectDataBuffer,&Size);
if (res)
{
printf("Could not connect to LPC port.\n -%x", res);
return 1;
}
typedef struct _LPC_SECTION_OWNER_MEMORY {
ULONG Length;
HANDLE SectionHandle;
ULONG OffsetInSection;
ULONG ViewSize;
PVOID ViewBase;
PVOID OtherSideViewBase;
} LPC_SECTION_OWNER_MEMORY, *PLPC_SECTION_OWNER_MEMORY;
typedef struct _LPC_SECTION_MEMORY {
ULONG Length;
ULONG ViewSize;
PVOID ViewBase;
} LPC_SECTION_MEMORY, *PLPC_SECTION_MEMORY;
NTSYSAPI NTSTATUS NTAPI NtConnectPort(
OUT PHANDLE PortHandle,
IN PUNICODE_STRING PortName,
IN PSECURITY_QUALITY_OF_SERVICE SecurityQos,
//IN OUT PPORT_VIEW ClientView OPTIONAL,
IN OUT PLPC_SECTION_OWNER_MEMORY ClientSharedMemory,
OUT PLPC_SECTION_MEMORY ServerSharedMemory,
//OUT PREMOTE_PORT_VIEW ServerView OPTIONAL,
OUT PULONG MaxMessageLength OPTIONAL,
IN OUT PVOID ConnectionInformation OPTIONAL,
IN OUT PULONG ConnectionInformationLength OPTIONAL
);
NTSYSAPI NTSTATUS NTAPI ZwConnectPort(
OUT PHANDLE PortHandle,
IN PUNICODE_STRING PortName,
IN PSECURITY_QUALITY_OF_SERVICE SecurityQos,
IN OUT PLPC_SECTION_OWNER_MEMORY ClientSharedMemory,
OUT PLPC_SECTION_MEMORY ServerSharedMemory,
//IN OUT int int1,
//IN OUT PPORT_VIEW ClientView OPTIONAL,
//OUT PREMOTE_PORT_VIEW ServerView OPTIONAL,
OUT PULONG MaxMessageLength OPTIONAL,
IN OUT PVOID ConnectionInformation OPTIONAL,
IN OUT PULONG ConnectionInformationLength OPTIONAL
);
You're not initializing the qos variable (http://msdn.microsoft.com/en-us/library/windows/desktop/aa379574(v=vs.85).aspx)
SecurityQos - Points to a structure that specifies the level
of impersonation available to the port listener.

NtOpenKey fails with 0xC0000034 - how to fix this?

I'm creating a user-mode CMD app using VS 2013 in C++ and I'm trying to use the native registry editing functions in it. I'm trying to open certain key with 'NtOpenKey' but it always fails with 'STATUS_OBJECT_NAME_NOT_FOUND' and I'm sure that the 'object' is in it's place so the reason must be somewhere else. I want to use the native registry API's because they can handle 'Hidden Registry Keys' - look here for more info. Here is a snippet of my code:
#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;
}
//....
}
And 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
);
NOTE: It's for educational prupose so please don't ask me why I don't use WIN32 API.
NB: using the kernel API from user mode is unsupported. I strongly recommend against doing so, unless there is a compelling reason why it is necessary.
Here's the problem:
UNICODE_STRING uStrTmp = { sizeof(strRegSteam), sizeof(strRegSteam), strRegSteam };
From the documentation for UNICODE_STRING:
If the string is null-terminated, Length does not include the trailing null character.
So you should be saying something like
UNICODE_STRING uStrTmp = { sizeof(strRegSteam) - sizeof(wchar_t),
sizeof(strRegSteam),
strRegSteam };
As written, your code was attempting to open a key named L"Valve\0" instead of the key named L"Valve".
Addendum: it has been disputed whether so-called "hidden" keys (an unfortunate name IMO; the keys are visible to Win32 code, they simply can't be manipulated) are actually possible, so here's working code to create one:
#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
}
As of Windows 7, at least, this still works. (You'll need a copy of ntdll.lib, available from the DDK/WDK, in order to build this code.)
Please do not do this in production code or on other people's machines.