【问题标题】:Calling NtCreateProcessEx fails without exception调用 NtCreateProcessEx 失败无异常
【发布时间】:2020-03-28 09:18:16
【问题描述】:

我想打电话给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/

【问题讨论】:

  • 你用错了NtCreateProcessExObjectAttributes 不能指向任何文件。并且必须为 0。相反,您需要从可执行文件创建部分并将其传递到位SectionHandle。还需要做更多的工作 - 在进程中创建线程,将进程附加到 csrss,分配环境变量等。CreateProcess 完成所有这些。
  • @RbMm 所以我不能只打电话给NtCreateProcessEx,我必须重新定义它。但我想知道为什么NtCreateFile 更容易使用。你有任何例子或资源来帮助我完成这个吗?
  • 如果没有记录,你为什么要使用它?
  • @user207421 它没有记录但不是非法的(只是不支持)。在某些在线课程和隔离日中,尝试使用无证 Api 是很常见的事情 :)。你也应该责怪成千上万的开发人员知道一个未记录的函数。
  • 你可以好好研究一下。我会先在网上找到调用它的源代码。

标签: c++ winapi system-calls ntdll


【解决方案1】:

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

【讨论】:

  • 这太好了,只有一个问题:进程在suspended 状态下创建,所以没有 cpu 时间,我是否必须更改特定标志或使用其他标准函数来恢复进程状态?
猜你喜欢
  • 2012-10-18
  • 1970-01-01
  • 1970-01-01
  • 2016-09-20
  • 1970-01-01
  • 2022-01-24
  • 2016-08-15
  • 2013-07-18
  • 2016-11-29
相关资源
最近更新 更多