The Microsoft’s documentation about the function LdrRegisterDllNotification()
states that DLL load notifications registered by this function:
Registers for notification when a DLL is first loaded.
This notification occurs before dynamic linking takes place.
I wrote the following test program to test this assertion and while these notifications act according to the documentation in Windows 7 x64, in Windows 10 x64 they act differently – namely, they occur after the DLL imports have been resolved and function entry points have been written to the Import Address Table ( IAT ) pointed to by the IMAGE_NT_HEADERS.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress->FirstThunk
VOID CALLBACK NotificationFunction(_In_ ULONG NotificationReason, _In_ PLDR_DLL_NOTIFICATION_DATA pNotificationData, _In_opt_ PVOID Context)
{
if (NotificationReason == LDR_DLL_NOTIFICATION_REASON_LOADED)
{
printf(" ----------------------------------------------------------------------------------------------- \n");
printf("LOADED: %wZ @ %p\n\n", pNotificationData->Loaded.FullDllName, pNotificationData->Loaded.DllBase);
if (!_wcsicmp((wchar_t*)Context, pNotificationData->Loaded.FullDllName->Buffer) || !_wcsicmp((wchar_t*)Context, pNotificationData->Loaded.BaseDllName->Buffer))
PrintImports((PBYTE)pNotificationData->Loaded.DllBase);
}
}
int wmain(int argc, wchar_t* argv[])
{
HMODULE hMod1 = LoadLibraryEx(argv[1], NULL, DONT_RESOLVE_DLL_REFERENCES);
if (hMod1)
{
printf(" ----------------------------------------------------------------------------------------------- \n");
printf("LOADED UNRESOLVED %ls @ %p\n\n", argv[1], hMod1);
if (PrintImports((PBYTE)hMod1))
printf("\nWARNING: Some functions have pre-bound entry points / addresses\n");
FreeLibrary(hMod1);
PVOID cookie;
NTSTATUS nts = LdrRegisterDllNotification(0, &NotificationFunction, argv[1], &cookie);
HMODULE hMod2 = LoadLibrary(argv[1]);
if (hMod2) {
printf(" ----------------------------------------------------------------------------------------------- \n");
printf("LOADED RESOLVED %ls @ %p\n\n", argv[1], hMod2);
}
nts = LdrUnregisterDllNotification(&cookie);
if (hMod2) {
PrintImports((PBYTE)hMod2);
FreeLibrary(hMod2);
}
} else {
printf("\nERROR: Loading library %ls\n", argv[1]);
return -1;
}
return 0;
}
The full Visual Studio project with the entire source code is available under the following address: tinyurl.com/4RbMm123
In Windows 7 x64, this test program generates the following output:
-----------------------------------------------------------------------------------------------
LOADED UNRESOLVED x.dll @ 000007FEF6030000
API-MS-Win-Core-LibraryLoader-L1-1-0.dll @ 000007FEFD680000
DisableThreadLibraryCalls 0000000000001230
API-MS-Win-Core-ProcessThreads-L1-1-0.dll @ 00000000772E0000
GetCurrentProcessId 000000000000128C
GetCurrentThreadId 0000000000001276
API-MS-Win-Core-Profile-L1-1-0.dll @ 000007FEFD680000
QueryPerformanceCounter 00000000000012CC
API-MS-Win-Core-SysInfo-L1-1-0.dll @ 000007FEFD680000
GetSystemTimeAsFileTime 000000000000131A
GetTickCount 000000000000130A
-----------------------------------------------------------------------------------------------
LOADED: x.dll @ 000007FEF5FF0000
API-MS-Win-Core-LibraryLoader-L1-1-0.dll @ 000007FEFD680000
DisableThreadLibraryCalls 0000000000001230
API-MS-Win-Core-ProcessThreads-L1-1-0.dll @ 00000000772E0000
GetCurrentProcessId 000000000000128C
GetCurrentThreadId 0000000000001276
API-MS-Win-Core-Profile-L1-1-0.dll @ 000007FEFD680000
QueryPerformanceCounter 00000000000012CC
API-MS-Win-Core-SysInfo-L1-1-0.dll @ 000007FEFD680000
GetSystemTimeAsFileTime 000000000000131A
GetTickCount 000000000000130A
-----------------------------------------------------------------------------------------------
LOADED RESOLVED x.dll @ 000007FEF6030000
API-MS-Win-Core-LibraryLoader-L1-1-0.dll @ 000007FEFD680000
DisableThreadLibraryCalls 0000000000001230 : 000007FEFD68B0B0
API-MS-Win-Core-ProcessThreads-L1-1-0.dll @ 00000000772E0000
GetCurrentProcessId 000000000000128C : 00000000772F32C0
GetCurrentThreadId 0000000000001276 : 00000000772F1CA0
API-MS-Win-Core-Profile-L1-1-0.dll @ 000007FEFD680000
QueryPerformanceCounter 00000000000012CC : 0000000077553BE0
API-MS-Win-Core-SysInfo-L1-1-0.dll @ 000007FEFD680000
GetSystemTimeAsFileTime 000000000000131A : 000007FEFD681760
GetTickCount 000000000000130A : 000007FEFD681120
However in Windows 10 x64, the same test program with the same x.dll
generates the following output:
-----------------------------------------------------------------------------------------------
LOADED UNRESOLVED x.dll @ 00007FF9005C0000
API-MS-Win-Core-LibraryLoader-L1-1-0.dll @ 00007FF905250000
DisableThreadLibraryCalls 0000000000001230
API-MS-Win-Core-ProcessThreads-L1-1-0.dll @ 00007FF906BC0000
GetCurrentProcessId 000000000000128C
GetCurrentThreadId 0000000000001276
API-MS-Win-Core-Profile-L1-1-0.dll @ 00007FF905250000
QueryPerformanceCounter 00000000000012CC
API-MS-Win-Core-SysInfo-L1-1-0.dll @ 00007FF905250000
GetSystemTimeAsFileTime 000000000000131A
GetTickCount 000000000000130A
-----------------------------------------------------------------------------------------------
LOADED: x.dll @ 00007FF9005C0000
API-MS-Win-Core-LibraryLoader-L1-1-0.dll @ 00007FF905250000
DisableThreadLibraryCalls 0000000000001230 : 00007FF9052C6C70
API-MS-Win-Core-ProcessThreads-L1-1-0.dll @ 00007FF906BC0000
GetCurrentProcessId 000000000000128C : 00007FF906BE4BA0
GetCurrentThreadId 0000000000001276 : 00007FF906BD5860
API-MS-Win-Core-Profile-L1-1-0.dll @ 00007FF905250000
QueryPerformanceCounter 00000000000012CC : 00007FF907B70160
API-MS-Win-Core-SysInfo-L1-1-0.dll @ 00007FF905250000
GetSystemTimeAsFileTime 000000000000131A : 00007FF9052A4240
GetTickCount 000000000000130A : 00007FF9052A0F80
-----------------------------------------------------------------------------------------------
LOADED RESOLVED x.dll @ 00007FF9005C0000
API-MS-Win-Core-LibraryLoader-L1-1-0.dll @ 00007FF905250000
DisableThreadLibraryCalls 0000000000001230 : 00007FF9052C6C70
API-MS-Win-Core-ProcessThreads-L1-1-0.dll @ 00007FF906BC0000
GetCurrentProcessId 000000000000128C : 00007FF906BE4BA0
GetCurrentThreadId 0000000000001276 : 00007FF906BD5860
API-MS-Win-Core-Profile-L1-1-0.dll @ 00007FF905250000
QueryPerformanceCounter 00000000000012CC : 00007FF907B70160
API-MS-Win-Core-SysInfo-L1-1-0.dll @ 00007FF905250000
GetSystemTimeAsFileTime 000000000000131A : 00007FF9052A4240
GetTickCount 000000000000130A : 00007FF9052A0F80
As you can see, the entry points to the imported functions are resolved in the "LOADED:" and "LOADED RESOLVED" sections in Windows 10 x64, however in Windows 7 x64 the imported functions are resolved only in the "LOADED RESOLVED" section, which agrees with the most current documentation.
Q: When exactly has this change happened ? i.e. in what version, service pack, update…
You need to sign in to view this answers
Leave feedback about this