bool SharkMemory::RemoveDetour(void **ppDelegate) { auto itr = m_hooks.find(*ppDelegate); if (itr == m_hooks.end()) { LOG_DEBUG("Could not find a detour registered to this delegate."); return false; } DWORD oldProtection = 0; SHookInformation &hookInfo = itr->second; DWORD_PTR functionOffset = reinterpret_cast<DWORD_PTR>(hookInfo.function); SetMemoryProtection(functionOffset, hookInfo.bytes.size(), PAGE_EXECUTE_READWRITE, &oldProtection); bool success = WriteMemory_Safe(functionOffset, hookInfo.bytes); SetMemoryProtection(functionOffset, hookInfo.bytes.size(), oldProtection); if (success) { *ppDelegate = hookInfo.function; m_trampolineHeap.free(hookInfo.trampoline); m_hooks.erase(itr); } else LOG_DEBUG("Detour transaction failed: Could not remove detour patch (Function: 0x%08X).", hookInfo.function); return success; }
bool SharkMemory::DetourFunction(void **ppDelegate, void *pRedirect) { ThreadGrabber threadGrabber; if (!threadGrabber.update(GetCurrentProcessId())) { LOG_DEBUG("Detour transaction failed: Could not take thread snapshot!"); return false; } bool success = false; void *function = *ppDelegate; DWORD_PTR functionOffset = reinterpret_cast<DWORD_PTR>(function); DWORD oldProtection = 0; if (SetMemoryProtection(functionOffset, 0x20, PAGE_EXECUTE_READWRITE, &oldProtection)) { uint32 trampolineSize = 0; uint32 jumpSize = sizeof(DWORD_PTR) + 1; while (trampolineSize < jumpSize) trampolineSize += GetInstructionSize(functionOffset + trampolineSize); // allocate a trampoline... byte *trampoline = m_trampolineHeap.allocate(trampolineSize + jumpSize); if (trampoline != nullptr) { memcpy(trampoline, function, trampolineSize); trampoline[trampolineSize] = 0xE9; DWORD_PTR trampolineOffset = reinterpret_cast<DWORD_PTR>(trampoline); GetMemory<DWORD_PTR>(trampolineOffset + trampolineSize + 1) = functionOffset - (trampolineOffset + jumpSize); SHookInformation hookInfo = {0}; hookInfo.function = function; hookInfo.trampoline = trampoline; hookInfo.bytes.put_array(trampoline, trampolineSize); m_hooks[trampoline] = hookInfo; // hook chain support - relocate jump far, call far if (trampolineSize > sizeof(DWORD_PTR) && (trampoline[0] == 0xE8 || trampoline[0] == 0xE9)) { DWORD_PTR& relocate = GetMemory<DWORD_PTR>(trampolineOffset + 1); relocate += functionOffset; relocate -= trampolineOffset; } ByteBuffer jump(trampolineSize, 0xCC); jump << byte(0xE9); jump << reinterpret_cast<DWORD_PTR>(pRedirect) - (functionOffset + jumpSize); const auto &threads = threadGrabber.threads(); for (const auto& thread: threads) _detourUpdateThread(thread, hookInfo); *ppDelegate = trampoline; success = WriteMemory_Safe(functionOffset, jump); for (const auto& thread: threads) _detourResumeThread(thread); } else LOG_DEBUG("Detour transaction failed: Trampoline heap alloc failed!"); SetMemoryProtection(functionOffset, 0x20, oldProtection); } else LOG_DEBUG("Detour transaction failed: Cannot set code protection!"); return success; }
void ForceWrite(void *dst, const void *src, size_t size) { SetMemoryProtection(dst, size, MemoryFlags::ExecuteReadWrite); memcpy(dst, src, size); SetMemoryProtection(dst, size, MemoryFlags::ExecuteRead); }