mirror of
https://github.com/rapid7/metasploit-payloads
synced 2025-04-24 10:09:49 +02:00

Previous commits removed the stack size parameter from the remote thread creation function call. This caused issues in systems prior to Vista/2k8. This fix puts that value back in and now everything is honky dory. Tested on 2k/XP/2k3/Vista/7/2k8
125 lines
2.8 KiB
C
125 lines
2.8 KiB
C
#include "precomp.h"
|
|
#include "../../../../../common/arch/win/remote_thread.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 = create_remote_thread(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;
|
|
}
|