Fix LibraryLoader crash on error during context-transfer restoration

- Track whether transferred thread's original context was successfully restored.
- In the catch block, leak the remote allocation instead of freeing it if the thread was not restored; this prevents the target process from executing freed memory.
- Remove redundant 'op == 0x55' check in InstructionAnalyzer (already matched by (op & 0xF8) == 0x50).
- Simplify MemoryBase ReadString align-down expression to previousLen - (previousLen % nullLen).
- Change StubAllocator size parameter from nint to int for clarity (internal test seam).

Tests: 199 passing, 4 integration/interactive skipped.
This commit is contained in:
kbe
2026-07-22 01:24:33 +02:00
parent 77736698ab
commit 614806f5f1
4 changed files with 20 additions and 7 deletions
+15 -2
View File
@@ -209,6 +209,8 @@ public sealed class DllInjector
throw new InvalidOperationException($"SuspendThread failed (error {error}).");
}
bool restored = false;
try
{
IntPtr result;
@@ -257,6 +259,8 @@ public sealed class DllInjector
int error = Marshal.GetLastPInvokeError();
throw new InvalidOperationException($"ResumeThread restore failed (error {error}).");
}
restored = true;
}
else
{
@@ -302,6 +306,8 @@ public sealed class DllInjector
int error = Marshal.GetLastPInvokeError();
throw new InvalidOperationException($"ResumeThread restore failed (error {error}).");
}
restored = true;
}
if (result == IntPtr.Zero)
@@ -311,8 +317,15 @@ public sealed class DllInjector
}
catch
{
// Best effort: resume the thread if we left it suspended.
_ = NativeMethods.ResumeThread(thread);
// If we never successfully restored the thread's original context, the
// thread may still be executing (or about to execute) code inside the
// injected allocation. Freeing that memory now would crash the target
// process, so leak the block and leave the thread suspended.
if (!restored)
{
remoteBase = IntPtr.Zero;
}
throw;
}
}