@@ -53,8 +53,49 @@ C_ASSERT(sizeof(_DETOUR_ALIGN) == 1);
5353//
5454// Region reserved for system DLLs, which cannot be used for trampolines.
5555//
56- static PVOID s_pSystemRegionLowerBound = (PVOID)(ULONG_PTR)0x70000000 ;
57- static PVOID s_pSystemRegionUpperBound = (PVOID)(ULONG_PTR)0x80000000 ;
56+ // On Windows 10, ntdll.dll is mapped at random location (ASLR) within a
57+ // range near the top of the usermode address space.
58+ // After that, further system DLLs are mapped top down within this range.
59+ // In the bottom of the range is reached, the allocator wraps to the top.
60+ //
61+ // We also want to exlcude any pages that share a CFG bitmap page with a system DLL
62+ // so leave an additional a 1MB buffer on each side of the range.
63+ //
64+ #if defined(DETOURS_64BIT)
65+ // On X64 the range is 0x7FF800000000..0x7FFFFFFF0000 - which is 32GB!
66+ // So we likely must allocate in the system DLL range to be +/- 2GB.
67+ // But we want to avoid at least the first 1GB that will be used for system DLLs.
68+ // Due to wrapping, this may be two seperate ranges.
69+ static PVOID s_pSystemRegionUpperBound = (PVOID)((ULONG_PTR)GetModuleHandleW(L" ntdll.dll" ) + (ULONG_PTR)0x100000 );
70+ static PVOID s_pSystemRegionLowerBound = (PVOID)((ULONG_PTR)s_pSystemRegionUpperBound < (ULONG_PTR)0x7FF83F000000 ?
71+ (ULONG_PTR)0x7FF7FF000000 : ((ULONG_PTR)s_pSystemRegionUpperBound - (ULONG_PTR)0x40000000 ));
72+ static SIZE_T s_pSystemRegionSize = (ULONG_PTR)s_pSystemRegionUpperBound - (ULONG_PTR)s_pSystemRegionLowerBound; // up to 1GB
73+
74+ static SIZE_T s_pSystemRegion2Size = (SIZE_T)0x40000000 - s_pSystemRegionSize;
75+ static PVOID s_pSystemRegion2UpperBound = (PVOID)(ULONG_PTR)0x800000000000 ;
76+ static PVOID s_pSystemRegion2LowerBound = (PVOID)((ULONG_PTR)s_pSystemRegion2UpperBound - s_pSystemRegion2Size);
77+ #else
78+ // On X86 the range was originally 0x70000000..0x80000000
79+ // However, since Windows 8, the range is now 0x50000000..0x78000000
80+ // Reference: Windows Internals, 7th Edition, page 368
81+ // We just exclude both ranges.
82+ static PVOID s_pSystemRegionUpperBound = (PVOID)((ULONG_PTR)0x80000000 );
83+ static PVOID s_pSystemRegionLowerBound = (PVOID)((ULONG_PTR)0x50000000 - 0x100000 );
84+ static SIZE_T s_pSystemRegionSize = (ULONG_PTR)s_pSystemRegionUpperBound - (ULONG_PTR)s_pSystemRegionLowerBound; // 769MB
85+ #endif
86+
87+ inline SIZE_T should_skip_sytem_range_size (PBYTE pbTry)
88+ {
89+ if (pbTry >= s_pSystemRegionLowerBound && pbTry <= s_pSystemRegionUpperBound) {
90+ return s_pSystemRegionSize;
91+ }
92+ #if defined(DETOURS_64BIT)
93+ if (pbTry >= s_pSystemRegion2LowerBound && pbTry <= s_pSystemRegion2UpperBound) {
94+ return s_pSystemRegion2Size;
95+ }
96+ #endif
97+ return 0 ;
98+ }
5899
59100// ////////////////////////////////////////////////////////////////////////////
60101//
@@ -1247,9 +1288,10 @@ static PVOID detour_alloc_region_from_lo(PBYTE pbLo, PBYTE pbHi)
12471288 for (; pbTry < pbHi;) {
12481289 MEMORY_BASIC_INFORMATION mbi;
12491290
1250- if (pbTry >= s_pSystemRegionLowerBound && pbTry <= s_pSystemRegionUpperBound) {
1291+ const SIZE_T nSkipSize = should_skip_sytem_range_size (pbTry);
1292+ if (nSkipSize) {
12511293 // Skip region reserved for system DLLs, but preserve address space entropy.
1252- pbTry += 0x08000000 ;
1294+ pbTry += nSkipSize ;
12531295 continue ;
12541296 }
12551297
@@ -1297,9 +1339,10 @@ static PVOID detour_alloc_region_from_hi(PBYTE pbLo, PBYTE pbHi)
12971339 MEMORY_BASIC_INFORMATION mbi;
12981340
12991341 DETOUR_TRACE ((" Try %p\n " , pbTry));
1300- if (pbTry >= s_pSystemRegionLowerBound && pbTry <= s_pSystemRegionUpperBound) {
1342+ const SIZE_T nSkipSize = should_skip_sytem_range_size (pbTry);
1343+ if (nSkipSize) {
13011344 // Skip region reserved for system DLLs, but preserve address space entropy.
1302- pbTry -= 0x08000000 ;
1345+ pbTry -= nSkipSize ;
13031346 continue ;
13041347 }
13051348
@@ -1346,6 +1389,9 @@ static PVOID detour_alloc_trampoline_allocate_new(PBYTE pbTarget,
13461389 // in order to maintain ASLR entropy.
13471390
13481391#if defined(DETOURS_64BIT)
1392+ DETOUR_TRACE ((" System DLL regions to skip: %p->%p and %p->%p\n " ,
1393+ s_pSystemRegionLowerBound, s_pSystemRegionUpperBound,
1394+ s_pSystemRegion2LowerBound, s_pSystemRegion2UpperBound));
13491395 // Try looking 1GB below or lower.
13501396 if (pbTry == NULL && pbTarget > (PBYTE)0x40000000 ) {
13511397 pbTry = detour_alloc_region_from_hi ((PBYTE)pLo, pbTarget - 0x40000000 );
0 commit comments