Fix dispatcher crash/deadlock, instruction analyzer, cache equality, task leak, and redirection protection
- MainThreadDispatcher: guard DispatchHook with try/catch so exceptions never escape to native caller; drain and fault pending work on Dispose; synchronize Execute/ExecuteAsync/Dispose against race/dispose. - InstructionAnalyzer: require ModRM 0xEC for 0x83/0x81 sub-esp/rsp forms, rejecting unsafe RIP-relative or memory forms. - PatternScannerCache: implement value equality on CacheKey so repeated scans actually hit cache. - BackgroundTaskExecutor: add remote allocations to the free list immediately after VirtualAllocEx, before any write that could fail and leak. - redirect: capture and restore original page protection in Apply/Remove instead of leaving target RWX. - Regression tests for all six fixes. Tests: 198 passing, 4 integration/interactive skipped.
This commit is contained in:
@@ -117,28 +117,39 @@ public sealed class Detour : IDisposable
|
||||
"Failed to write the detour trampoline into the target process.");
|
||||
}
|
||||
|
||||
// Make the target page writable if necessary, then write the detour jump.
|
||||
// Make the target page writable if necessary, then write the detour jump,
|
||||
// restoring the original protection regardless of success or failure.
|
||||
if (!NativeMethods.VirtualProtectEx(
|
||||
_memory.Handle,
|
||||
Target,
|
||||
preserveLength,
|
||||
MemoryProtectionType.ExecuteReadWrite,
|
||||
out _))
|
||||
out MemoryProtectionType oldProtect))
|
||||
{
|
||||
int error = Marshal.GetLastPInvokeError();
|
||||
throw new InvalidOperationException(
|
||||
$"Failed to change target memory protection: error {error}");
|
||||
}
|
||||
|
||||
written = _memory.WriteBytes(Target, hookJump);
|
||||
if (written != hookJump.Length)
|
||||
try
|
||||
{
|
||||
throw new InvalidOperationException("Failed to write detour jump to target.");
|
||||
}
|
||||
written = _memory.WriteBytes(Target, hookJump);
|
||||
if (written != hookJump.Length)
|
||||
throw new InvalidOperationException("Failed to write detour jump to target.");
|
||||
|
||||
Trampoline = trampoline;
|
||||
Original = Marshal.GetDelegateForFunctionPointer(Trampoline, Hook.GetType());
|
||||
IsApplied = true;
|
||||
Trampoline = trampoline;
|
||||
Original = Marshal.GetDelegateForFunctionPointer(Trampoline, Hook.GetType());
|
||||
IsApplied = true;
|
||||
}
|
||||
finally
|
||||
{
|
||||
NativeMethods.VirtualProtectEx(
|
||||
_memory.Handle,
|
||||
Target,
|
||||
preserveLength,
|
||||
oldProtect,
|
||||
out _);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
@@ -164,9 +175,21 @@ public sealed class Detour : IDisposable
|
||||
Target,
|
||||
OverwrittenBytes.Length,
|
||||
MemoryProtectionType.ExecuteReadWrite,
|
||||
out _);
|
||||
out MemoryProtectionType oldProtect);
|
||||
|
||||
_memory.WriteBytes(Target, OverwrittenBytes);
|
||||
try
|
||||
{
|
||||
_memory.WriteBytes(Target, OverwrittenBytes);
|
||||
}
|
||||
finally
|
||||
{
|
||||
NativeMethods.VirtualProtectEx(
|
||||
_memory.Handle,
|
||||
Target,
|
||||
OverwrittenBytes.Length,
|
||||
oldProtect,
|
||||
out _);
|
||||
}
|
||||
}
|
||||
|
||||
if (Trampoline != IntPtr.Zero)
|
||||
|
||||
Reference in New Issue
Block a user