Beating the dead horse, only to inject it some more…

The windows shatter attack is so old that it’s time for someone to reinvent it.

This someone could be me.

While looking at wscadminui.exe I noticed that it expects 2 arguments: the first one is a /DefaultProductRequest string, and the second is also a string (a name of an app).

When these are provided, the program calls wscapi.dll::wscLaunchAdminMakeDefaultUI API and passes the app name to it. The wscLaunchAdminMakeDefaultUI in turn, passes the app name to another function called wscShowAMSCNEx. The latter creates a window of a class AMNotificationDialog.

So, running:

wscadminui.exe /DefaultProductRequest foobar

will start the wscadminui.exe process and it will create the AMNotificationDialog window for us:

With that in place, we can look at the window procedure handling the messages for the AMNotificationDialog window:

You can see that it is using WM_NCCREATE message to set a Window Long Pointer at offset 0 to a value provided in that windows message (lParam). What attracts our attention more though is that the very same value is later used as a function pointer — in other words, whatever the offset the Window Long Ptr @0 points to, the code at this offset will be executed!

So, one could inject code into wscadminui.exe process and then execute it using a simple call to SetWindowLongPtr API:

  WinExec ("wscadminui.exe /DefaultProductRequest foobar",0);
  Sleep(1000);
  HWND x = FindWindow("AMNotificationDialog", "");
  if (x != NULL)
  	{
  		SetWindowLongPtr (x, 0, 0x123456789ABCDEF);
  		ShowWindow (x, SW_SHOW);
  	}

Now, the very same program invocation:

wscadminui.exe /DefaultProductRequest foobar

leads to a creation of another window — this time it is of an ANIMATION_TIMER_HWND class (you can see it on the screenshot above). This window’s lifecycle is handled by the UIAnimation.dll, and this is where we can find the implementation of the window’s procedure handling messages for it:

Again, we can easily manipulate this GWLP_USERDATA pointer – a simple snippet like the one below can redirect code execution of the scapegoat wscadminui.exe to the pointer of our liking:

  WinExec ("wscadminui.exe /DefaultProductRequest foobar",0);
  Sleep(1000);
  HWND x = FindWindow("ANIMATION_TIMER_HWND", "");
  if (x != NULL)
  	{
  		SetWindowLongPtr (x, GWLP_USERDATA, 0x123456789ABCDEF);
  		ShowWindow (x, SW_SHOW);
  	}

As usual, there are more examples like this out there, but the point I want to make is that over 20 years after the window shatter attack was described for the first time it is still available to attackers in many forms and places.

Procmonning the Win11_24H2 build

This is a bunch of random notes from running Procmon on Win11_24H2 build.

We all know about autorun.inf that OS is checking when we attach a new device to the system, but on new devices the system is actually looking for more files — here’s the list:

  • \Device\HarddiskVolumeN\audio_ts\audio_ts.ifo
  • \Device\HarddiskVolumeN\autorun.inf
  • \Device\HarddiskVolumeN\AVCHD
  • \Device\HarddiskVolumeN\BDAV
  • \Device\HarddiskVolumeN\BDMV
  • \Device\HarddiskVolumeN\bootex.log
  • \Device\HarddiskVolumeN\DCIM
  • \Device\HarddiskVolumeN\desktop.ini
  • \Device\HarddiskVolumeN\dvd_rtav\vr_mangr.ifo
  • \Device\HarddiskVolumeN\EFI\Microsoft\Boot\BCD
  • \Device\HarddiskVolumeN\EFI\Microsoft\Boot\BCD.LOG
  • \Device\HarddiskVolumeN\EFI\Microsoft\Boot\Policies\UnlockToken.pol
  • \Device\HarddiskVolumeN\PRIVATE\AVCHD
  • \Device\HarddiskVolumeN\Recovery.txt
  • \Device\HarddiskVolumeN\SVCD\entries.svd
  • \Device\HarddiskVolumeN\SVCD\entries.vcd
  • \Device\HarddiskVolumeN\System Volume Information
  • \Device\HarddiskVolumeN\System Volume Information\AadRecoveryPasswordDelete
  • \Device\HarddiskVolumeN\System Volume Information\ClientRecoveryPasswordRotation
  • \Device\HarddiskVolumeN\System Volume Information\FveDecryptedVolumeFolder
  • \Device\HarddiskVolumeN\VCD\entries.vcd
  • \Device\HarddiskVolumeN\video_ts\video_ts.ifo
  • \Device\HarddiskVolumeN\WinReOfflineScanningResult.dat

Some of them are obviously media-related, some are Windows Backup-related, and some … I have no clue.

The other interesting bit is that when executed, lsass.exe is trying to load a phantom DLL named “”.dll:

  • C:\Windows\””.DLL
  • C:\Windows\System\””.DLL
  • C:\Windows\System32\””.DLL

