Jump to content
Sign in to follow this  

DLL Hijack Auditing - Questions

Recommended Posts


- Auditing DLL Hijacking -

The root causes of this vulnerability class are calls to:
1. Non-existing dlls. E.g. doesnotexistonthisos.dll vs exists.dll
2. DLL files without specifying full path. E.g. foo.dll vs c:\windows\system32\foo.dll
3. Wrong name. E.g. foo.dll.dll

This can be exploited by:
1. Placing a malicious DLL in the CWD, a directory in PATH or a remote share/WebDAV. 
Some hardening techniques (registry) are available which can affect load-order: KnownDLLs, SafeDLLSearch, CWDIllegalInDllSearch. 

2. DLL Planting in application directory if it has weak permissions.

3. Dynamic-Link Library Redirection. Details: https://msdn.microsoft.com/en-us/library/windows/desktop/ms682600(v=vs.85).aspx

4. For installation archives obtained over HTTP and unsigned: extract archive, test executables for DLL hijacking, place DLL inside archive, compress and serve to end-user with MiTM.

* Auditing * 
Dynamic analysis: Use ProcMon and filter for .dll NOT FOUND.
Static analysis: Use strings on the binary or load into IDA Pro.

* Exploitation *
1. DLL Does Not Exist: code a malicious DLL, store it together with the executable
2. DLL Without Path: 
A. Use Dependency Walker to export all DLL calls, create a new DLL with the calls as stub
B. Perform DLL redirection
3. As 1 or 2 but change the extension

1. Why is static IDA Pro output different results than dynamic Procmon? Example: Application X loads DLL Y and Z audit with Procmon. IDA only lists DLL Y. If we place a Z DLL it will get loaded and executed by the application. 

2. I am never able to load a double extension DLL through hijacking (foo.dll.dll). Any idea why? 

3. DLL Without Path, which option for exploitation: A or B ? 

I found two solutions to solve this but solution A does not work (application loads DLL, crashes on one stub functions), B is yet to be tested. 

Solution A

/* export all required functions - use Dependency Walker to check what is needed */

extern "C"


   __declspec(dllexport) int GetFileVersionInfoA();

   __declspec(dllexport) int GetFileVersionInfoSizeA();

   __declspec(dllexport) int VerQueryValueA();

   __declspec(dllexport) int GetFileVersionInfoW();

   __declspec(dllexport) int GetFileVersionInfoSizeW();

   __declspec(dllexport) int VerQueryValueW();




    Implement DLLMain with common datatypes so we don't have to include windows.h.

    Otherwise this would cause several compile errors because of the already known but reexported functions.


int DllMain(void* hinst, unsigned long* reason, void* reserved) {


    return 0;


/* Implement stubs of our exports */

int GetFileVersionInfoA() {

    return 0;


Solution B
Forward functions to their corresponding functions in the original user32 DLL file. This can be accomplished using linker directives:

#pragma comment(linker, "/export:MessageBox=user33.MessageBox")

This instructs the linker to add an exportable function named MessageBox to our DLL's export table, and that this exported function will simply be a forwarder to the MessageBox function in user33.dll.

Note the use of the name user33 instead of user32 (no, this is not a typo). This is necessary because our DLL is named user32.dll, so if we had specified user32.MessageBox, we would be forwarding the function back to ourselves. To prevent this, we will copy the original user32.dll file into the Internet Explorer directory (along with the manifest file and our new user32.dll file), renaming it to user33.dll

Source: https://dl.packetstormsecurity.net/papers/win/intercept_apis_dll_redirection.pdf

Share this post

Link to post

Please sign in to comment

You will be able to leave a comment after signing in

Sign In Now
Sign in to follow this