Yes… how to call SetWindowBand?
This article will be subdivided into 2 parts.
typedef BOOL(WINAPI* NtUserEnableIAMAccess)(
IN ULONG64 key,
IN BOOL enable);
typedef BOOL(WINAPI* NtUserAcquireIAMKey)(
OUT ULONG64* pkey);
typedef BOOL(WINAPI* SetWindowBand)(
IN HWND hWnd,
IN HWND hwndInsertAfter,
IN DWORD dwBand);
typedef BOOL SetShellWindow(
IN HWND hwnd)
Part 1: Using explorer.exe via DLL injection
You need to use detours (or any library that redirects function calls).
Example for accessing SetWindowBand function via DLL injection via explorer.exe (github.com)
How it works?
For SetWindowBand to work requires that IAM have access to the current thread. To enable access we need a key and that key can only be caught with a hook.
To put it simply, we inject our dll into explorer, wait until explorer makes a call to
NtUserEnableIAMAccess which at this point is a detoured function, save the key so we can use it later, detach the hook and then we can finally call SetWindowBand (after enabling IAM access).
Part 2: Using another broker via DLL injection WITHOUT running explorer.exe
This part will be detailed soon (or whenever I have a bit of time)
TL;DR: You need a broker that is MS signed and has “.imrsiv” data section. Call SetShellWindow (this is important), the call NtUserAcquireIAMKey and save the key. Finally use NtUserEnableIAMAccess BEFORE calling SetWindowBand (must be on the same thread, test it yourself 🙂 ).
Thanks to Matthew for finding out that SetShellWindow/Ex creates an IAM key internally.
This article was made 1 year ago, sorry for not publishing it earlier but I didn’t have time to proofread and check for any possible issue :/
3 thoughts on “How to call SetWindowBand”
Waiting for part 2.
Method is a bit messy imo. In windows 10, it was easy to find CPrivilegedPresentationOperations vtable address in code section but they changed it with Win11, now you need to search in memory but still doable and requires no hooking. With that vtable, you can get IAMKey (kinda unneccessary) and also you can just call 4th func which is SetWindowBand does all the job for you, if you want you can also hook WndProc to use sendmessage from another app with needed params in order to call it anytime you want, benefit of doing this is WndProc runs on GUI thread which has an IAM thread.
Alternatively you can go kernelmode and it’s much more simpler, its after ExStyles2 just set it and works. I also tried setting ZBID_IMMERSIVE_RESTRICTED from kernel, it makes other windows crash 🙂
One question is how did you find the ZBID enum? I couldn’t find it in pdbs.
Can You give example, how to find CPrivilegedPresentationOperations vtable and how to go kernelmode and “after ExStyles2 just set it”?