Skip to content

Commit 63fb5dd

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 63fb5dd

File tree

1 file changed

+16
-6
lines changed

1 file changed

+16
-6
lines changed

Source/KNSoft.SlimDetours/Memory.c

Lines changed: 16 additions & 6 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,6 +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 const UNICODE_STRING g_usNtdllDll = RTL_CONSTANT_STRING(L"ntdll.dll");
3839
static ULONG_PTR s_ulSystemRegionHighLowerBound = MAXULONG_PTR;
3940
#else
4041
_STATIC_ASSERT(SYSTEM_RESERVED_REGION_HIGHEST + 1 == 0x78000000UL);
@@ -116,12 +117,21 @@ detour_memory_init(VOID)
116117
{
117118
#if defined(_WIN64)
118119
/* 1GB after Ntdll.dll */
119-
PLDR_DATA_TABLE_ENTRY NtdllLdrEntry;
120+
PVOID NtdllBase = NULL;
121+
LdrGetDllHandle(NULL, NULL, (PUNICODE_STRING)&g_usNtdllDll, &NtdllBase);
122+
123+
// Note: The ntdll region isn't excluded, but it's already occupied
124+
// by ntdll, so that shouldn't be a problem.
125+
s_ulSystemRegionLowUpperBound = (ULONG_PTR)NtdllBase - 1;
126+
127+
// This condition is normally false, it's here just in case to have
128+
// defined behavior in unusual situations (e.g. EDR tampering).
129+
if (s_ulSystemRegionLowUpperBound < SYSTEM_RESERVED_REGION_LOWEST ||
130+
s_ulSystemRegionLowUpperBound > SYSTEM_RESERVED_REGION_HIGHEST)
131+
{
132+
s_ulSystemRegionLowUpperBound = SYSTEM_RESERVED_REGION_HIGHEST;
133+
}
120134

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;
125135
s_ulSystemRegionLowLowerBound = s_ulSystemRegionLowUpperBound - _1GB + 1;
126136
if (s_ulSystemRegionLowLowerBound < SYSTEM_RESERVED_REGION_LOWEST)
127137
{

0 commit comments

Comments
 (0)