Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Possible to prevent certain process from getting themed ? #9

Closed
ghost opened this issue Apr 10, 2020 · 4 comments
Closed

Possible to prevent certain process from getting themed ? #9

ghost opened this issue Apr 10, 2020 · 4 comments
Assignees
Labels
wontfix This will not be worked on

Comments

@ghost
Copy link

ghost commented Apr 10, 2020

As what I see the way of patching is by injecting DLLs so theme related api calls are redirected. Now that OneNote UI is broken with third party theme. Is there any way to ignore onenote.exe so its appearance remains unpatched ?
image

Trying to use a fake dll simply doesn't work.
image

@namazso
Copy link
Owner

namazso commented Apr 10, 2020

Please see #7 (comment)
Also, the patch this program makes is done in winlogon.exe and it's simply returning TRUE in CryptVerifySignature regardless of input whenever we're called by the theme dlls, everything else about themes is done by windows on it's own, without injection.
Also, for VerifierDlls to get looked at you need GlobalFlag have 0x100 bit set, and it does not support paths, only dlls in system32. Regardless, even if you would've gotten it right it wouldn't do a thing.

@namazso
Copy link
Owner

namazso commented Apr 10, 2020

As for a update on looking for a way to apply themes per-process, it is simply not possible in any meaningful way. See for example FillRect(HDC, LPCRECT, HBRUSH)'s handling of system brushes:
image
As you can see the brush pseudohandle is mapped to a real handle through an array in gpsi (a global pointing at a tagSERVERINFO mapped read-only into all processes containing lots of user32 stuff). We can easily confirm this is set by tracking user32!SetSysColors (win32u!NtUserSetSysColors -> win32kbase!NtUserSetSysColors -> win32kbase!xxxSetSysColors -> win32kbase!SetSysColor) where a brush is created and saved into gpsi, to an array of same offset (and the RGB value is also saved):
image
The problems this causes are pretty bad:

  • There is no single handle converting function, or any point of code where all conversion passes through. Therefore we'd have to hook all functions taking brush handles. Just user32.dll alone has 2485 exports, and it grows and changes every feature update, and then there's the others like gdi32.dll.
  • You could say "then let's try the other side, surely at some point the brush handle is passed to kernel, we just compare and swap there". Unfortunately this is not so simple. Many syscalls take HBRUSHes directly, again, never passing through a single codepath (at least in usermode). My copy of win32u.dll contains 1242 syscall stubs, and these are also changing and growing each feature update, so hooking these is out of the question.
  • The last alternative would be not focusing on code, but rather on data. A simple approach would be putting a page guard on *(gpsi), or maybe just changing gpsi to point at invalid memory, then just emulating all accesses via a Vectored Exception Handler. Unfortunately gpsi is accessed far too much, and this would presumably have a very big overhead, since we'd break on all accesses to it, not just when resolving brush pseudohandles. A more granular version of this could be utilizing the debug registrs, however we only have 4 of those, each watching at most 8 bytes. This means we'd be able to watch at most 8 of the 32 system brushes (and we haven't even considered the RGB values saved yet!) which is far from enough.

With these we exhausted all conventional options we had for replacing system brushes per-process. With the last method we could discover all gpsi access sites and hook them, then possibly JIT compile some code or use an x86 emulator to interruptlessly replace the colors, but the complexity of these solutions is far over of what I'm willing to make.

An alternative I could offer is faking high contrast themes, which have dark versions by default, and some software explicitly checks for it. This is for example win32calc.exe, when high contrast is faked:
image
(Without, for comparison:)
image

I haven't yet tested OneNote with this since I don't have it installed.

@ghost
Copy link
Author

ghost commented Apr 11, 2020

alright that's unexpected, I didn't know about how hard that is, guess I've asked something too difficult to do.
You may add add issue to FAQ in project home page so others can see it.

@namazso
Copy link
Owner

namazso commented Apr 19, 2020

added to the FAQ.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
wontfix This will not be worked on
Projects
None yet
Development

No branches or pull requests

1 participant