Commit 81a6f78
authored
Fix AccessViolationException when scanning Unity 6 modules with protected memory pages (#267)
* Fix AccessViolation scanning Unity 6 modules with protected pages
FindSignatureInModule did a raw linear byte walk over the entire loaded
module. On Unity 6000.x the GameAssembly image maps regions as PAGE_NOACCESS
/ guard pages, so dereferencing them throws a process-fatal
AccessViolationException before the caller's signature-exhaustion fallback
can run (observed registering injected types on Priconne, Unity 6000.0.58f2).
Temporarily flip every committed region of the module to PAGE_EXECUTE_READWRITE
for the duration of the scan via VirtualQuery/VirtualProtect, then restore the
original protections in a finally block. Non-committed (MEM_FREE/MEM_RESERVE)
regions are skipped. Mirrors the approach used by downstream forks that already
support Unity 6.
* Guard the page-protection scan workaround to Windows only
Per @ds5678's review on #267: VirtualProtect/VirtualQuery are kernel32 (Windows-only)
and PAGE_NOACCESS is a Windows page state. Run the make-readable / restore dance only
when OperatingSystem.IsWindows(); on other platforms fall back to the direct
FindSignatureInBlock scan (its prior behaviour), so the kernel32 P/Invokes are never
called off-Windows. Also satisfies the CA1416 platform-compatibility analyzer.
* Scan only readable regions instead of changing page protections
Per @ds5678's review on #267 (relaying Discord feedback): modifying page protections
(VirtualProtect to PAGE_EXECUTE_READWRITE) is dangerous and unnecessary. VirtualQuery
already enumerates the module's regions, so skip the non-readable / guard / uncommitted
ones during the signature scan rather than forcing them readable. Removes VirtualProtect
and the RWX flip entirely; keeps the Windows-only guard (VirtualQuery is kernel32) with
the plain whole-module scan as the off-Windows fallback.
* Bound the signature scan to each region + apply review refinements
The per-region scan could read up to mask.Length-1 bytes past a readable region into the
adjacent guard / PAGE_NOACCESS page -> a fatal AccessViolationException. Cap
FindSignatureInBlock's loop at blockSize - mask.Length so every read stays inside the region.
Per @ds5678's review: GetModuleRegions now returns the list instead of an out parameter, and
its comment is XML documentation.
* Use TerraFX.Interop.Windows for VirtualQuery instead of a manual P/Invoke
Replace the hand-written kernel32 VirtualQuery DllImport and MEMORY_BASIC_INFORMATION struct with the TerraFX.Interop.Windows bindings, pinned to 10.0.22621.2 (the last release targeting .NET 6). The readable-region scan is unchanged.
* Annotate the region scan as Windows-only for CA1416
The TerraFX MEMORY_BASIC_INFORMATION fields are annotated for Windows 6.1+. Mark GetModuleRegions with the matching SupportedOSPlatform attribute and guard the call with OperatingSystem.IsWindowsVersionAtLeast(6, 1) so the platform-compatibility analyzer is satisfied.
* Use TerraFX MEM/PAGE constants instead of hand-rolled hex
Drop the manual MEM_COMMIT/PAGE_GUARD/PAGE_READABLE consts and the
`using static Windows` in favour of the constants TerraFX already
exposes (MEM.*, PAGE.*), qualify VirtualQuery, and default-init the
MEMORY_BASIC_INFORMATION. The readable mask moves inside the
windows6.1 guard so the const fold stays on a supported-platform path.1 parent 455c42a commit 81a6f78
2 files changed
Lines changed: 66 additions & 10 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
33 | 33 | | |
34 | 34 | | |
35 | 35 | | |
| 36 | + | |
36 | 37 | | |
37 | 38 | | |
38 | 39 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | | - | |
| 1 | + | |
| 2 | + | |
| 3 | + | |
2 | 4 | | |
| 5 | + | |
3 | 6 | | |
| 7 | + | |
4 | 8 | | |
5 | 9 | | |
6 | 10 | | |
7 | 11 | | |
8 | 12 | | |
9 | | - | |
| 13 | + | |
10 | 14 | | |
11 | | - | |
12 | | - | |
13 | | - | |
14 | | - | |
15 | | - | |
16 | | - | |
17 | | - | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
18 | 45 | | |
19 | 46 | | |
20 | 47 | | |
| |||
28 | 55 | | |
29 | 56 | | |
30 | 57 | | |
31 | | - | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
32 | 63 | | |
33 | 64 | | |
34 | 65 | | |
| |||
45 | 76 | | |
46 | 77 | | |
47 | 78 | | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
48 | 103 | | |
49 | 104 | | |
50 | 105 | | |
| |||
0 commit comments