NtCreateUserProcess 初探与玩法
字数 1478 2025-08-25 22:58:29

NtCreateUserProcess 深入解析与实战应用

1. 基本概念与背景

NtCreateUserProcess 是 Windows 系统底层用于创建用户模式进程的系统调用。相比传统的 CreateProcess API,它提供了更底层的进程创建控制能力。

1.1 历史演变

  • 在 XP 时代,创建进程需要执行四个系统调用:

    • NtOpenFile
    • NtCreateSection
    • NtCreateProcess(Ex)
    • NtCreateThread(Ex)
  • 现代 Windows 系统中,NtCreateUserProcess 整合了这些功能,只需一个系统调用即可创建新进程

1.2 与 CreateProcess 的关系

CreateProcess 是用户态 API,其内部调用链为:

kernel32.dll!CreateProcessW 
→ CreateProcessInternalW 
→ ntdll.dll!NtCreateUserProcess

2. NtCreateUserProcess 函数原型与参数详解

NTSTATUS NTAPI NtCreateUserProcess(
    _Out_ PHANDLE ProcessHandle,
    _Out_ PHANDLE ThreadHandle,
    _In_ ACCESS_MASK ProcessDesiredAccess,
    _In_ ACCESS_MASK ThreadDesiredAccess,
    _In_opt_ POBJECT_ATTRIBUTES ProcessObjectAttributes,
    _In_opt_ POBJECT_ATTRIBUTES ThreadObjectAttributes,
    _In_ ULONG ProcessFlags,
    _In_ ULONG ThreadFlags,
    _In_ PRTL_USER_PROCESS_PARAMETERS ProcessParameters,
    _Inout_ PPS_CREATE_INFO CreateInfo,
    _In_ PPS_ATTRIBUTE_LIST AttributeList
);

2.1 关键参数解析

2.1.1 句柄与访问权限

  • ProcessHandleThreadHandle:存储创建的进程和线程句柄
  • ProcessDesiredAccessThreadDesiredAccess:进程和线程的访问权限
    • 常用值:PROCESS_ALL_ACCESSTHREAD_ALL_ACCESS

2.1.2 对象属性

  • ProcessObjectAttributesThreadObjectAttributes:指向 OBJECT_ATTRIBUTES 结构
typedef struct _OBJECT_ATTRIBUTES {
  ULONG           Length;
  HANDLE          RootDirectory;
  PUNICODE_STRING ObjectName;
  ULONG           Attributes;
  PVOID           SecurityDescriptor;
  PVOID           SecurityQualityOfService;
} OBJECT_ATTRIBUTES;

2.1.3 进程和线程标志

  • ProcessFlagsThreadFlags:控制创建行为

常用进程标志:

#define PROCESS_CREATE_FLAGS_BREAKAWAY 0x00000001
#define PROCESS_CREATE_FLAGS_NO_DEBUG_INHERIT 0x00000002
#define PROCESS_CREATE_FLAGS_INHERIT_HANDLES 0x00000004
#define PROCESS_CREATE_FLAGS_SUSPENDED 0x00000200

常用线程标志:

#define THREAD_CREATE_FLAGS_CREATE_SUSPENDED 0x00000001
#define THREAD_CREATE_FLAGS_HIDE_FROM_DEBUGGER 0x00000004
#define THREAD_CREATE_FLAGS_INITIAL_THREAD 0x00000080

2.1.4 进程参数

  • ProcessParameters:指向 RTL_USER_PROCESS_PARAMETERS 结构
typedef struct _RTL_USER_PROCESS_PARAMETERS {
  BYTE           Reserved1[16];
  PVOID          Reserved2[10];
  UNICODE_STRING ImagePathName;
  UNICODE_STRING CommandLine;
} RTL_USER_PROCESS_PARAMETERS, *PRTL_USER_PROCESS_PARAMETERS;

使用 RtlCreateProcessParametersEx 初始化:

RtlCreateProcessParametersEx(&ProcessParameters, &ImagePath, NULL, NULL, NULL, 
                           NULL, NULL, NULL, NULL, NULL, 
                           RTL_USER_PROCESS_PARAMETERS_NORMALIZED);

2.1.5 创建信息

  • CreateInfo:指向 PS_CREATE_INFO 结构
typedef struct _PS_CREATE_INFO {
  SIZE_T Size;
  PS_CREATE_STATE State;
  // ...
} PS_CREATE_INFO;

基本初始化:

CreateInfo.Size = sizeof(CreateInfo);
CreateInfo.State = PsCreateInitialState;

