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.

Beyond good ol’ Run key, Part 149

This post is a nothing burger. I didn’t make it work, but I still want to document it.

When I came across a ‘GPExtensionDLL’ entry expected under

HKLM\SYSTEM\CurrentControlSet\Services\MPSSVC\Parameters

I got excited, because it looked like a typical undocumented registry entry that can be abused for persistence.

After setting it up, as usual, to point to my test DLL I restarted the system only to discover the system … crashing.

After a few back and forth, it downed on me that the code that loads that DLL is surrounded by other code that relies on code pointers expected to be hard coded to point to proper function addresses, which is not always the case, hence system BSODs after calls to a null pointer-based function.

So, does this entry deserve to be even mentioned in this series?

I think so.

We cannot exclude the possibility someone will figure it out better than me, there is always an opportunity to stop the execution after the main DLL module is loaded, and in general, one of the goals of this series is to document ALL possible persistence mechanisms out there, no matter how difficult it is to actually take advantage of them…