DLL Proxying in the Tele-Conferencing Age

By: Mor Davidovich - Application Security Consultant & Penetration Tester   |   Updated: 4/26/2021

Ever since the whole covid-19 situation there has been a growth in the usage of tele-conferencing software such as Zoom, Microsoft Teams, Cisco WebEx and more. A lot of companies had to implement at least one of those software solutions into their infrastructure in order to accommodate the new way of work (or should I say, tele-work) that has been imposed on us due to the pandemic.

As a red teamer, one thing came to mind: how can I abuse the trust between the target’s infrastructure and the tele-conferencing solution implemented on the target? DLL Proxying (Sometimes also called DLL Sideloading). Let’s say we are tasked with attacking a highly restrictive environment with AV/EDR solutions installed, monitoring, AWL and more. Knowing that in order to work properly these days they will need to have some tele-conferencing solution installed on their systems, they would also have to allow it to run on their restrictive environment by whitelisting it so users could run that program. If we could make the program load our specially crafted DLL we can get Code Execution on the target system via a signed, trusted and probably White Listed binary that will run our malicious code for us. This code execution mechanism could potentially allow for initial access, persistence and even privilege escalation (in some situations) in the target environment.

How does it all work:

A dynamic-link library (DLL) is a module that contains functions and data that can be used by another module (application or DLL).”

Programs load DLLs all the time and this can be observed via tools such as Procmon. But what if the program cannot find the DLL in the location specified? This is where SafeDllSearchMode comes into play.

Since Windows XP, when a DLL cannot be found or its location is not explicitly specified in the program, Windows Loader (SafeDllSearchMode specifically) will search for it in a defined search order:

  1. The directory from which the application is loaded
  2. The system directory (C:\Windows\System32\)
  3. The 16-bit system directory (C:\Windows\System\)
  4. The Windows directory (C:\Windows\)
  5. The current directory (same as 1 unless otherwise specified)
  6. The directories that are listed in the PATH environment variable

< https://docs.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-search-order >

This search order can create situations where a program tries to load a DLL from the directory the program resides in before loading the DLL from its correct location. When this occurs (for example when we have write permissions on the directory the program resides in), we can easily place our specially crafted DLL that will execute our malicious code when it’s loaded while directing all legitimate function calls to the intended DLL file so it won’t disturb the flow of operations and crash the program.

Microsoft Teams:

The first step is identifying a DLL that can be hijacked, i.e.: a DLL the program is trying to load from a wrong path (as part of the search order described above) before finally loading it from the correct path. This can be done by opening the program, in this case Microsoft Teams (Teams.exe), while Running ProcMon in the background with the following filters:

The above filter will result in a list of DLL to be potentially proxied. It is essentially all of the DLLs that the program tried to load but could not find them in that path.

Let’s take a closer look at dxgi.dll (It can be any of them for that matter) by changing the Procmon filters to “Path Ends with: dxgi.dll” and removing the “Result: NAME NOT FOUND” filter:

Here we can see a perfect example of the SafeDllSearchMode defined search order in action.

First, the program looks for the “dxgi.dll” in the AppData folder (which in this case is the directory in which the program resides in - the first entry in the SafeDllSearchMode defined search order), once it can’t find it there (hence the result – NAME NOT FOUND) it then looks for it in the System Directory (C:\Windows\System32) and when it successfully finds the DLL there it then loads it into the memory space of the program (Load Image Operation).

What will happen if we plant a malicious DLL in the directory in which the program resides in? The program will load our malicious DLL instead of the real DLL! And since the directory is located in the local AppData directory, which is writable by the user by default, this is perfectly doable.

In order to not break the program’s flow, our malicious DLL needs to export all of the original DLL’s functions and proxy any calls made to those functions to the original DLL. We can do so by utilizing a simple python script that will generate the instructions for the linker to do all of that.