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.

Inserting data into other processes’ address space, part 1a

I never thought I will write the part 1a of my old post, but here it is.

As usual, I have not explored the below topic in-depth, but have certainly noticed the opportunities and since this is how many interesting developments start, I guess it is still worth … talking…

How do we copy data between processes?

In my old post I have listed a number of inter-process data exchange ideas, but I missed the one that I believe is the most important — at least in 2022 — the non-native stuff. And by that, I mean all these proprietary mechanisms of data exchange that have been developed over the years by vendors different than Microsoft. Many, of course, utilizing the core components of Windows OS, and the very same inter-process communication and cross-process access API functions. Being the ‘genuine’ software and all that, I bet it had to somehow pop up on the radar, and the be filtered out, with time by the likes of AV, EDR, and any other ‘watchmen’… cuz it’s genuine. It’s a stretch, of course, but to their credit, security solutions are getting better and better at detecting any sort of trickery…

With that in mind I started poking around DLLs of known vendors.

I soon discovered a DLL from NVidia (NvIFR.dll) that offers a particular set of exported functions:

  • NvIFR_ConnectToCrossProcessSharedSurfaceEXT
  • NvIFR_CopyFromCrossProcessSharedSurfaceEXT
  • NvIFR_CopyFromSharedSurfaceEXT
  • NvIFR_CopyToCrossProcessSharedSurfaceEXT
  • NvIFR_CopyToSharedSurfaceEXT
  • NvIFR_Create
  • NvIFR_CreateCrossProcessSharedSurfaceEXT
  • NvIFR_CreateEx
  • NvIFR_CreateSharedSurfaceEXT
  • NvIFR_DestroyCrossProcessSharedSurfaceEXT
  • NvIFR_DestroySharedSurfaceEXT
  • NvIFR_GetSDKVersion

hmmm Cross-Process, Shared, and Connect To, and Copy … that certainly sounds interesting!

I don’t have access to any native Nvidia setup, and I don’t play games, so it’s hard to test what these functions really do :(. Quick google for NvIFR_ConnectToCrossProcessSharedSurfaceEXT brought only this interesting reddit conversation.

Poking around the available code, we can speculate that Cross-process Surface interface seems to be accessible via this pipe:

\.\pipe\NVIFR_CPSS_%lld

After you write “[\x7F” to it, you can read a buffer of 2136 bytes (in the DLL version I looked at). The buffer we can then read will contain a name of the shared section we can now open, map, and … hopefully write to. The analysis of the code that follows is not straightforward, there are other DLLs being loaded, APIs resolved, and the complexities encountered would really benefit from ‘live’ analysis, but… c’est la vie.

And this is where this blurb ends. I know, I know, it’s not much, but imagine the possibilities. We can find more similar pieces of code, legitimate, genuine software, and cross-process data exchange snippets present inside these signed DLLs or executables… we may as well come up with many new ways of bypassing security solutions that might have not been possible in the past…