Skip to content

Commit 4ed81f1

Browse files
author
John Uhlmann
committed
update system DLL range logic for 64-bit OSes
1 parent 4b8c659 commit 4ed81f1

File tree

1 file changed

+52
-6
lines changed

1 file changed

+52
-6
lines changed

src/detours.cpp

Lines changed: 52 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)