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.

Beyond good ol’ Run key, Part 150

I decided to add this post to this old series, but the scope of this post is – as you will find out soon – much wider.

You will find servercoreshell.exe program to be present on both Windows Server 2022 and 2025. It is an interesting binary, because it does a lot of stuff that, well… makes it interesting!

When you execute it, it displays the following screen:

I have not explored these options.

Because… the far more interesting things happen under the hood. If you start Process Monitor before you execute servercoreshell.exe program and then look at the events collected during a single test session you will find out that some of them are… well.. interesting!

It accesses a lot of interesting Registry locations, including:

  • HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\Explorer\DisableCurrentUserRunOnce
  • HKCU\Software\Microsoft\Windows\CurrentVersion\RunOnce
  • HKLM\Software\Microsoft\Windows\CurrentVersion\RunOnce
  • HKLM\Software\Microsoft\Windows\CurrentVersion\RunOnceEx
  • HKLM\Software\WOW6432Node\Microsoft\Windows\CurrentVersion\RunOnceEx
  • HKLM\SOFTWARE\Microsoft\ServerCore\Shell Launcher\Shell
  • HKLM\SOFTWARE\Microsoft\ServerCore\Shell Launcher\<SID>\Shell
  • HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\ServerCore\Shell Launcher\Users\Local\<user>\Shell
  • HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\ServerCore\Shell Launcher\Users\Domain\<user>\Shell

And that HKLM\SOFTWARE\Microsoft\ServerCore\Shell Launcher\Shell is a DEFAULT persistent location that allows me to put this post in the Beyond good ol’ Run key series:

For starters, we can modify the content of the file c:\WINDOWS\System32\servercoreshelllaunch.bat. We can also change the value of the Registry entry that shell points to. Then the only remaining bit is to ensure the servercoreshell.exe program is executed at some time during system start, or after user logs in.

Bad news though — need Trusted Installer rights for that.

Still, this single program runs through many ‘shell’ initialization routines that Windows Symbols describe as:

  • ProcessHKLMRunOnce
  • _RunStartupGroup
  • ProcessPackagedStartupTasks
  • ProcessRun6432
  • LaunchCustomShellAndWait

During my tests, I played around and pointed some of the aforementioned registry settings to calculator, notepad, etc. and I discovered that the servercoreshell.exe program often goes into a never-ending loop. When you launch it, then kill the main window, it will just continue to spawn its own copies. And when I set shell value to a randomly named user under HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\ServerCore\Shell Launcher\Users\Domain\<user>\Shell to calculator, I ended up with a never-ending loop of new Calculator instances being spawn:

I suspect it’s a little buggy…

I also believe the servercoreshell.exe program is related to this documented Shell Launcher feature:

Shell Launcher is a Windows feature that you can use to replace the default Windows Explorer shell (Explorer.exe) with a Windows desktop application or a Universal Windows Platform (UWP) app. This feature is useful for creating a custom user experience on devices that are used for a specific purpose, including kiosks, ATMs, and digital signage.

Installing the latter on Windows 11 introduces a slightly different executable to the system though: ShellLauncherConfig.exe and the shell keys it relies on are located in a different place too:

  • HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Embedded\Shell Launcher
  • HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Embedded\Shell Launcher cached

Looks like the feature has at least 2 different, distinctive versions for server and non-server versions of Windows.