DLL Hijacking


I’ve been having a lot of fun recently with DLL Hijacking. It’s been around for quite a few years now and the ‘best practices’ recommended by Microsoft are to fully-qualify the DLL paths.

Quite a lot of applications that don’t do this, however…

Thankfully, the Windows OS has gotten quite a bit smarter over the years when it comes to this sort of thing. They’ve altered the priority of paths being searched, which significantly cut down on the impact to most applications. Additionally, some of their core DLL files are set up in such a way that even if an explicit path is given, it will ignore it in favor of where it knows the ‘good’ copy is.

The MSDN documentation provides some pretty useful information on the way searching happens.

  1. If a DLL with the same module name is already loaded in memory, the system checks only for redirection and a manifest before resolving to the loaded DLL, no matter which directory it is in. The system does not search for the DLL.
  2. If the DLL is on the list of known DLLs for the version of Windows on which the application is running, the system uses its copy of the known DLL (and the known DLL’s dependent DLLs, if any) instead of searching for the DLL. For a list of known DLLs on the current system, see the following registry key: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\KnownDLLs.
  3. If a DLL has dependencies, the system searches for the dependent DLLs as if they were loaded with just their module names. This is true even if the first DLL was loaded by specifying a full path.

The first and last items were interesting to me.

But, really, it’s even more simple if the application you’re looking to hijack is installed outside of the usual “Program Files” or “Program Files (x86)” directories. At least when an application is installed in one of those folders, local admin rights are needed to write to them. But if the program is installed to its own folder, plenty of fun can be had…

One such example I’ve had success with in my home environment is BGInfo utility, from Sysinternals. It’s a popular utility with system administrators and generally seems to get installed in C:\bginfo\ (which doesn’t have any built-in protections, by default). It looks like I wasn’t the only one who found it to be a worthwhile target

This allows a custom DLL to be added to the directory (by a tech-savy user, malware, an attacker, etc.) without any special rights being needed.

Using procmon, also by Sysinternals, I was able to see that one of the libraries BGInfo uses is version.dll

I found the legitimate file, made my own DLL with the same name and public methods. All requests made to it get sent over to the appropriate routine in the legitimate version.dll file (so the program continues to work as expected). I also added my own custom payload into the DLL’s initial execution. That payload gets run under the context of the account executing BGInfo.exe

As a proof-of-concept, I simply added a message box. If this had been a real exploit, however, there’s a lot more potential for abuse…

At most organizations, BGInfo gets executed upon login by all users… which includes local administrators and potentially domain administrators. Just let that sink in for a bit… Here’s code provided by a non-admin, malware, etc. and it’s getting automatically executed by an admin. Ouch!

Granted, it’s a bit of a waiting game… but it can allow for some rather easy elevation of privileges… Especially if logins by local administrators happen pretty frequently.

What about if domain admins don’t do local logins? No problem. Use the initial DLL hijacking to execute code for a local admin. From there, additional hijacking for programs commonly used by domain admins (via Run As…) can be done without a whole lot of additional effort.

This can also lead to pass-the-hash attacks, spreading similar attacks to other machines on the network, etc.

All in all… it’s bad news for an enterprise.

Even if no admins (local or otherwise) execute the DLL-hijacked application, it’s still going to have persistent code that launches whenever the program does (which is login, in the case of BGInfo). Probably not ideal.

If there isn’t an obviously-exploitable program in an unprotected directory, though… what then? I’ve had a surprisingly amount of success dropping hijacked DLLs into the current user’s AppData temp directory. Using my same tainted version.dll from earlier, I was able to trigger my ‘rogue code’ during a Notepad++ update. Pretty handy.

The moral of the story is… fully qualify your DLL paths. And even if you do, be aware of potential DLL hijacking through the dependencies of the DLLs you are fully-qualifying. If it can be abused… it probably will be.

Next on my list of techniques to get more familiar with is DLL Injection. Seems like it’ll be a lot of fun, too.

Share Your Thought