While it looks like an attractive proposition, I am not sure if there is a way to exploit it 🙁 Still, need to come back to it to understand why the process is doing so. Perhaps there is a new data dumping opportunity here, somewhere…

There are a lot of new phantom DLLs, but they are tricky to play with. While writing this post I messed up this build’s booting so many times that I no longer understand which of these test phantom DLLs I added to the system contributed to the damage 🙂 I have added a list of potentials at the bottom of this post.

Then there is smss.exe trying to find these:

  • C:\Windows\apppatch\drvpatch.sdb
  • C:\Windows\System32\wowarmhw.dll
  • C:\Windows\System32\xtajit.dll
  • C:\Windows\System32\xtajit64.dll
  • C:\Windows\System32\xtajit64se.dll
  • C:\Windows\SysWOW64\wow64.dll
  • C:\Windows\SysWOW64\wow64base.dll
  • C:\Windows\SysWOW64\wow64con.dll
  • C:\Windows\SysWOW64\wow64win.dll
  • C:\Windows\SysWOW64\xtajit64.dll
  • C:\Windows\SysWOW64\xtajit64se.dll

Then spoolsv.exe trying to access these:

  • C:\Windows\System32
  • C:\Windows\System32\spool
  • C:\Windows\System32\spool\drivers
  • C:\Windows\System32\spool\drivers\ARM64
  • C:\WINDOWS\system32\spool\drivers\ARM64\3\New\
  • C:\WINDOWS\system32\spool\drivers\ARM64\3\Old\
  • C:\WINDOWS\system32\spool\drivers\ARM64\4\New\
  • C:\WINDOWS\system32\spool\drivers\ARM64\4\Old\
  • C:\Windows\System32\spool\drivers\IA64
  • C:\WINDOWS\system32\spool\drivers\IA64\3\New\
  • C:\WINDOWS\system32\spool\drivers\IA64\3\Old\
  • C:\Windows\System32\spool\drivers\W32X86
  • C:\Windows\System32\spool\drivers\W32X86\3\New
  • C:\Windows\System32\spool\drivers\W32X86\3\Old
  • C:\Windows\System32\spool\drivers\x64
  • C:\Windows\System32\spool\drivers\x64\3\New
  • C:\Windows\System32\spool\drivers\x64\3\Old
  • C:\WINDOWS\system32\spool\drivers\x64\4\New\
  • C:\WINDOWS\system32\spool\drivers\x64\4\Old\
  • C:\Windows\System32\spool\PRINTERS
  • C:\Windows\System32\spool\SERVERS
  • C:\Windows\System32\ualapi.dll
  • C:\Windows\System32\vfprint.dll

There seems to be a lot of cross-architectural code logic present here that needs further exploration.

There also seem to be more phantom DLL loading opportunities that are only available under specific conditions:

  • C:\Windows\System32\Unknown.DLL (loaded by svchost.exe when AFAICT there is no network connectivity)
  • C:\WINDOWS\SYSTEM32\windowsdefender:\.DLL – a potential phantom DLL but impossible due to file/ADS naming limitations

And finally, there is really a lot of paths the OS is trying to access in the procmon log that suggests some incoherent environment variable parsing:

  • C:\Windows\System32\%ProgramFiles(arm)%
  • C:\WINDOWS\system32\%systemroot%\system32\wbem\cimwin32.dll
  • C:\WINDOWS\system32\%systemroot%\system32\wbem\wmipcima.dll
  • C:\WINDOWS\%WINDIR%\System32\SPP\Migration\sppgenmig.dat
  • C:\WINDOWS\%WINDIR%\System32\SPP\Migration\sppmig.dat
  • C:\Windows\System32\%SystemRoot%\ProgramData\Microsoft\Windows\AppRepository\Packages\MicrosoftWindows.Client.AIX_1000.26100.29.0_x64__cw5n1h2txyewy\ActivationStore.dat
  • C:\Windows\SystemApps\Microsoft.Windows.StartMenuExperienceHost_cw5n1h2txyewy\%SystemRoot%\ProgramData\Microsoft\Windows\AppRepository\Packages\MicrosoftWindows.Client.AIX_1000.26100.29.0_x64__cw5n1h2txyewy\ActivationStore.dat
  • C:\WINDOWS\%WINDIR%\System32\SPP\Migration\sppgenmig.dat
  • C:\WINDOWS\system32\%systemroot%\system32\wbem\wmiprov.dll
  • C:\Users\<USER>\Desktop\%1
  • C:\Users\Public\Desktop\%1

That’s a lot of sideloading and potential LPE vulns to explore…

The full list of possible phantom DLLs can be found here (win11_24H2_phantom_dlls.txt). Some of them are obvious path problems, but many are real phantom DLLs.