This post is part of a new series I’m starting titled “Fun with DLL’s” where I will dive into the specifics of Windows DLLs. In this series, I’ll be going over Windows Dynamic-Link Libraries (DLLs). I’ll discuss their purpose, very briefly explain how they function, and describe their implications in the realm of Information Security through walkthroughs of common DLL exploitation techniques.
Purpose of DLLs
Dynamic-Link Libraries (DLLs) are modular code components in Windows that are intended to streamline the code base. The reason this works is because shared functions exist in a single file rather than being duplicated in multiple files, and module code only needs to be loaded into memory once for multiple applications to share. Additionally, only one copy of the shared functions need to be updated to patch all other applications. This can be convenient, but can also present problems (which I’ll cover later in the series).
How DLLs are used
DLLs are crucial to the operation of the Windows OS. Pretty much the entire Windows API is implemented through DLLs, and many core system components depend on them.
With Windows DLLs, there are a few key concepts worthy of discussion briefly before I dive into our first technique. These are Name Resolution, Search Order, Redirection, and Side-by-Side (SxS) components.
Name resolution is a general IT concept wherein a system must determine an actual path based on some given alias. Those familiar with DNS know that clients must query name servers with human-readable domain names in order to “resolve” them to IP Addresses. In much the same way, with DLL Name Resolution a Windows system must “resolve” a given DLL name to a given file either already loaded in memory or resting on disk.
In order to resolve or “find” the DLL in question, Windows is designed to look in several predefined places throughout the system. The system executes this process by using a predefined Search Order which dictates which locations are to be searched for a DLL and in which order (under normal circumstances).
Redirection and SxS components are closely related because they are both intended to “force” an application to use certain DLLs irrespective of normal system behavior. These components exist in order to ensure applications have the library versions they need to function regardless of the environment they run in. Redirection simply involves dropping the needed DLLs and an empty “yourapp.local” file in the application directory. This forces Windows to load the DLLs in the same directory if they exist, otherwise it will load via the standard search order. SxS components serve a somewhat similar function but are outside the scope of this series. Just know that these components give massive power to developers to describe precisely the environment in which their applications should be executed, and therefore add flexibility and versioning protection for developers/administrators.
Concerning DLL Search Order, certain factors within a Windows System can modify the order of the search. A number of other factors can affect whether DLLs are even searched for at all. Here are some of the more common items that can affect search order:
1. DLL is already in Memory – System only searches for redirect (.local) file or SxS manifest before using the DLL in memory.
2. Known DLLs – Known DLLs are a list of DLLs that are given special treatment by the kernel module loader. If a DLL is found in this list (or is a dependency of one on the list *mind blown*), the search order is bypassed. Even redirection is bypassed! It is located at: HKLM\SYSTEM\CCS\Control\Session Manager\KnownDLLs
3. SafeDllSearchMode – Search order changes based on whether this key is enabled or disabled: HKLM\System\CCS\Control\Session Manager\SafeDllSearchMode. Even if enabled, this key could possibly be modified by a tricky adversary to load patched or spoofed system libraries for Command and Control, Persistence, etc.
These are just a few of the important factors affecting DLL Search Order in Windows.
What does this mean for security?
Any file capable of executing code will likely be the target of attackers at some point. This becomes even more likely because DLLs are such an essential component of the Windows OS. The MITRE ATT&CK Matrix includes three techniques related specifically to DLLs:
- DLL Search Order Hijacking – T1038
- DLL Injection – T1055
- DLL Side-Loading – T1073
We will be going over each of these in this series. Now that we’ve discussed the basics, let’s get into the first technique on this list – DLL Search-Order Hijacking – MITRE ATT&CK Technique T1038.
DLL Search Order Hijacking
Also referred to as Binary Planting or DLL Preloading, search order hijacking involves taking advantage of ambiguous search paths in applications. This involves creating a sort of “race condition” where the attacker attempts to place a malicious DLL in a location in the search order prior to where the legitimate DLL is located. When an executable is run and dynamically loads a DLL at run time, Windows standard behavior is to “search” for the DLL on the system in several locations until it is found.
As mentioned above, this search order can vary depending on several factors, but here is the default DLL Search Order for Desktop Applications with Safe DLL Search Mode enabled:
- Application Directory. (i.e. C:\Program Files\MyApp)
- System Directory. (i.e. C:\Windows\System32)
- 16-bit System Directory. (i.e. C:\Windows\System)
- Windows Directory. (i.e. C:\Windows)
- Current Directory.
- Directories listed in the PATH variable.
If certain conditions are met an attacker is somehow able to inject their DLL in a location earlier in the above search order than the legitimate DLL is found, the system will execute the attacker’s DLL instead. This is the heart of this technique. For instance, if an unsafe DLL call is made to a library in the System Directory (2nd in search order), and the attacker places a library of the same name in the Application’s Directory (1st in search order), the Attacker’s library would load and execute when called!
To demonstrate Search Order Hijacking in a very trivial way, I created 3 small C++ files:
- MyDLL.dll (legit)
- MyDLL.dll (evil)
To simulate the a Desktop Application, I installed the MyApplication.exe as seen below. The application is a very short one that merely loads a DLL and utilizes its exported function (in this case, a message box popup). Please note that my default version of Windows 10 did not have the SafeDLLSearchMode key added and enabled so the search order is slightly different than above. Here is my simulated Application Directory:
The Legitimate DLL the application needs to run is located in the Windows directory as seen below. This is unlikely behavior but gets the point across for our exercise:
Running the program via command prompt shows what happens when the application runs — It simply runs a function included in its DLL dependency:
Next, I fired up Process Monitor (from the SysInternals Suite) and added a filter so I could observe the system behavior as I launched the application:
After applying these changes, I began capturing in ProcMon and fired the Application off again to observe the DLL behavior:
As you can see, The system follows the search order with the result of NAME NOT FOUND until it locates the correct DLL in the Windows directory! What would happen if an adversary gained control of an application process via remote exploit and wanted to circumvent its normal behavior? They would simply have to place a DLL of the same name in the Application directory earlier in the Search Order! An advanced adversary may even patch the legitimate DLL with their malicious functions to keep the application stable.
Here is what the application directory looks like after our notional compromise:
After firing off our application this time, we see how the code of our “adversary” is executed instead:
Taking another look at ProcMon, we naturally see the DLL Name Resolution stop because it was found earlier in the Search Order:
This illustrates in a very simple way how DLL Search-Order can be exploited to further the objectives of an adversary.
The post wouldn’t be complete without methods for detection and mitigation. To detect, Utilize Sysmon and Watch for Event ID 7 – Image Loaded to baseline individual applications and set up alerts to monitor for deviations. General Threat Detections such as remote paths in the ImageLoaded attribute should definitely raise suspicion, as should unsigned DLLs being loaded in an environment which enforces strict Code Signing.
- Add and Enable the SafeDLLSearchMode Registry Key described above.
- Disable Remote Loading of DLLs with the following Keys:
- HKLM\SYSTEM\CCS\Control\Session Manager\CWDIllegalInDllSearch
- HKLM\Software\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\MyApplication.exe\CWDIllegalInDllSearch
- See here (https://blogs.technet.microsoft.com/srd/2010/08/23/more-information-about-the-dll-preloading-remote-attack-vector/) for instructions on which values to set!
- Create a rule in Application Control Policies\AppLocker via the Local Policy Editor that only allows signed DLLs to run (Caution: This should be strictly tested and may not be suitable for Large Enterprise use! Consider implementing as a rule with an exception system.)
- Add critical DLLs to KnownDLLs key. (Caution: There is a performance impact to this and I have not tested it personally.)
Thanks for reading. Stay tuned for my next post on DLL Injection!
https://msdn.microsoft.com/en-us/library/windows/desktop/ms682586(v=vs.85).aspx https://msdn.microsoft.com/en-us/library/windows/desktop/aa374029(v=vs.85).aspx https://msdn.microsoft.com/en-us/library/ms810279.aspx https://technet.microsoft.com/en-us/library/2007.09.windowsconfidential.aspx https://attack.mitre.org/wiki/Technique/T1038