调用 NtCreateProcessEx 无一例外地失败

Calling NtCreateProcessEx fails without exception

我想调用 NtCreateProcessEx,但我没有收到任何异常和错误,也没有任何反应。我也不想使用 CreateProcess。我的意图是从具有此特定功能的文件创建并运行一个进程。

到目前为止我已经尝试过:

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

整个互联网上都没有关于此特定功能的文档和示例。我可以为 NtCreateFile 做一些与此类似的事情,但这是我对 NtCreateProcessEx 最接近的尝试,但没有运气。

我使用 Visual Studio 2019 和 windows 10 1909。

这些是我尝试过的一些资源:

  1. NtCreateProcess(Ex) - Can I have a child process inherit the parents address space while running under a different process name?
  2. http://www.rohitab.com/discuss/topic/40191-ntcreateuserprocess/
  3. https://github.com/Microwave89/createuserprocess/blob/master/createuserprocess/main.c
  4. http://www.rohitab.com/discuss/topic/42229-start-a-process-using-ntcreateprocessex-usermode/
  5. https://hshrzd.wordpress.com/2017/12/18/process-doppelganging-a-new-way-to-impersonate-a-process/

首先,第三个参数是指向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
    );

要使用的示例(删除错误检查):

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