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:
kbe
2026-07-22 00:32:19 +02:00
parent 3f0bea6bd4
commit 44a368de9c
9 changed files with 301 additions and 43 deletions
@@ -128,6 +128,29 @@ public sealed class PatternScannerCache
IntPtr End,
IReadOnlyList<ProcessModule>? Modules = null) : IEquatable<CacheKey>
{
public bool Equals(CacheKey? other)
{
if (other is null)
return false;
if (Start != other.Start || End != other.End || Mask != other.Mask)
return false;
if (!Pattern.AsSpan().SequenceEqual(other.Pattern))
return false;
if (Modules is null)
return other.Modules is null;
if (other.Modules is null || Modules.Count != other.Modules.Count)
return false;
for (int i = 0; i < Modules.Count; i++)
{
if (Modules[i].BaseAddress != other.Modules[i].BaseAddress)
return false;
}
return true;
}
// Override GetHashCode to hash the contents, not references
public override int GetHashCode()
{