2.1.6 属性列表

  • AttributeList:指向 PS_ATTRIBUTE_LIST 结构
typedef struct _PS_ATTRIBUTE {
  ULONG_PTR Attribute;
  SIZE_T Size;
  union {
    ULONG_PTR Value;
    PVOID ValuePtr;
  };
  PSIZE_T ReturnLength;
} PS_ATTRIBUTE, *PPS_ATTRIBUTE;

typedef struct _PS_ATTRIBUTE_LIST {
  SIZE_T TotalLength;
  PS_ATTRIBUTE Attributes[1];
} PS_ATTRIBUTE_LIST, *PPS_ATTRIBUTE_LIST;

初始化示例:

PPS_ATTRIBUTE_LIST AttributeList = (PS_ATTRIBUTE_LIST*)RtlAllocateHeap(
  RtlProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PS_ATTRIBUTE));
AttributeList->TotalLength = sizeof(PS_ATTRIBUTE_LIST) - sizeof(PS_ATTRIBUTE);
AttributeList->Attributes[0].Attribute = PS_ATTRIBUTE_IMAGE_NAME;
AttributeList->Attributes[0].Size = NtImagePath.Length;
AttributeList->Attributes[0].Value = (ULONG_PTR)NtImagePath.Buffer;

3. 实战应用

3.1 基本进程创建

// 初始化UNICODE_STRING
UNICODE_STRING ImagePath;
RtlInitUnicodeString(&ImagePath, (PWSTR)L"\\??\\C:\\Windows\\System32\\calc.exe");

// 创建进程参数
PRTL_USER_PROCESS_PARAMETERS ProcessParameters;
RtlCreateProcessParametersEx(&ProcessParameters, &ImagePath, NULL, NULL, NULL, 
                           NULL, NULL, NULL, NULL, NULL, 
                           RTL_USER_PROCESS_PARAMETERS_NORMALIZED);

// 初始化创建信息
PS_CREATE_INFO CreateInfo;
CreateInfo.Size = sizeof(CreateInfo);
CreateInfo.State = PsCreateInitialState;

// 初始化属性列表
PPS_ATTRIBUTE_LIST AttributeList = (PS_ATTRIBUTE_LIST*)RtlAllocateHeap(
  RtlProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PS_ATTRIBUTE));
AttributeList->TotalLength = sizeof(PS_ATTRIBUTE_LIST) - sizeof(PS_ATTRIBUTE);
AttributeList->Attributes[0].Attribute = PS_ATTRIBUTE_IMAGE_NAME;
AttributeList->Attributes[0].Size = ImagePath.Length;
AttributeList->Attributes[0].Value = (ULONG_PTR)ImagePath.Buffer;

// 调用NtCreateUserProcess
HANDLE hProcess, hThread;
NtCreateUserProcess(&hProcess, &hThread, PROCESS_ALL_ACCESS, THREAD_ALL_ACCESS, 
                   NULL, NULL, NULL, NULL, ProcessParameters, &CreateInfo, 
                   AttributeList);

// 清理资源
RtlFreeHeap(RtlProcessHeap(), 0, AttributeList);
RtlDestroyProcessParameters(ProcessParameters);

3.2 父进程欺骗(PPID Spoofing)

PPID欺骗是一种使恶意进程看起来像是由合法进程产生的技术,用于规避检测。

实现步骤:

  1. 获取目标父进程句柄
OBJECT_ATTRIBUTES oa;
InitializeObjectAttributes(&oa, 0, 0, 0, 0);
CLIENT_ID cid = { (HANDLE)5644, NULL }; // 5644为目标父进程ID
HANDLE hParent = NULL;
NtOpenProcess(&hParent, PROCESS_ALL_ACCESS, &oa, &cid);
  1. 检查父进程完整性级别(可选)
HANDLE hToken;
OpenProcessToken(hProcess, TOKEN_QUERY, &hToken);
DWORD cbTokenIL = 0;
PTOKEN_MANDATORY_LABEL pTokenIL = NULL;
GetTokenInformation(hToken, TokenIntegrityLevel, NULL, 0, &cbTokenIL);
pTokenIL = (TOKEN_MANDATORY_LABEL)LocalAlloc(LPTR, cbTokenIL);
GetTokenInformation(hToken, TokenIntegrityLevel, pTokenIL, cbTokenIL, &cbTokenIL);
DWORD dwIntegrityLevel = GetSidSubAuthority(pTokenIL->Label.Sid, 0);
// dwIntegrityLevel 值对应: LOW, MEDIUM, HIGH, SYSTEM
  1. 添加父进程属性
