Skip to content

Commit 52341eb

Browse files
committed
Improve x64 system region calculation
InInitializationOrderModuleList might be unreliable due to security products. Also, use a more defensive approach for unusual Ntdll.dll base addresses.
1 parent 6745f6d commit 52341eb

2 files changed

Lines changed: 21 additions & 18 deletions

File tree

Source/KNSoft.SlimDetours/Memory.c

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
*
1515
* The region is [0x50000000 ... 0x78000000) (640MB) on 32-bit Windows;
1616
* and [0x00007FF7FFFF0000 ... 0x00007FFFFFFF0000) (32GB) on 64-bit Windows, which is too large to avoid.
17-
* In this case, avoiding 1GB range starting at Ntdll.dll is make sense.
17+
* In this case, avoiding 1GB range starting at Ntdll.dll makes sense.
1818
* If ASLR is disabled on NT6.0 or NT6.1, we reserve the top 1GB or 640MB region.
1919
*
2020
* The original Microsoft Detours always assumes and reserves [0x70000000 ... 0x80000000] (256MB) for system DLLs,
@@ -35,7 +35,7 @@ _STATIC_ASSERT(SYSTEM_RESERVED_REGION_HIGHEST + 1 == 0x00007FFFFFFF0000ULL);
3535
_STATIC_ASSERT(SYSTEM_RESERVED_REGION_SIZE == _32GB);
3636
_STATIC_ASSERT(SYSTEM_RESERVED_REGION_LOWEST == 0x00007FF7FFFF0000ULL);
3737

38-
static ULONG_PTR s_ulSystemRegionHighLowerBound = MAXULONG_PTR;
38+
static const UNICODE_STRING g_usNtdllDll = RTL_CONSTANT_STRING(L"ntdll.dll");
3939
#else
4040
_STATIC_ASSERT(SYSTEM_RESERVED_REGION_HIGHEST + 1 == 0x78000000UL);
4141
_STATIC_ASSERT(SYSTEM_RESERVED_REGION_SIZE == _640MB);
@@ -116,18 +116,25 @@ detour_memory_init(VOID)
116116
{
117117
#if defined(_WIN64)
118118
/* 1GB after Ntdll.dll */
119-
PLDR_DATA_TABLE_ENTRY NtdllLdrEntry;
119+
PVOID NtdllBase = NULL;
120+
LdrGetDllHandle(NULL, NULL, (PUNICODE_STRING)&g_usNtdllDll, &NtdllBase);
120121

121-
NtdllLdrEntry = CONTAINING_RECORD(NtCurrentPeb()->Ldr->InInitializationOrderModuleList.Flink,
122-
LDR_DATA_TABLE_ENTRY,
123-
InInitializationOrderLinks);
124-
s_ulSystemRegionLowUpperBound = (ULONG_PTR)NtdllLdrEntry->DllBase + NtdllLdrEntry->SizeOfImage - 1;
125-
s_ulSystemRegionLowLowerBound = s_ulSystemRegionLowUpperBound - _1GB + 1;
126-
if (s_ulSystemRegionLowLowerBound < SYSTEM_RESERVED_REGION_LOWEST)
122+
// Win10/Win11 ntdll virtual size is around 1.8-2.5MB, reserving 16MB should
123+
// be enough to cover future growth. Moreover, the ntdll region is already
124+
// used by ntdll, so it's merely an optimization.
125+
s_ulSystemRegionLowUpperBound = (ULONG_PTR)NtdllBase + _16MB - 1;
126+
127+
// Ensure the reserved region is within the system reserved range. It should
128+
// be, but be defensive just in case.
129+
if (s_ulSystemRegionLowUpperBound < SYSTEM_RESERVED_REGION_LOWEST + _1GB - 1)
127130
{
128-
s_ulSystemRegionHighLowerBound = s_ulSystemRegionLowLowerBound + SYSTEM_RESERVED_REGION_SIZE;
129-
s_ulSystemRegionLowLowerBound = SYSTEM_RESERVED_REGION_LOWEST;
131+
s_ulSystemRegionLowUpperBound = SYSTEM_RESERVED_REGION_LOWEST + _1GB - 1;
132+
} else if (s_ulSystemRegionLowUpperBound > SYSTEM_RESERVED_REGION_HIGHEST)
133+
{
134+
s_ulSystemRegionLowUpperBound = SYSTEM_RESERVED_REGION_HIGHEST;
130135
}
136+
137+
s_ulSystemRegionLowLowerBound = s_ulSystemRegionLowUpperBound - _1GB + 1;
131138
#else
132139
s_ulSystemRegionLowUpperBound = SYSTEM_RESERVED_REGION_HIGHEST;
133140
s_ulSystemRegionLowLowerBound = SYSTEM_RESERVED_REGION_LOWEST;
@@ -207,13 +214,8 @@ BOOL
207214
detour_memory_is_system_reserved(
208215
_In_ PVOID Address)
209216
{
210-
return
211-
((ULONG_PTR)Address >= s_ulSystemRegionLowLowerBound && (ULONG_PTR)Address <= s_ulSystemRegionLowUpperBound)
212-
#if defined(_WIN64)
213-
|| ((ULONG_PTR)Address >= s_ulSystemRegionHighLowerBound &&
214-
(ULONG_PTR)Address <= SYSTEM_RESERVED_REGION_HIGHEST)
215-
#endif
216-
;
217+
return (ULONG_PTR)Address >= s_ulSystemRegionLowLowerBound &&
218+
(ULONG_PTR)Address <= s_ulSystemRegionLowUpperBound;
217219
}
218220

219221
_Ret_notnull_

Source/KNSoft.SlimDetours/SlimDetours.NDK.inl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ C_ASSERT((ULONG_PTR)MI_ASLR_HIGHEST_SYSTEM_RANGE_ADDRESS - (ULONG_PTR)MI_ASLR_LO
100100
#define _GB(x) ((x) * _1GB)
101101

102102
#define _512KB _KB(512)
103+
#define _16MB _MB(16)
103104
#define _640MB _MB(640)
104105
#define _2GB _GB(2)
105106
#define _32GB _GB(32)

0 commit comments

Comments
 (0)