Home DLL Hijacking via gdi32full delay-load DLLs

DLL Hijacking via gdi32full delay-load DLLs

I was recently scrolling down my feed on Twitter (yes, Twitter is a dumpster 🔥 right now, but still some great researchers are posting good info there), and I stumbled upon this tweet from Kurosh Dabbagh (@_Kudaes_):

Kudaes Tweet

(highly recommend reading the entire thread here)

Kurosh found a commonly used library (gdi32full.dll) that is susceptible to Delayed DLL Search Order Hijacking, due to this DLL making use of a feature called Delay-Load DLL and the way its calling TextShaping.dll. In all honesty, I did not know the Delay-Load DLL feature existed until I read this tweet from @_Kudaes_... And just like that, my brain decided to fixate on this for a couple of days.

🤔 So what is Delay-Load DLL?

This feature was introduced as part of Microsoft Visual Studio for C++, to allow developers to only load a DLL when they explicitly want to. A DLL, or dynamically-linked library, is a library that contains functions that can be used by other programs. This helps keep code efficient and encourages code reuse, so programmers can focus on creating new features and logic, and avoid reinventing the wheel. When a developer creates a program and wants to reuse some existing functions in a given library, dynamically, they can import that library's functions into their code. They can then call these function in two ways:

  1. By using runtime dynamic linking (when the application is already running and needs to get the DLL’s functions addresses)

  2. By load time dynamic linking (when the application is first loaded into memory, it uses an imported DLL’s functions as if they were local to the program).

By delay-loading a DLL, they only call these functions when specific conditions are met.

To give an example, let's say you created an application, and you want your app to open a registry key every time a user hits the "Open Registry Key" button on your application. You could implement a delay load on the library advapi32.dll, which would load only when the RegOpenKeyExAfunction function is called in your code.

Delay loading a DLL has multiple advantages, such as:

  • Improving initialization time by only loading DLLs when they are needed

  • Compatibility and error handling when apps need to run on different versions of Windows, where a function name may not exist or is called differently depending on the OS version.

🕵🏽‍♀️ Where does gdi32full.dll come into this?

As @_Kudaes_ pointed out, gdi32full.dll is leveraging the delay loading feature for the TextShaping.dll library.

Here we can see it specified from the DUMPBIN command

f\> dumpbin /IMPORTS gdi32full.dll

Dumpbin command

The gdi32full.dll library refers to the "GDI Client DLL". According to Microsoft's documentation, this library is responsible for rendering graphical elements on the screen, such as text and images. So… pretty much a huge portion of applications would make use of this library. Now, this library is not vulnerable just because it's using delay-loaded imports. The main issue is that because gdi32full.dll is only calling TextShaping.dll by name, there's no configuration that specifies the fully qualified path of this DLL to load or to search for it on its known directory. Instead, Windows’ dynamic-link library search order kicks-in, which makes the TextShaping.dll library susceptible to be hijacked if the program loading this DLL is not performing a secure search order implementation in its code.

🧐 How can this type of DLL Hijack occur?

Well, my dear Watson, when a library is called without specifying its absolute path, Windows will try to search for this library in order to load it and make it accessible to a program (you can check out the current DLL search order here). Below is an illustration on the default search order.

default search order

As seen on the above image, one of the places Windows will check is the executable's folder or the folder where the application was loaded from. If this folder’s permission allow any authenticated user to write to it, an attacker could drop a malicious DLL in this folder with the same name as the legitimate one Windows is looking for. The executed program would then load the malicious DLL instead.

🥴 Ok, so is this bad?

It's not ideal, that's for sure! If an application’s code is not performing safe DLL search order methods, it could easily be leveraged by an attacker to perform DLL hijacking. This type of attack is extremely common on Windows systems and different techniques exist on how to hijack a DLL. For this specific blog post, I’m only going to focus on the search order hijack when an application allows for malicious DLL that try to impersonate legitimate Windows DLLs to load from the application's directory.

This type of technique is still common among threat actors. Not so long ago (2022), Palo Alto’s unit42 discovered an ISO file in VirusTotal that they believe is tied to APT29. This ISO file, after mounted, would show a Windows shortcut file (.lnk) trying to pose as a Microsoft Word document containing a person’s “resume”. Interestingly enough, the ISO had multiple hidden files. This included a legitimate (and signed) binary for OneDrive Updater (OneDriveUpdater.exe), a legitimate version of the version.dll library (renamed by the APT as vresion.dll) and a malicious “impersonating” DLL called version.dll. Attackers leveraged this “Uncontrolled Search Path Element” weakness on that version of OneDriveUpdater.exe binary to execute malicious code that would ultimately install Brute Ratel C4. I highly encourage checking out unit42’s report on their analysis of this malicious file.

Thankfully, applications behave differently in how they would call the TextShaping.dll library, so this trick may not be as attractive to attackers… unless they know of applications that call this DLL with minimal interaction. In that case, it’s game on.

@_Kudaes_ mentioned in his thread a couple of vulnerable programs, such as Process Hacker, and CherryTree. Now, not all applications that are leveraging gdi32full.dll are vulnerable. But the ones that are not implementing methods to avoid these types of attacks are. I'll mention some methods to prevent this type of vulnerability later on in this post. But first! Let's dive into how the exploitation of this vulnerability looks, and how we can detect this.

💻 How to Exploit

The first thing that I did was generate my malicious payload, so I could test this technique. I decided to use msfvenom to build a meterpreter payload

msfvenom output