AttributeList->Attributes[1].Attribute = PS_ATTRIBUTE_PARENT_PROCESS;
AttributeList->Attributes[1].Size = sizeof(HANDLE);
AttributeList->Attributes[1].ValuePtr = hParent;
// 注意增加TotalLength以容纳新属性

4. 优势与应用场景

4.1 优势

  1. 规避检测:相比CreateProcess,NtCreateUserProcess更底层,不易被安全产品Hook
  2. 更细粒度控制:直接控制进程创建的各个阶段
  3. 隐蔽性:可实现PPID欺骗等高级技术

4.2 应用场景

  1. 恶意软件开发中规避检测
  2. 渗透测试中实现隐蔽进程创建
  3. 安全产品开发中监控进程创建行为
  4. 系统工具开发中需要精细控制进程创建

5. 注意事项

  1. 内存管理:正确释放分配的资源(RtlFreeHeap, RtlDestroyProcessParameters)
  2. 错误处理:检查NTSTATUS返回值
  3. 权限要求:某些操作需要高权限(如SeTcb)
  4. 兼容性:不同Windows版本可能有细微差异

6. 扩展学习

  1. 研究NtCreateProcessEx与NtCreateUserProcess的区别
  2. 探索更多PS_ATTRIBUTE类型及其用途
  3. 结合进程注入技术实现更复杂的攻击链
  4. 研究如何检测此类隐蔽的进程创建行为
NtCreateUserProcess 深入解析与实战应用 1. 基本概念与背景 NtCreateUserProcess 是 Windows 系统底层用于创建用户模式进程的系统调用。相比传统的 CreateProcess API,它提供了更底层的进程创建控制能力。 1.1 历史演变 在 XP 时代,创建进程需要执行四个系统调用: NtOpenFile NtCreateSection NtCreateProcess(Ex) NtCreateThread(Ex) 现代 Windows 系统中,NtCreateUserProcess 整合了这些功能,只需一个系统调用即可创建新进程 1.2 与 CreateProcess 的关系 CreateProcess 是用户态 API,其内部调用链为: 2. NtCreateUserProcess 函数原型与参数详解 2.1 关键参数解析 2.1.1 句柄与访问权限 ProcessHandle 和 ThreadHandle :存储创建的进程和线程句柄 ProcessDesiredAccess 和 ThreadDesiredAccess :进程和线程的访问权限 常用值: PROCESS_ALL_ACCESS 和 THREAD_ALL_ACCESS 2.1.2 对象属性 ProcessObjectAttributes 和 ThreadObjectAttributes :指向 OBJECT_ATTRIBUTES 结构 2.1.3 进程和线程标志 ProcessFlags 和 ThreadFlags :控制创建行为 常用进程标志: 常用线程标志: 2.1.4 进程参数 ProcessParameters :指向 RTL_USER_PROCESS_PARAMETERS 结构 使用 RtlCreateProcessParametersEx 初始化: 2.1.5 创建信息 CreateInfo :指向 PS_CREATE_INFO 结构 基本初始化: 2.1.6 属性列表 AttributeList :指向 PS_ATTRIBUTE_LIST 结构 初始化示例: 3. 实战应用 3.1 基本进程创建 3.2 父进程欺骗(PPID Spoofing) PPID欺骗是一种使恶意进程看起来像是由合法进程产生的技术,用于规避检测。 实现步骤: 获取目标父进程句柄 检查父进程完整性级别(可选) 添加父进程属性 4. 优势与应用场景 4.1 优势 规避检测 :相比CreateProcess,NtCreateUserProcess更底层,不易被安全产品Hook 更细粒度控制 :直接控制进程创建的各个阶段 隐蔽性 :可实现PPID欺骗等高级技术 4.2 应用场景 恶意软件开发中规避检测 渗透测试中实现隐蔽进程创建 安全产品开发中监控进程创建行为 系统工具开发中需要精细控制进程创建 5. 注意事项 内存管理 :正确释放分配的资源(RtlFreeHeap, RtlDestroyProcessParameters) 错误处理 :检查NTSTATUS返回值 权限要求 :某些操作需要高权限(如SeTcb) 兼容性 :不同Windows版本可能有细微差异 6. 扩展学习 研究NtCreateProcessEx与NtCreateUserProcess的区别 探索更多PS_ ATTRIBUTE类型及其用途 结合进程注入技术实现更复杂的攻击链 研究如何检测此类隐蔽的进程创建行为