运行 使用 RtlCreateUserProcess 的程序只能偶尔工作

Running programs using RtlCreateUserProcess only works occasionally

免责声明:这个问题似乎被否决了,因为我应该使用普通的 Win32 API(CreateProcess、ShellExecute)。我知道这些 APIs 并且我知道 RtlCreateUserProcess 不应该被直接调用。但是,原生 API 是一个与安全性非常相关的主题,这就是我研究它的原因。

我正在尝试 运行 使用从 ntdll.dll 导出的函数 RtlCreateUserProcess 在 Windows 上编写程序。我的代码适用于 运行 calc.exe,但是,在尝试 运行 notepad.exe 之后,我收到一条错误消息 The ordinal 345 could not be located in dynamic link library "C:\Windows\SysWOW64\notepad.exe"。当尝试 运行 其他程序时,它会显示各种类似的消息,总是与某些序号或 DLL 丢失有关。

我的示例代码如下所示:

#include <windows.h>
#include <iostream>
#include <winternl.h>

typedef struct _SECTION_IMAGE_INFORMATION {

    PVOID                   EntryPoint;
    ULONG                   StackZeroBits;
    ULONG                   StackReserved;
    ULONG                   StackCommit;
    ULONG                   ImageSubsystem;
    WORD                    SubSystemVersionLow;
    WORD                    SubSystemVersionHigh;
    ULONG                   Unknown1;
    ULONG                   ImageCharacteristics;
    ULONG                   ImageMachineType;
    ULONG                   Unknown2[3];

} SECTION_IMAGE_INFORMATION, * PSECTION_IMAGE_INFORMATION;

typedef struct _RTL_USER_PROCESS_INFORMATION {

    ULONG                   Size;
    HANDLE                  ProcessHandle;
    HANDLE                  ThreadHandle;
    CLIENT_ID               ClientId;
    SECTION_IMAGE_INFORMATION ImageInformation;

} RTL_USER_PROCESS_INFORMATION, * PRTL_USER_PROCESS_INFORMATION;

typedef VOID(NTAPI* Func1)(PUNICODE_STRING DestinationString, __drv_aliasesMem PCWSTR SourceString);
typedef NTSTATUS(NTAPI* Func2)(OUT PRTL_USER_PROCESS_PARAMETERS* pProcessParameters, IN PUNICODE_STRING ImagePathName, IN PUNICODE_STRING DllPath OPTIONAL, IN PUNICODE_STRING CurrentDirectory OPTIONAL, IN PUNICODE_STRING CommandLine OPTIONAL, IN PVOID Environment OPTIONAL, IN PUNICODE_STRING WindowTitle OPTIONAL, IN PUNICODE_STRING DesktopInfo OPTIONAL, IN PUNICODE_STRING ShellInfo OPTIONAL, IN PUNICODE_STRING RuntimeData OPTIONAL);
typedef NTSTATUS(NTAPI* Func3)(PUNICODE_STRING NtImagePathName, ULONG Attributes, PRTL_USER_PROCESS_PARAMETERS ProcessParameters, PSECURITY_DESCRIPTOR ProcessSecurityDescriptor, PSECURITY_DESCRIPTOR ThreadSecurityDescriptor, HANDLE ParentProcess, BOOLEAN InheritHandles, HANDLE DebugPort, HANDLE ExceptionPort, PRTL_USER_PROCESS_INFORMATION ProcessInformation);

int main()
{

    UNICODE_STRING str;

    PRTL_USER_PROCESS_PARAMETERS processparameters; 
    RTL_USER_PROCESS_INFORMATION processinformation = { 0 }; 

    Func1 RtlInitUnicodeString = (Func1)GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "RtlInitUnicodeString");
    Func2 RtlCreateProcessParameters = (Func2)GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "RtlCreateProcessParameters");
    Func3 RtlCreateUserProcess = (Func3)GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "RtlCreateUserProcess");

    RtlInitUnicodeString(&str, L"\??\C:\Windows\SysWOW64\notepad.exe"); //Starting calc.exe works, notepad.exe does not.
    RtlCreateProcessParameters(&processparameters, &str, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);

    NTSTATUS works = RtlCreateUserProcess(&str, OBJ_CASE_INSENSITIVE, processparameters, NULL, NULL, NULL, FALSE, NULL, NULL, &processinformation);
    
    if (NT_SUCCESS(works)) {
        ResumeThread(processinformation.ThreadHandle);
        //Started application crashes at this point + the error message gets shown
    }
    else {
        std::cout << "Failed" << std::endl;
    }

    return 0;
}

不幸的是,没有太多关于使用此功能的信息,所以如果能回答如何正确使用此功能,我将不胜感激。

CreateProcess 在创建新进程后做更多的工作,特别是它根据 exe 清单(BasepConstructSxsCreateProcessMessage + CsrClientCallServer)为新进程创建激活上下文,因为新进程有初始激活上下文,存储在 PEBSystemDefaultActivationContextDataActivationContextData)中,但在通过纯调用 RtlCreateUserProcess this 创建的过程中字段为空 (0)。结果,您的进程从 system32(版本 5.82)加载了 ComCtl32.dll 并激活了记事本上下文 - 6+ 版本。

The ordinal 345 could not be located in dynamic link library

确实在 ComCtl32.DLL pre 6 版本 (5.82) 中。 345 - 这是 TaskDialogIndirect api 仅存在于 ComCtl32.DLL 版本 6+ .但是你的进程负载 5.82.. -

所以 CreateProcess 不是比 RtlCreateUserProcessNtCreateUserProcess 薄 shell,而是大而复杂 api。如果可能的话,它很难发挥作用,直接实施