Are Win32 applications automatically linked against ntdll.dll?
Asked Answered
A

1

7

I've just found out by accident that doing this GetModuleHandle("ntdll.dll") works without a previous call to LoadLibrary("ntdll.dll").

This means ntdll.dll is already loaded in my process.

Is it safe to assume that ntdll.dll will always be loaded on Win32 applications, so that a call to LoadLibrary is not necessary?

Amplification answered 25/4, 2017 at 17:46 Comment(12)
It is an implementation detail that is subject to change. You ought to not using anything in ntdll.dll directly. But as long as you do, Microsoft can only help you if you do this correctly. There is no point in avoiding LoadLibrary().Jolo
ntdll.dll always loaded in all processes. it has always been and always will be surePeeress
Think about it this way... You made a call to GetModuleHandle(). GetModuleHandle() is in kernel32.dll, so your application had to link to it. If you look at the dependencies of kernel32.dll, you'll see it is dependent on ntdll.dll. So, if your application has to load kernel32, then it also has to load ntdll. But, that should not be a surprise about ntdll since it as the root of any Win32 process. There are several/many functions in kernel32 that are wrappers around functions in ntdll.Neckcloth
@JoeWillcoxson - ntdll.dll loaded before kernel.32 or any other dlls by very deep reason. when process start, from which address in user mode it must begin executed ? when new thread start - again from which point in user mode ? when kernel pass exception to user mode - to which address ? when Apc excecuted - which is first instruction in user mode ? when any windows messages come to process - again first user mode instruction where ? ntdll.dll hold entry points from kernel to user mode. and when process begin executed - who is initialize it user mode space, load addition dlls, etcPeeress
all this is ntdll.dll do. some processes not use kernel32.dll at all. but ntdll.dll always map to process space by kernelPeeress
@RbMm: "ntdll.dll always loaded in all processes. it has always been and always will be sure" - that is true in modern Windows versions, but it was not always true. NTDLL only exists in the NT-based Windows versions (NT, 2000, and XP onward), it did not exist in Windows 3.x, 9x, or ME, as they were not NT-based.Gunas
@RemyLebeau - i speak only about NT-based line. only which is actual now. and ntdll.dll as bootstrap dll, which do process initialization in user space and hold all entry points from kernel to user space - have very deep reason to be always loaded and in future.Peeress
@Peeress That is implementation detail.Particular
@DavidHeffernan - can say yes. but this is very fundamental details, which is very hard change (and are exist sense ?). else one reason point NuSkooler in own answer - dll loader also implemented in ntdll.dll too many fundamental reason have some dll in process, which initialize process, handle/hold entry points from kernel to user, etc. if this changed - faster of all in way - rename ntdll.dll, but for what?Peeress
@RbMm, I'm not an expert in the subject, but maybe for similar reasons that kernel32.dll has changed? I don't think it would be impossible for Microsoft to give those deep rules of ntdll like that of kernel to user entry points or SEH or ... to say ntcore.dll making ntdll a wrapper, at least for some parts . Then one may find that at least some native apps may not have ntdll.dll loaded but only that fictitious ntcore.dll. I think no one knows why they might decide to do that in future but Is it guaranteed that they won't?Queridas
@Queridas - may be all, but with different probability. kernel need some well known agent in process user space for callbacks via it (exception,apc, windows/hooks messages), threads entry point of execution, process initialization, etc. so some (at least 1) dll must be always load to all processes. now this is ntdll.dll. can say ms for example change name of this dll ? yes, can, but i not think that this will be done. can be part of functional moved to another dll (ntcore you say) - yes, but in this case anyway this dlls (in this case 2) need be loaded to process.Peeress
@RbMm, I understand that the kernel/user bridge dll will be loaded for all processes, (be it ntdll, ntcore or anything else) but the assumption that ntdll would be that bridge, may not hold forever. This maybe of more concern for NT native app writers rather than Win32 subsystem developers. As I see it near impossible for ntdll to not get loaded for Win32 even in those imaginary scenarios.Queridas
A
12

From MSDN on LoadLibrary() (emphasis mine):

The system maintains a per-process reference count on all loaded modules. Calling LoadLibrary increments the reference count. Calling the FreeLibrary or FreeLibraryAndExitThread function decrements the reference count. The system unloads a module when its reference count reaches zero or when the process terminates (regardless of the reference count).

In other words, continue to call LoadLibrary() and ensure you get your handle to ntdll.dll to be safe -- but the system will almost certainly be bumping a reference count as it should already be loaded.

As for "is it really always loaded?", see Windows Internals on the Image Loader (the short answer is yes, ntdll.dll is part of the loader itself and is always present).

The relevant paragraph is:

The image loader lives in the user-mode system DLL Ntdll.dll and not in the kernel library. Therefore, it behaves just like standard code that is part of a DLL, and it is subject to the same restrictions in terms of memory access and security rights. What makes this code special is the guaranty that it will always be present in the running process (Ntdll.dll is always loaded) and that it is the first piece of code to run in user mode as part of a new application. (When the system builds the initial context, the program counter, or instruction pointer is set to an initialization function inside Ntdll.dll.)

Alejandro answered 25/4, 2017 at 21:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.