In my previous post about DLLs and how they work, I commented that winmm.dll was a KnownDLL in Longhorn. It turns out that this is a bug in an existing KnownDLL. But what in the heck ARE Known DLLs in the first place?
Well, it turns out that it’s in the KB, and I’ll summarize.
KnownDLL’s is a mechanism in Windows NT (and win9x) that allows the system to “cache” commonly used system DLLs. It was originally added to improve application load time, but it also can be considered a security mechanism, since it prevents people from exploiting weak application directory permissions by dropping in Trojan horse versions of system DLLs (since the key system DLLs are all known DLLs, the version of the file in the application directory will be ignored). As a security mechanism it’s not a particularly strong mechanism (if you can write to the directory that contains a program, you can create other forms of havoc), but it can be considered a security mechanism.
If you remember from my previous article, when the loader finds a DLL import record in an executable, it opens the file and tries to map the file into memory. Well, that’s not ENTIRELY the case. In fact, before that happens the loader looks for an existing section called \KnownDlls\<dll filename>. If that section exists, then instead of opening the file, the loader simply uses the existing section. It then follows all the “normal” rules for loading a DLL.
When the system boots, it looks in the registry at HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\KnownDLLs and creates a \KnownDlls\<dll filename> section for every DLL listed under that registry key.
If you compare the HKLM\System\CCS\Control\Session Manager\KnownDLLs registry key with the sections under \KnownDlls (using a viewer like winobj), you’ll notice that the \KnownDlls object container always has more entries in it than the registry key. This is because the \KnownDlls sections are computed as the transitive closure of the DLLs listed in KnownDLLs. So if a DLL’s listed in KnownDLLs, all of the DLL’s that are statically linked with the DLL are ALSO listed in the \KnownDlls section.
Also, if you look in the KnownDLLs registry key, you’ll notice that there’s no path listed for the KnownDLLs. That’s because all KnownDLLs are assumed to be in the directory pointed to by HKLM\System\CCS\Control\KnownDLLs\DllDirectory registry value. Again, this is an aspect of KnownDLLs being a security feature – by requiring KnownDLLs to be in the same directory, it makes it harder for someone to inject their own Trojan version of one of the KnownDLLs.
Oh, and if the KnownDLLs processing causes any issues, or if for some other reason you don’t want the system to load a DLL as a KnownDll, then you can set HKLM\System\CCS\Control\Session Manager\ExcludeFromKnownDlls to exclude a DLL from the KnownDll processing. So in my example, until the bug is fixed in the existing KnownDLL, I’m adding winmm.dll to my ExcludeFromKnownDlls list.