DLL hijacking vulnerabilities

Published: 2010-08-23
Last Updated: 2010-08-27 12:17:51 UTC
by Bojan Zdrnja (Version: 3)
22 comment(s)

For the last couple of days there have been a lot of discussions about a vulnerability published by a Slovenian security company ACROS. HD Moore (of Metasploit fame) also independently found hundreds of vulnerable applications and, as he said, the cat is now really out of the bag.

In order to see what is going here we first have to understand how modern applications are built. Modern applications come modularized with multiple DLLs (Dynamic Link Libraries). This allows the programmer to use functions available in other DLLs on the system – Windows has hundreds of them. Now, if a DLL is not available on the system, the developer can decide to pack it with the main application’s executable and store it, for example, in the applications directory.

The most important DLLs are specified in the KnownDLLs registry key (HKLM/System/CurrentControlSet/Control/Session Manager/KnownDLLs). These are easy – if an application needs to load it, the system knows that they have to be in the directory specified by the DllDirectory registry key, which is usually %SystemRoot%/system32.

However, when another DLL is being loaded, the system dynamically tries to find the DLL. Historically, Microsoft made a mistake by putting the current directory in the first place (some of you Unix oldies might remember when “.” was at the first place in the PATH variable). This has been fixed by Microsoft by introducing the SafeDllSearchMode setting (registry value). This setting specifies the order in which a DLL will be searched for. For example, as specified in http://msdn.microsoft.com/en-us/library/ms682586%28v=VS.85%29.aspx this is the search order with the SafeDllSearchMode setting enabled:

   1. The directory from which the application loaded.
   2. The system directory. Use the GetSystemDirectory function to get the path of this directory.
   3. The 16-bit system directory. There is no function that obtains the path of this directory, but it is searched.
   4. The Windows directory. Use the GetWindowsDirectory function to get the path of this directory.
   5. The current directory.
   6. The directories that are listed in the PATH environment variable. Note that this does not include the per-application path specified by the App Paths registry key. The App Paths key is not used when computing the DLL search path.

If multiple directories hold a DLL with the same name, the first match wins. This setting is enabled by default on Windows XP SP2.

