#define ArrLen(arr) (sizeof(arr)/sizeof(arr[0]))
int main(int argc, char *argv[])
{
// Open process with
HANDLE processHandle = OpenProcess(PROCESS_QUERY_INFORMATION //
| PROCESS_CREATE_THREAD // Required by 'CreateRemoteThread()'.
| PROCESS_VM_OPERATION // Required by 'VirtualAllocEx()'.
| PROCESS_VM_WRITE, // Required by 'WriteProcessMemory()'.
FALSE, 1234);
// Allocate memory at remote processs.
char *remoteMem = static_cast<char *>(VirtualAllocEx(processHandle, nullptr, 64, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE));
// All processes use "kernel32.dll" in the same location, we get the offset of 'LoadLibraryA()' and use it in remote process.
// (There is no function named 'LoadLibrary'!)
PTHREAD_START_ROUTINE funcLoadLibrary = reinterpret_cast<PTHREAD_START_ROUTINE>(GetProcAddress(GetModuleHandle("kernel32"), "LoadLibraryA"));
// Write argument to remote process for 'LoadLibraryA()'.
const char buf[64] = "youDll.dll";
WriteProcessMemory(processHandle, remoteMem, buf, ArrLen(buf), nullptr);
// Create remote thread, and run the 'LoadLibraryA()'.
// You can write your code at the 'case DLL_PROCESS_ATTACH' in dll.
HANDLE hThread = CreateRemoteThread(processHandle, nullptr, 0, funcLoadLibrary, remoteMem, 0, nullptr);
// Wait for completion of the remote task.
WaitForSingleObject(hThread, INFINITE);
return 0;
}