Systray Guid Icon Spoofing - whats the purpose of this when its now super easy to hijack systray icons?

Tags: #<Tag:0x00007f224fcf3348>

So here NotificationIcon Sample (Windows) | Microsoft Learn

It say

Notification icons specified with a GUID are protected against spoofing by validating that only a single application registers them. This registration is performed the first time you call Shell_NotifyIcon(NIM_ADD, …) and the full path name of the calling application is stored. If you later move your binary file to a different location, the system will not allow the icon to be added again.

TLDR if you know the guid to a systray icon, you can hijack and control any systray icon from a different app - arguably the complete opposite of the spoofing claim in the link above!!!

To display an icon in the system tray a handle to an icon needs to be provided.
A single app can have one or more icons visible in the systray.
Each systray instance displaying an icon can also share a single window handle & callback procedure or have its own window handle and callback procedure to intercept and process windows messages generated by the user interacting with the corresponding systray icon.

Upto Win7 the uID in the NOTIFYICONDATAA (shellapi.h) - Win32 apps | Microsoft Learn is the unique identifier used to control a systray icon or the space where an icon would appear because its not mandatory to display an icon!
Win7 onwards, the GuidItem is recommended for use to control the systray icons, although the uID will still work on Win10 if no guiditem is specified, I guess for backwards compatibility reasons.

So I dont really see what the Guiditem brings to the table from Win7 onwards, other than it prevents an app which has the guiditem hard coded in the app from being moved from one folder to another.

If your app does use the same guid and you try to move it or copy it to a different location, a windows error will get thrown: namely 2147500037 which doesnt appear in this list of windows error codes Tutorial - Debug system error codes - Win32 apps | Microsoft Learn as the last windows error code is

ERROR_API_UNAVAILABLE - 15841 (0x3DE1) - This API cannot be used in the context of the caller’s application type.

As it happens my apps generate a new guid everytime it loads the icons from various sources, so the user can move an app to a different location and also choose what icons are used in the systray.

So apart from providing a stealth way of preventing an app being moved to a different folder if it happens to use the same “hardcoded” guid and systray icon, I cant see the purpose of this functionality.

Likwise, another app using only the same guid can control the systray icons from the 1st app, in other words its possible to hijack a systray icon if you know its guid which is the opposite of whats being claimed in the 1st MS link.

It seems all thats needed is knowledge of the guid, they dont even need the same handles to icons and windows or callback procedure addresses in order to hijack the systray icons on display, and then play with users!

So does anyone know why this guiditem is now recommend use?


So its also possible to hijack the systray icons using the old hwnd + uID way. All it needs is matching hwnd and uid and you can take control of the systray icon. Interestingly, the NOTIFYICONDATA can even have different memory locations, from different exe’s to control the user notifications.

So next test is to see what else I can get the systray notifications to do…

Its also an insight into how joined up or not this api is with other parts of the OS.


One other implication is, its really easy scanning exe’s and dll’s for guid’s using a regex unlike getting a runtime api assigned handle and uID, but there is nothing stopping us from using a new guid everytime an icon is loaded from the exe/dll resource section, or from other file locations.

Either way, its possible to have some fun with these window notification popup messages for other apps running in the systray. :rofl:

Perhaps you need to search the hex representation of that value.

Best I can find is its a DB error in things like
Error 80004005 when using ADO or ODBC to connect an Access database - Office | Microsoft Learn
You may receive error code 0x80004005 or other error codes when you try to start a Windows XP-based computer (

The former could be true considering the guids are added once and there is no way to remove the guid from the OS.

Given time, I might be able to stuff many many guids into this Shell_NotifyIcon(NIM_ADD, …) api and work out which file is storing them or where its stored on the hard drive, I do know some system folders are hidden away to most OS processes, but you can find them from the installation files and if some group policies are not enabled, it could be possible to get to them.

So at this stage it appears to be possible to hijack the callback process, which makes me wonder if its possible to obtain the security token of other processes like the networking systray icon, wifi systray icon and other OS level things.

The other test, is to see if I can get notifications off a website to the systray notifications, and if so, to see how far I can get in to hijack a process using web push notification.

RFC 8030: Generic Event Delivery Using HTTP Push (

because it appears that you dont even need MS Edge to be open or running to send web based notifications, but this might be separate to shell notify icon.
Improving notifications and badging in Microsoft Edge - Microsoft Edge Blog (

Its all a bit vague tbh so still working through it all.

Worst case scenario is it could be a zero click way into a system after visiting a website.


Its an hresult and there is a very interesting video at this link which explains these in more details because I just got an E_INVALIDARG One or more arguments are not valid 0x80070057 for a different api.
HRESULT Error Codes | Microsoft Learn

The original error when I use the same guid throws this.
E_FAIL Unspecified failure 0x80004005

I’m using the CoCreateGuid and CreateUUID api to get my guids/uids stuffed into a group type conforming to the multi element layout for a guid/uuid.

Cant say if the E_Fail is the correct error message though.

Not sure this is it, but would make sense if it’s a failure code of some kind.

E_ComputerSaysNo could be it.

I’ve seen that error code here… Little Britain USA - S01E02 - Computer Says No - YouTube