Now, the problem happens when, for example, the application tries to load a DLL that does not exist on the system. You can see one such example in the picture below, where I found out that one of my favorite applications is very much vulnerable. See how it tries to find the DLL in all those directories before if gets to the one on the share? Both names of the application and DLL have been blacked out – no point in serving this on a silver plated dish :(

DLL hijacking

Ok, so what about attack vectors. Any place where the attacker can put both the file to be opened by an application and a malicious DLL can be used as the attack vector. Obviously, as in the example above, the most obvious attack place are Windows shares so I guess we are looking at another vulnerability that uses similar attack vectors such as the LNK vulnerability last month – the difference here is that by just browsing to the directory nothing will happen since the user has to open the file.

In order to protect your networks/system be sure to audit permissions on shares to prevent unauthorized users from putting files where they shouldn’t be. Of course, I expect that by now you already blocked SMB and WebDAV on the perimeter so an external share cannot be used.

What about a fix? This will be a difficult one, especially since we can look at SafeDllSearchMode as a fix. So in most cases, developers of vulnerable applications will have to fix them and judging by the numbers I’ve seen around we are looking at a very difficult period. Hopefully those popular applications (such as the one I successfully exploited above) will get patched quickly so the final risk will be reduced.

We will keep an eye on this and update the diary as we get more information.


Microsoft released several articles describing details about this vulnerability as well as offering some workarounds. The main security advisory is available here (2269637). Recommendations are basically similar to those I wrote above, however, Microsoft also released a tool that allows blocklisting certain directories (locations) from being used for library loading. You can find more information about the tool here, and the tool itself here. The tool adds a new registry setting called CWDIllegailInDllSearch. This allows you to block loading of DLLs from shared network disks or through WebDAV clients. Of course, if you plan on deploying it, I recommend thoroughly testing it before push it somewhere as it might break loads of things - that is probably why Microsoft doesn't push this as a security update. To be fair, this is not Microsoft's fault, but bad programming since this vulnerability has been known for years and years (although some new attack vectors have been published recently). Microsoft also released a nice document about searching DLLs that you can find on the second link above (I especially like how they used Process Monitor to demonstrate the vulnerability and removed the vulnerable application's name and the DLL it's loading - same as I did in the picture above :).

Finally, I would like to say thanks to readers who wrote in, especially to Stefan Kanthak who shared a whole list of possible attack vectors. After spending some time going through this and locating even more, this looks extremely bad, but it is questionable if we will see wide exploitation of this vulnerability.

Let us know about your experiences with this and especially if you see someone/something exploiting this.


We received some e-mails about active exploitation of this vulnerability in the wild. While there are potentially hundreds, if not thousands of applications that are vulnerable, it appears that the attackers so far are exploiting uTorrent, Microsoft Office and Windows Mail, which are, coincidentally or not, applications for which Proof of Concept exploits have been published. Remember, it is extremely easy to exploit this and it doesn't require any advanced knowledge so be sure to check Microsoft's recommendation above or be very careful about files you open from network shares.


US-CERT has released an advisory regarding this issue today. As far as I can see there isn't any new information as such.  The latest version of the bulletin can be found here http://www.us-cert.gov/cas/techalerts/TA10-238A.html  - MH


Keywords: dll hijacking
22 comment(s)


Running as non-admin (and installing apps in directories not writable by non-admins) should protect users from inadvertently downloading DLL's into all subdirs *except* the "current directory" (which is a per-application-instance path to "the" working directory). Perhaps I'm missing the point, but I see no reason whatsoever to include the working directory in the DLL search path, as it varies and thus will lead to unpredictable results (what parts of the DLL hell does Microsoft refuse to fix).

Note that, IIRC, this is not a plain remote execution bug; users will have to be tricked into downloading DLL's to specific directories. However using standard Explorer settings, DLL's are typically not visible so users may not be aware of potentially planted "bombs". I recall the "Safari carpet bomb" issue where DLL's were planted on the user's desktop without asking any questions (however that bug should be fixed by now).

Anyway Microsoft should probably update system files such that something like a "ReallySafeDllSearchMode" registry value is supported, and the "current directory" is not included in DLL searches at all.

Until Microsoft provides a fix, another approach may prove useful, that is, by simply adding the missing DLL's to a location searched *before* the current directory. Obviously you must first find out which DLL's those are (for all applications you use), and, secondly, you'll typically have a problem locating those missing DLL's... A solution and a workaround are provided below.


The excellent tool "Dependency Walker" (aka depends.exe) written by Steve Miller is quite useful for said purpose. It lists all DLL's searched for at application startup, and tries to identify dynamically loaded DLL's (at a later stage). Depends.exe was distributed with various Microsoft applications (such as the "XP SP2 Support Tools" that are still on my system). Note that if Process Explorer (by Mark Russinovich) finds depends.exe on your system, right clicking an executable will show a submenu containing "Launch depends...".

You can download the latest version of DependencyWalker at http://www.dependencywalker.com/ . None of the files in the x86 version I just downloaded was digitally signed. Somebody else had already submitted the x86 zip to http://www.virustotal.com/file-scan/report.html?id=03d73abba0e856c81ba994505373fdb94a13b84eb29e6c268be1bf21b7417ca3-1282559314 which yields 0/41 (however, this neither means that Steve Miller can be trusted, nor that Steve Miller actually created or last-modified the files included in the zip file). You may want to search the Microsoft site for a more reliable (and digitally signed) but older version. Anyway be sure to read Steve's FAQ, http://www.dependencywalker.com/faq.html , in particular the topmost question (and answer ;)


Back to the second problem at hand: any DLL that an application looks for, that is *not found*, apparently poses a potential security risk. However, if the application functions perfectly without it, chances are that the application will still function correctly if you *add* a dummy DLL to the application installation directory with the missing-DLL-name (however, without the rquired functionality). For example, SERVMESS.DLL that comes with the W2k3 resource kit support tools (as part of the AutoExNT service) doesn't include any interesting code; instead it contains strings intended for various eventlog messages. The idea is to use a DLL without functions in order to avoid accidentally called functions, which may either take place based on the function-NAME (there's a small chance that function names coincide) *or* based on the function-NUMBER (ordinal) in the DLL (huge chance of conflicts). Calling a function with a wrong number of parameters and/or different parameter types usually causes an application to crash (and may even introduce other security vulnerabilities). My guess (but I'm not 100% sure, don't blame me if it happens too you) is that SERVMESS.DLL won't cause any crashes. Side note: the original SERVMESS.DLL that came with the NT4 resource kit, obviously as a result of a bug, didn't even contain any strings...

The W2k3 x86 reskit tools can be downloaded here: http://www.microsoft.com/downloads/details.aspx?familyid=9d467a69-57ff-4ae7-96ee-b18c4790cffd&displaylang=en
Unfortunately I'm unaware of a similar 64bit DLL, but then, I'm not sure that this problem even applies to 64-bit Windows.


