c++ - 调用 NtCreateProcessEx 失败无异常
问题描述
我想打电话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。
这些是我尝试过的一些资源:
- NtCreateProcess(Ex) - 我可以让子进程在以不同的进程名称运行时继承父地址空间吗?
- 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/
解决方案
首先,第三个参数是指向的指针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;
}