Back in February, 2008, I posted on DLL preloading attacks and how to avoid them here. It seems that the problem has recently gotten a lot of attention – currently called "Binary Planting". You can read more about that at the MSRC blog, the SWI blog, on this ZDNET blog post, an update, and a Computerworld article.

In addition to the advice I gave previously, I recently thought of a simple way to avoid problems. The technique is simply to push the current working directory, set it to something safe, like c:\windows\system32, call LoadLibrary, and then reset it to the previous current working directory. Note that if you can call SetDllDirectory(""), as I documented in my previous post, then you should do that, as it is easier and will solve the problem for all your LoadLibrary calls. If you cannot do that, here's a code sample that will fix individual calls for you:

HMODULE SafeLoadLibrary(const wchar_t* wzFileName)

{

    static wchar_t wzSystem[MAX_PATH];

    wchar_t wzCurDir[MAX_PATH];

    HMODULE hMod = NULL;

 

    if(wzSystem[0] == L'\0')

    {

        if(GetSystemDirectory(wzSystem, _countof(wzSystem)) == 0)

            return NULL;

    }

 

    // Now get the actual current working directory

    if(GetCurrentDirectory(_countof(wzCurDir), wzCurDir) == 0)

        wzCurDir[0] = L'\0';

 

    SetCurrentDirectory(wzSystem);

 

    hMod = LoadLibrary(wzFileName);

 

    SetCurrentDirectory(wzCurDir);

 

    return hMod;

}

A nice feature of this code is that if the library you're loading might not have this fix and loads additional DLLs, it's been made safe by your changing the current working directory to something that's known good. A drawback of this code is that if some other thread is changing your current working directory, the two threads could have a race condition. This would be an unusual problem, but something to be aware of.

Obviously, if you need the current working directory in your search path, then this won't help, and it is up to you to ensure that the current working directory isn't something under an attacker's control.