As a test I opened c:\windows\system32\calc.exe in depends.exe: it reported (in red) that IESHIMS.DLL and WER.DLL are missing. I copied servmess.dll to C:\Windows\System32\iEsHImS.DlL and C:\Windows\System32\wEr.DlL (I used the funny names to be able to easily relocate those "hacked" files :)
I had to close and restart Depends.exe, now it reports: "Warning: At least one module has an unresolved import due to a missing export function in a delay-load dependent module" which is logical, servmess.dll doesn't include the functions that the application is looking for.

Actually it's not CALC.EXE that needs IESHIMS.DLL and WER.DLL: it's IEFRAME.DLL which is part of a rather deep hierarchy of DLL's. Furthermore, most Windows applications appear to be potentially looking for IESHIMS.DLL and WER.DLL sooner or later. I've not encountered any side effects after the change mentioned above - so far, but will post them here when I do. BTW I conducted this experiment on an English version of XP SP3 32bit (fully patched).


I suggest readers of sans.edu experiment with Dependency Walker to discover missing DLL's in the apps they use, perhaps "replace" them by dummy DLL's (until MS provides a fix), and report their findings.
Microsoft Security Advisory (2269637)
Insecure Library Loading Could Allow Remote Code Execution
- http://www.microsoft.com/technet/security/advisory/2269637.mspx
August 23, 2010 - "... DLL preloading attacks..."
Thanks to PC.Tech for the URL!

Indeed the fix described in http://support.microsoft.com/kb/2264107 introduces a new registry value "CWDIllegalInDllSearchValue" (not "ReallySafeDllSearchMode" I proposed, ya cant gettem all ;) that, if set to 0xFFFFFFFF, removes the current working directory from the default DLL search order.

IMPORTANT: using Microsoft's fix is the preferred solution over experimenting with SERVMESS.DLL as I described above as a workaround!
The text in http://support.microsoft.com/kb/2264107 seems not to be fully correct yet.

In the tables one can read "CWDIllegalInDllSearchValue" (which is what I mentioned in my post above), this is incorrect!

The value name I found in ntdll.dll (just patched on my PC) is "CWDIllegalInDllSearch". This matches the examples shown on the KB2264107 page, so they appear to be correct.

Furthermore (less important), the page mentions:

The CWDIllegalInDllSearch registry key [...]

which, IIRC, is incorrect, it's not a *key* but a registry value name (to which one assignes value data, in this case of type DWORD).

Finally, it appears that installing KB2264107 adds the value CWDIllegalInDllSearch to the registry, but sets it to zero (no effect). So, after patching, you'll have to assign other value_data (0xFFFFFFFF) to CWDIllegalInDllSearch in order to prevent the execution of DLL's in the current working directory.
I've discovered quite a few vulnerable programs that I haven't seen mentioned publicly yet that I would consider "high risk" (ie - they're part of the Windows core software). Two big ones are Outlook Express 6 and the Windows Address Book.


Looks like 0xFFFFFFFF breaks Outlook 2003 SP3, at least the first time it gets opened by a user (and that was the first app I tested)! This is going to be painful. I did some quick testing, and it looks like there is no option 3 (i.e. block both WebDAV and SMB, but permit all local working directory DLL loading). My hope was that the REG_DWORD was a bit-vector and 3 would represent flipping the WebDAV and SMB bits on, but that doesn't appear to be the case. ARGH! So now I have to decide which vector appears to be the more likely one since I can't protect against both.
Breaks Outlook 2002 (Office XP, fully patched) as well.

Apparently, during startup, Outlook (temporarily?) sets "C:\Program Files\Common Files\System\Mapi\1033" as its current working directory in order to load DLL's such as OUTEX.DLL, EMSMDB.DLL and MSMAPI32.DLL.

Fix: run regedit, locate key "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\OUTLOOK.EXE", open the value "Path" and append to it:

;C:\Program Files\Common Files\System\Mapi\1033

NOTE#1: The "1033" subdirname applies to US English, a different value will likely apply on systems with other languages in use.

The full value data on My PC now reads:
C:\Program Files\Microsoft Office\Office10\;C:\Program Files\Common Files\System\Mapi\1033

NOTE#2: the "Office10" subdir applies to Office XP (2002), this will probably be "Office11" for Outlook 2003.
Whoops, this site removes sequences such as \ followed by 10.

The string to append to the "Path" value in the HK.....OUTLOOK.EXE registry key LOOKS LIKE:

;C:/Program Files/Common Files/System/Mapi/1033

However, you must replace each / (slash) by \ (backslash) in regedit in order to get things right. Sorry I can't post the correct string here!
The patch breaks Chrome. When opening Chrome, it says it cannot find the file avutil-50.dll .
I can verify the Chrome error, I get the same thing.

Diary Archives