I then set up my Metasploit console to listen for my Meterpreter payload:

metasploit output

Now the next step was to get the payload on my "victim machine" or lab VM. In the spirit of transparency, I was feeling lazy, so I just dropped the DLL on my machine's current user downloads folder 😬. An attacker, of course, would implement other ways to deliver this payload unto the victim's machines. For example, through a phishing email (similar to the earlier resume example). For testing, I just moved it over to my VM.

I then started looking for potentially vulnerable applications that were already running on my Windows 10 lab machine. For this, I used Process Monitor (❤️) and filtered on the below:

procmon filter

I tested a couple of applications already running on my VM to see how they would behave with my malicious DLL on their executable folders, making sure to only target executables running out of non-elevated paths. This means directories where a non-admin user has permissions to write files to (i.,e, C:\User\<username>\Documents, %APPDATA%, etc), since it would make it easier to plant my malicious DLL.

The good news is most of the applications I was testing with were not vulnerable to this. I then decided to check against applications that were popular among different groups I’m part of. I started testing with these tools and found a couple that were susceptible to this exploit. I would like to focus on the AutoHotKey application. I did not find the AutoHotKey executable itself to be affected by this issue, but the setup executable was.

As I mentioned earlier, I had dropped my malicious TextShaping.dll payload on my Downloads folder. After AutoHotKey's installer (AutoHotkey_2.0.2_setup.exe) finished downloading and was made available on my Downloads folder, I ran the executable. But ruh roh! I noticed that as soon as I ran the installer, I got a Meterpreter session opened!


Analyzing the Process Monitor entries, I saw the setup executable called my fake TextShaping.dll library which I had placed earlier on my Downloads folder. I tried this technique with a non-admin user, and saw the TextShaping.dll library is loaded before UAC kicks in. This does not mean it’s elevating privileges, but that the application calls gdi32full.dll, which then calls TextShaping.dll to open a Windows dialog that prompts the user to start AutoHotKey program installation. In order words, this initial dialog prompt causes TextShaping.dll to load as soon as the program is executed. Therefore, minimal interaction is needed to make the AutoHotKey installer load the malicious DLL.

Because the installer called my fake DLL which did not contain any of the legitimate DLL’s functionality, the installer itself did not open or run at all. I moved my DLL out of the Downloads path and installed the AutoHotKey application successfully. I then tried to perform a similar exploit within the executable's path, but as you can see below, it was successfully calling the legitimate binary from the C:\Windows\SysWOW64\ and C:\Windows\System32\ directories:

ahk_download File dropped on the application's path

ahk_exec Legitimate TextShaping.dll library being called by the AutoHotKey PE

🕵️How to Detect

I'm running Sysmon on my lab VM with Olaf Hartong's sysmon-modular research configuration (and FileBlockExecutable disabled) . There are multiple things we can detect based on this attack:

  1. DLL Search Order Hijack

  2. Evidence of Meterpreter Payload

In this blog, I'm only going to focus on # 1.

Since this attack focuses on "impersonating" a real executable in an abnormal location, we should look for instances when the "TextShaping.dll" library was loaded and the path of this library is not under C:\Windows\SysWOW64\ or C:\Windows\System32\. Below, you can see how this library was loaded from the C:\Users\groot\Downloads\ directory


Thankfully, Sysmon has an event ID that will provide us with the exact information we're looking for… Event ID 7 would trigger every time a module is loaded in a specific process. As you can see below, Sysmon logged my malicious DLL being loaded by the AutoHotKey installer


🛡️ How can it be prevented?

Microsoft has released some good guidelines on how to prevent DLL Search Order Hijack vulnerabilities. I'm pasting a few of these below, but more details can be found in Microsoft's documentation:

  • Use DLL redirection or a manifest to specify the DLLs to load

  • Enable safe DLL search mode

  • Implement absolute paths for calls to functions that require a module to be loaded (LoadLibrary, CreateProcess, etc)

  • Use the LOAD_LIBRARY_SEARCH flags from the LoadLibraryEx function to implement a search order for your program.

That's it folks! I hope you enjoyed reading this, and huge kudos to Kurosh Dabbagh for this cool finding!


  • Kurosh Dabbagh (@_Kudaes_) for the detailed thread on his finding
  • Bryan Alexander (@dronesec) for his research on abusing Delay-load DLLs
  • itm4n’s input on Windows DLL hijacking (I always refer to this post when talking about DLL hijacking)
  • Microsoft team cause I was able to find good documentation on their site about this 🙏



  • Process Monitor
  • Sysmon
  • Sysmon-modular (@olafhartong)
  • Msfvenom
  • Msfconsole
  • Dumpbin
  • CFF Explorer

Vulnerability Disclosure

This uncontrolled search path element vulnerability was responsibly disclosed to AutoHotKey’s responsible parties on April 26th, 2023. The below GitHub issue was opened as requested by the AutoHotKey contributors team:

Uncontrolled Search Path Element vulnerability On AHK installer v2.0.2


Per Microsoft, delay-loaded libraries have a separate section on the /import list of a PE file, and are marked as delay-loaded imports. From the above dumpbin screenshot, we can see how dumpbin.exe dumped the import details of delay-loaded DLLs on its own separate segment. I was also able to see "DWrite.dll" and "mscms.dll" are also listed in this section. Noting these here to look into these DLLs as well in the future and see if they could be leveraged in the same way as TextShaping.dll for DLL hijacking oppotunities.

This post is licensed under CC BY 4.0 by the author.