From 64be4f82754a806cd49050ba25cfebba5016a82f Mon Sep 17 00:00:00 2001 From: Kevin Bataille Date: Wed, 22 Jul 2026 01:29:52 +0200 Subject: [PATCH] Fix page-boundary read issue in redirection helper Risk mitigation: - redirect now falls back to reading the minimum required bytes (detourLength) if the full buffer (detourLength + 16) cannot be read due to page boundaries. - First attempt: read detourLength + 16 bytes for the instruction analyzer (preferred). - Second attempt: read only detourLength bytes if the first attempt fails (bare minimum). - Throw only if both attempts fail. This prevents crashes when function interception functions that sit at the very end of a committed page. Tests: 199 passing, 4 integration/interactive skipped. --- WhiteMagic/Hooking/Detour.cs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/WhiteMagic/Hooking/Detour.cs b/WhiteMagic/Hooking/Detour.cs index b779ef0..541ef41 100644 --- a/WhiteMagic/Hooking/Detour.cs +++ b/WhiteMagic/Hooking/Detour.cs @@ -66,11 +66,18 @@ public sealed class Detour : IDisposable int pointerSize = _memory.Is64Bit ? 8 : 4; int detourLength = pointerSize == 8 ? 14 : 5; + // Try to read detourLength + 16 bytes for the prologue decoder. + // If the target is near a page boundary, this might fail, so fall back to the minimum. byte[] prologue = _memory.ReadBytes(Target, detourLength + 16); if (prologue.Length < detourLength) { - throw new InvalidOperationException( - "Could not read enough bytes from the target function to install a detour."); + // Second attempt: read only the minimum required bytes + prologue = _memory.ReadBytes(Target, detourLength); + if (prologue.Length < detourLength) + { + throw new InvalidOperationException( + "Could not read enough bytes from the target function to install a detour."); + } } int preserveLength = PrologueDecoder.GetWholeInstructionLength(prologue, detourLength, _memory.Is64Bit);