August 25, 2021

%appdata% is a mistake — Introducing Invoke-DLLClone

Combining DLL metadata cloning, export table copying, and fake code-signing into a single PowerShell workflow for DLL hijacking operations.

Originally published on redteamer.tips


Two days ago a tweet from vxunderground linked a paper: An Empirical Assessment of EDR Systems against APT Attack Vectors. Being a red teamer this obviously piqued my interest, as evading EDRs is kinda what I do for a living.

The whole whitepaper is very interesting but for the sake of this blogpost I want to focus on the fact that according to the paper, DLL hijacking still circumvents a lot of EDRs. From experience, this very much aligns with what I have been seeing during operations as well.

It is due to this article that I started thinking about operational security considerations that could (and should) be taken when doing this kind of attack.

I started looking at available tooling and quickly encountered a familiar name on GitHub — Joe Vest. For those of you that are not aware, Joe has taken over Raphael Mudge’s place as lead for Cobalt Strike. He developed a PowerShell script called metatwin that utilizes Resource Hacker in the backend to copy metadata from one binary onto another. It can also copy signatures of these binaries (obviously invalidating them in the process) using SigThief. Pretty neat!

Another cool project that is often used in DLL hijacking attacks is called Koppeling by Nick Landers (monoxgas). The cool thing about Koppeling is that it can clone export tables of DLLs onto other DLLs after compilation. This means that you don’t have to recompile your malicious DLL over and over, resolving export forwards.

These two projects are awesome, and provide decent opsec when combined, so I merely glued them together in Invoke-DLLClone.

As a final quality of life feature, I also included my own LazySign project to provide the user the option to not just clone signatures, but fake sign binaries with whatever company name they desire (obviously, these signatures will not be valid though).

%localappdata% AKA the stupidest folder ever

One of the primary reasons DLL search order hijacking is so darn effective is because some software gets installed in %localappdata%. Coincidentally, most of this software is used for web communications (Teams, Discord, Slack, WebEx, OneDrive).

Fun fact, %localappdata% is… user writeable. What could possibly go wrong…

Let’s find out, shall we? Let’s fire up Discord with procmon attached to the sucker.

Applications look for their dependencies in their current folder first — there is a whole search order that has been explained on countless other blogs about this topic. Take a pick of a DLL that is not found. In this example I chose powrprof.dll.

Note: always TEST your candidate DLL. Not all DLLs work!

Now all we need to do is create a DLL that avoids Loader Deadlock. An interesting project that can help with that is slaeryan’s aquarmory template. Or Vivek’s template.

Freshly compiled, your DLL probably looks quite different from a legitimate system DLL — no metadata, no version info, no signature. How can we fix this problem? Easy!

Once you have your malicious payload DLL compiled, we can use Invoke-DLLClone using the legitimate DLL as a source and our evil.dll as a target:

Invoke-DllClone -Source C:\Windows\SysWOW64\powrprof.dll -Target C:\Users\Jean\source\repos\SideLoadInjector\Release\totallylegitpowrprof.dll -Output powrprof.dll -Sign

A new folder in the Invoke-DLL directory will be created containing both a signed and unsigned copy of your DLL (which now carries the metadata, exports, and signature of the original).

Note: Discord is a 32-bit application on my system, so I took the powrprof.dll in SysWOW64 instead of System32.

Shells, shells everywhere

Now all we have to do is drop our new powrprof.dll in the Discord directory we identified earlier and restart Discord. And…

Shells. Literally everywhere.

If you implement this technique, implement logic to only execute your malicious thread once — how to do that is an exercise for the reader.


Check out Invoke-DLLClone on GitHub.