131 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			C++
		
	
	
	
		
		
			
		
	
	
			131 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			C++
		
	
	
	
| 
								 | 
							
								#include <iostream>
							 | 
						||
| 
								 | 
							
								#include <string>
							 | 
						||
| 
								 | 
							
								#include <windows.h>
							 | 
						||
| 
								 | 
							
								#include <detours.h>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include "payloadguid.hpp"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								HANDLE hChildProcess = NULL;
							 | 
						||
| 
								 | 
							
								HANDLE hChildThread = NULL;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								__declspec(noreturn) void HandleApiFailure(const char* api)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    DWORD lastErr = GetLastError();
							 | 
						||
| 
								 | 
							
								    std::cout << "payload.exe: " << api << " failed (" << lastErr << ')' << std::endl;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (hChildThread != NULL)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        CloseHandle(hChildThread);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (hChildProcess != NULL)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        TerminateProcess(hChildProcess, 1);
							 | 
						||
| 
								 | 
							
								        CloseHandle(hChildProcess);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    ExitProcess(1);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								std::wstring GetProcessFileName(HANDLE process)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    DWORD exeLocation_size = MAX_PATH + 1;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    std::wstring exeLocation;
							 | 
						||
| 
								 | 
							
								    exeLocation.resize(exeLocation_size);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (!QueryFullProcessImageNameW(process, 0, &exeLocation[0], &exeLocation_size))
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        HandleApiFailure("QueryFullProcessImageNameW");
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    exeLocation.resize(exeLocation_size);
							 | 
						||
| 
								 | 
							
								    return exeLocation;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void StartChild()
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    std::wstring target = GetProcessFileName(GetCurrentProcess());
							 | 
						||
| 
								 | 
							
								    target.erase(target.rfind(L'\\') + 1);
							 | 
						||
| 
								 | 
							
								    target += L"payloadtarget.exe";
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    STARTUPINFOW si = { sizeof(si) };
							 | 
						||
| 
								 | 
							
								    PROCESS_INFORMATION pi;
							 | 
						||
| 
								 | 
							
								    if (!CreateProcessW(target.c_str(), NULL, NULL, NULL, false,
							 | 
						||
| 
								 | 
							
								        CREATE_SUSPENDED, NULL, NULL, &si, &pi))
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        HandleApiFailure("CreateProcessW");
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    hChildProcess = pi.hProcess;
							 | 
						||
| 
								 | 
							
								    hChildThread = pi.hThread;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template<typename T>
							 | 
						||
| 
								 | 
							
								volatile T* InjectPayload(HANDLE hProcess, T payload, REFGUID guid)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    return static_cast<volatile T*>(
							 | 
						||
| 
								 | 
							
								        DetourCopyPayloadToProcessEx(hProcess,guid, &payload, sizeof(payload)));
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int main()
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    StartChild();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // give the child a handle to ourself
							 | 
						||
| 
								 | 
							
								    HANDLE targetHandleToParent;
							 | 
						||
| 
								 | 
							
								    if (!DuplicateHandle(GetCurrentProcess(), GetCurrentProcess(),
							 | 
						||
| 
								 | 
							
								        hChildProcess, &targetHandleToParent, 0, false, DUPLICATE_SAME_ACCESS))
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        HandleApiFailure("DuplicateHandle");
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (!InjectPayload(hChildProcess, targetHandleToParent, PARENT_HANDLE_PAYLOAD))
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        HandleApiFailure("DetourCopyPayloadToProcessEx");
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // inject a payload in ourself containing zero data
							 | 
						||
| 
								 | 
							
								    // the goal is for the child process to find this payload
							 | 
						||
| 
								 | 
							
								    // and fill it with random data, to test DetourFindRemotePayload
							 | 
						||
| 
								 | 
							
								    volatile random_payload_t* payloadAddr =
							 | 
						||
| 
								 | 
							
								        InjectPayload<random_payload_t>(GetCurrentProcess(), 0, RANDOM_DATA_PAYLOAD);
							 | 
						||
| 
								 | 
							
								    if (!payloadAddr)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        HandleApiFailure("DetourCopyPayloadToProcessEx");
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (!ResumeThread(hChildThread))
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        HandleApiFailure("ResumeThread");
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    CloseHandle(hChildThread);
							 | 
						||
| 
								 | 
							
								    hChildThread = NULL;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (WaitForSingleObject(hChildProcess, INFINITE) == WAIT_FAILED)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        HandleApiFailure("WaitForSingleObject");
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    DWORD exitCode;
							 | 
						||
| 
								 | 
							
								    if (!GetExitCodeProcess(hChildProcess, &exitCode))
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        HandleApiFailure("GetExitCodeProcess");
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // the exit code should match the random data the child process gave us
							 | 
						||
| 
								 | 
							
								    random_payload_t payload = *payloadAddr;
							 | 
						||
| 
								 | 
							
								    if (exitCode == payload)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        std::cout << "Success, exit code (0x" << std::uppercase << std::hex << exitCode
							 | 
						||
| 
								 | 
							
								            << ") matches payload content (0x" << payload << ')' << std::endl;
							 | 
						||
| 
								 | 
							
								        return 0;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    else
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        std::cout << "Error, exit code (0x" << std::uppercase  << std::hex << exitCode
							 | 
						||
| 
								 | 
							
								            << ") does not matches payload content (0x" << payload << ')' << std::endl;
							 | 
						||
| 
								 | 
							
								        return 1;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 |