DLL ForwardSideloading

Some DLLs export functions (via export table) that are just forwarding execution to functions implemented in other libraries. It’s a very common practice and one of the most known forwards are:

kernel32.dll HeapAlloc -> NTDLL.RtlAllocateHeap
kernel32.dll HeapReAlloc -> NTDLL.RtlReAllocateHeap
kernel32.dll HeapSize -> NTDLL.RtlSizeHeap

Now, most of us assume that lots of forwards redirect the execution to most popular Windows DLLs, and these are typically just your regular KnownDLLs: ntdll, kernelbase, ole32, etc. — ones that are on the KnownDLLs list + very often already loaded into memory.

I decided to check what forwards we can find on the Win 11 OS, because I had a cunning plan: If I can find a forward that does not redirect to KnownDlls, then I can execute an indirect DLL sideloading, one that is on par with traditional EXE sideloading technique.

Meaning?

Use a signed rundll32.exe to load a signed DLL that will then load the payload DLL of our choice… by using that exported function.

This is a list of forwards I have generated.

We can quickly identify a non-KnownDlls pair, where:

keyiso.dll KeyIsoSetAuditingInterface -> NCRYPTPROV.SetAuditingInterface

So, copying keyiso.dll to c:\test, and then placing a payload in NCRYPTPROV.dll in the same folder, and then finally executing:

rundll32.exe c:\test\keyiso.dll, KeyIsoSetAuditingInterface

will load a copy of the keyiso.dll first, then the function resolution of KeyIsoSetAuditingInterface will resolve it first to NCRYPTPROV.SetAuditingInterface forward, and then automatically load the NCRYPTPROV.dll, and only then execute the function’s code. In the example below, I didn’t bother to implement SetAuditingInterface in the test DLL, just to showcase the execution flow leading to (actually misleading, since it refers to the outer DLL/API name combo) ‘missing API’ message box.

The DLLMain_64_DLL_PROCESS_ATTACH.txt file is created by the test payload, indicating its DllMain function has been executed.

Obviously, this technique does not need to rely on OS libraries. I am pretty sure that a bigger study of exported functions from a larger corpora of signed DLLs will yield a set of combos that can be used to implement this technique.

Rundll32 and Phantom DLL lolbins

This may be a new, kinda ephemereal addition to the lolbin world (not sure if anyone covered it before).

Windows 11 comes with a large number of DLLs – some of which are broken.

DuCsps.dll on Windows 11 Pro 22H2

The DuCsps.dll imports 2 APIs from UpdateAPI.dll:

  • GetInstalledPackageInfo, and
  • FreeInstalledPackageInfo.

The problem is that there is no UpdateAPI.dll. It may be present in other versions of Windows, but it’s not present in 22H2 (note: I have not tested all the subversions, so YMMV).

tssrvlic.dll on Windows 11 Pro 22H2

The same goes for tssrvlic.dll that imports 3 APIs from a non-existing TlsBrand.dll:

  • RDSGetProductAccessRights,
  • W2K3ADPUCALDetailsCreator, and
  • RDSProductDetailsCreator

They both create a lolbin opportunity via a missing phantom DLL, and an attacker can simply bring in their versions of malicious UpdateAPI.dll or TlsBrand.dll, and then run (from the same directory where these payloads are located) the following rundll32 commands:

rundll32 DuCsps.dll, foo

rundll32 tssrvlic.dll, bar

where foo and bar can be anything.

See below: