| 56 | } |
| 57 | |
| 58 | static void InjectDll(const HANDLE hProcess, const std::filesystem::path& dllPath) |
| 59 | { |
| 60 | auto absDllPath = std::filesystem::absolute(dllPath).string(); |
| 61 | auto remoteMemSize = absDllPath.size() + 1; // +1 to account for null character |
| 62 | auto* pRemoteMem = VirtualAllocEx(hProcess, NULL, remoteMemSize, MEM_COMMIT, PAGE_READWRITE); |
| 63 | |
| 64 | if (pRemoteMem == NULL) |
| 65 | { |
| 66 | auto error = GetLastError(); |
| 67 | LOGE << "Could not allocate memory in target process. Error: " << win::GetErrorDescription(error) << std::endl; |
| 68 | exit(1); |
| 69 | } |
| 70 | |
| 71 | if (!WriteProcessMemory(hProcess, pRemoteMem, absDllPath.c_str(), remoteMemSize, NULL)) |
| 72 | { |
| 73 | auto error = GetLastError(); |
| 74 | LOGE << "WriteProcessMemory failed. Error: " << win::GetErrorDescription(error) << std::endl; |
| 75 | exit(1); |
| 76 | } |
| 77 | FlushInstructionCache(hProcess, pRemoteMem, remoteMemSize); |
| 78 | |
| 79 | HMODULE hKernel32 = GetModuleHandle("Kernel32"); |
| 80 | HANDLE hRemoteThread = CreateRemoteThread( |
| 81 | hProcess, |
| 82 | NULL, |
| 83 | 0, |
| 84 | reinterpret_cast<LPTHREAD_START_ROUTINE>(GetProcAddress(hKernel32, "LoadLibraryA")), |
| 85 | pRemoteMem, |
| 86 | 0, |
| 87 | NULL |
| 88 | ); |
| 89 | |
| 90 | if (hRemoteThread == NULL) |
| 91 | { |
| 92 | auto error = GetLastError(); |
| 93 | LOGE << "Could not create remote thread in target process. Error: " << win::GetErrorDescription(error); |
| 94 | LOGE << "Tip: Check bit-ness of the application and DXGIOverlay.exe." << std::endl; |
| 95 | VirtualFreeEx(hProcess, pRemoteMem, 0, MEM_RELEASE); |
| 96 | exit(1); |
| 97 | } |
| 98 | |
| 99 | WaitForSingleObject(hRemoteThread, INFINITE); |
| 100 | CloseHandle(hRemoteThread); |
| 101 | |
| 102 | VirtualFreeEx(hProcess, pRemoteMem, 0, MEM_RELEASE); |
| 103 | } |
| 104 | |
| 105 | void Attach(uint32_t processId, const std::filesystem::path& dllPath) |
| 106 | { |
no test coverage detected