inline SmartHandle CreateRemoteThreadAndWait(Process const& process, LPTHREAD_START_ROUTINE func, DWORD timeout = INFINITE) { SmartHandle remote_thread{::CreateRemoteThread( process.GetHandle(), nullptr, 0, func, nullptr, 0, nullptr)}; if (!remote_thread.GetHandle()) { DWORD const last_error = ::GetLastError(); HADESMEM_DETAIL_THROW_EXCEPTION(Error{} << ErrorString{"CreateRemoteThread failed."} << ErrorCodeWinLast{last_error}); } DWORD const wait_res = ::WaitForSingleObject(remote_thread.GetHandle(), timeout); if (wait_res != WAIT_OBJECT_0) { if (wait_res == WAIT_TIMEOUT) { HADESMEM_DETAIL_THROW_EXCEPTION( Error{} << ErrorString{"WaitForSingleObject timeout."}); } DWORD const last_error = ::GetLastError(); HADESMEM_DETAIL_THROW_EXCEPTION( Error{} << ErrorString{"WaitForSingleObject failed."} << ErrorCodeWinLast{last_error}); } return remote_thread; }
inline PVOID TryAlloc(Process const& process, SIZE_T size, PVOID base = nullptr) { return ::VirtualAllocEx(process.GetHandle(), base, size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); }
inline void Free(Process const& process, LPVOID address) { if (!::VirtualFreeEx(process.GetHandle(), address, 0, MEM_RELEASE)) { DWORD const last_error = ::GetLastError(); HADESMEM_DETAIL_THROW_EXCEPTION(Error{} << ErrorString{"VirtualFreeEx failed."} << ErrorCodeWinLast{last_error}); } }
inline PVOID Alloc(Process const& process, SIZE_T size, PVOID base = nullptr) { PVOID const address = ::VirtualAllocEx(process.GetHandle(), base, size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); if (!address) { DWORD const last_error = ::GetLastError(); HADESMEM_DETAIL_THROW_EXCEPTION(Error{} << ErrorString{"VirtualAllocEx failed."} << ErrorCodeWinLast{last_error}); } return address; }
inline DWORD Protect(Process const& process, MEMORY_BASIC_INFORMATION const& mbi, DWORD protect) { DWORD old_protect = 0; if (!::VirtualProtectEx(process.GetHandle(), mbi.BaseAddress, mbi.RegionSize, protect, &old_protect)) { DWORD const last_error = ::GetLastError(); HADESMEM_DETAIL_THROW_EXCEPTION(Error{} << ErrorString{"VirtualProtectEx failed."} << ErrorCodeWinLast{last_error}); } return old_protect; }
inline void WriteUnchecked(Process const& process, PVOID address, LPCVOID data, std::size_t len) { HADESMEM_DETAIL_ASSERT(address != nullptr); HADESMEM_DETAIL_ASSERT(data != nullptr); HADESMEM_DETAIL_ASSERT(len != 0); SIZE_T bytes_written = 0; if (!::WriteProcessMemory( process.GetHandle(), address, data, len, &bytes_written) || bytes_written != len) { DWORD const last_error = ::GetLastError(); HADESMEM_DETAIL_THROW_EXCEPTION(Error{} << ErrorString{"WriteProcessMemory failed."} << ErrorCodeWinLast{last_error}); } }