Rendered at 16:02:15 GMT+0000 (Coordinated Universal Time) with Cloudflare Workers.
drdexebtjl 16 hours ago [-]
Interesting framing that hooking functions is considered “rogue” by Microsoft, or something you’re “not authorized” to do, when Microsoft themselves makes the detours library and never framed it like this before.
Also, missing from this explanation: hooks are usually applied per process, from user space. The code pages in a dynamic library are CoW’d from the shared page when you write to them to apply a patch.
Does the Windows Update work similarly, or does it somehow modify the original, shared page, affecting all processes? Does a hook in a single process disable hot patching on the entire system?
ack_complete 12 hours ago [-]
They've also used Detours within Windows itself. The auto super resolution (AutoSR) feature works by dxgi.dll detouring specific calls in user32.dll, in-process, to virtualize certain monitor metrics. I found this out because it was broken for a while on Windows 11 ARM64 when it couldn't handle PAC-enabled function prologs and enabling it would just crash programs by corrupting user32 functions.
pjmlp 7 hours ago [-]
This has been a thing since the whole Windows MinWin project.
Why would they need runtime patching instead of just replacing the legacy DLLs with ones that redirect to the new ones?
saagarjha 14 hours ago [-]
Hooking code you don’t own is typically playing with fire. Because Microsoft wrote the code, they’re generally in a better position to understand when it is safe to do so.
drdexebtjl 13 hours ago [-]
It is perfectly safe to hook any code as long as you can guarantee no thread is currently executing the instructions you're replacing.
saagarjha 12 hours ago [-]
Safety means more than torn writes
jonhohle 17 hours ago [-]
At a previous job I wrote a docker build for patching individual Java class files on top of a monolithic docker image. This was not runtime patching, but allowed a single layer that was only a few kilobytes to be deployed quickly in emergency situations.
Interestingly, it had similar constraints and checked them at build time: it could not be a public ABI change and only one patch at a time.
itintheory 15 hours ago [-]
Was it for the log4shell vulnerability? I did something similar there.
If your hotpatching library is competent, then it does everything atomically. Either by suspending all threads first and temporarily resuming them while they're executing any affected instructions, or by just using atomics when possible.
In which case there is no race condition.
high_na_euv 4 hours ago [-]
>There is a race condition: The prescan may show that all the functions are safe to patch, but then somebody might patch a function after the prescan completes. In that case, the patcher will get halfway through and then discover the rogue-patched function, and now it’s kind of stuck. It can’t continue forward, and it can’t reliably roll back (because the rollback is probably also going to fail because the patch got overpatched). You’re stuck with a binary in memory that is half-patched, and who knows what’ll happen now.
Ehh :) scenarios like this are the best
vlovich123 14 hours ago [-]
What happens if two consecutive updates try to hot patch the same function? Wouldn’t this be completely within the realm of possibility and be a pure Microsoft issue with no one else involved?
Dwedit 15 hours ago [-]
Detouring can be done for already detoured functions. Just look at Steam Overlay vs other systems that hook into Direct3D, they can coexist.
drdexebtjl 12 hours ago [-]
Any idea of how that's done? In particular, how do multiple systems synchronize the installation of their hooks?
I've made my own hooking library that lets multiple plug-ins hook the same function, but it only works decently because it has this central library synchronizing access.
apple1417 11 hours ago [-]
If you use OBS, a game capture works the same way, it hooks the DirectX (or whatever API) functions to grab the rendered scene directly. It often has issues picking up overlays because there isn't really any synchronisation, just whatever made the last detour fires first. Like the sibling commit says, you can stack detours, it's only an issue for OBS if something that runs after it renders more things to the screen.
There is a setting to make it pick up overlays, which works reasonably well, I'm not entirely sure how it's implemented.
Dwedit 56 minutes ago [-]
What an overlay does is hook the 'present' function, does more drawing, then calls the base 'present' function. It's easy enough to detect when a draw call happens during a call to 'present', that tells you that an overlay is active.
Then you're faced with the problem of how deep your hook is, you either want it to run early (before other hooks), or late (after other hooks but before actual function). When you're trying to capture the overlay, you want your hook to run late.
The cop-out is to hook D3DKMTPresent instead and hope nobody else hooked it.
quotemstr 12 hours ago [-]
Detours rewrites instructions at the start of the detoured function. Why should it know or care whether the instructions it's overwriting happen to be ones written by a previous detour? Why would you need to synchronize?
drdexebtjl 4 hours ago [-]
1) Thread A could read the original instructions immediately before thread B replaces them. Thread A’s trampoline would contain the original instructions, not the instructions from thread B, so it would bypass thread B’s hook.
2) Thread A reads original instructions while thread B is replacing them, such that it reads part of an original instruction and part of a replaced instruction. Thread A’s trampoline would have nonsensical instructions.
dezgeg 8 hours ago [-]
Doesn't the Microsoft implementation work by having nop instruction as the first instruction of the function, which can then be patched to a jump to the patched code, that finally jumps back to the original function past the NOP?
Naive implementation of this scheme doesn't allow stacking.
Dwedit 1 hours ago [-]
If you have the standard two-byte backwards jump pointing to a longer jump instruction, you also have another happy case for overriding it (just change the long jump).
Meanwhile, the Microsoft Detours library supports detouring other kinds of instructions at the beginning of a function. It's not exclusively for the 'two byte nop and blank space' thing.
fragmede 17 hours ago [-]
The world could use more hot patching. Now that AI upends computer security, getting software patched in a timely fashion is more important than ever, and having to reboot/restart the process or computer to get those updates is more of a problem than it was before.
Firerouge 16 hours ago [-]
Agreed, it would be nice if it was more straightforward to set up self hosted hot patching on arbitrary Linux distros
traverseda 15 hours ago [-]
Super easy to override software on nixos.
CoastalCoder 17 hours ago [-]
I genuinely cannot tell if you're joking.
fragmede 17 hours ago [-]
I don't understand the joke. My background is worked at Ksplice a long time ago, patching the Linux kernel for security fixes without having to reboot.
mauvehaus 16 hours ago [-]
It's been at least 20 years, and Microsoft's blogging platform still doesn't support previous/next post links. Makes it goddamn hard to read the prior series about hot patching if it's not at the top of the blog.
icepush 15 hours ago [-]
There actually used to be links, but they broke every time the blog platform was moved and eventually were taken out.
arcanemachiner 15 hours ago [-]
Missed opportunity for Microsoft to rewrite the whole blog in React Native.
j45 16 hours ago [-]
It’s like mixing two different hot sauces, ymmv.
bitwize 12 hours ago [-]
Or loading two different TSRs in DOS
pjmlp 7 hours ago [-]
That one used to be "fun" to track down, especially since most of them were coded in Assembly.
Also, missing from this explanation: hooks are usually applied per process, from user space. The code pages in a dynamic library are CoW’d from the shared page when you write to them to apply a patch.
Does the Windows Update work similarly, or does it somehow modify the original, shared page, affecting all processes? Does a hook in a single process disable hot patching on the entire system?
https://en.wikipedia.org/wiki/MinWin
https://techcommunity.microsoft.com/blog/windowsosplatform/o...
Detours like technology is used in API Sets, to redirect legacy DLLS into the new refactored ones.
https://learn.microsoft.com/en-us/windows/win32/apiindex/win...
Interestingly, it had similar constraints and checked them at build time: it could not be a public ABI change and only one patch at a time.
In which case there is no race condition.
Ehh :) scenarios like this are the best
I've made my own hooking library that lets multiple plug-ins hook the same function, but it only works decently because it has this central library synchronizing access.
There is a setting to make it pick up overlays, which works reasonably well, I'm not entirely sure how it's implemented.
Then you're faced with the problem of how deep your hook is, you either want it to run early (before other hooks), or late (after other hooks but before actual function). When you're trying to capture the overlay, you want your hook to run late.
The cop-out is to hook D3DKMTPresent instead and hope nobody else hooked it.
2) Thread A reads original instructions while thread B is replacing them, such that it reads part of an original instruction and part of a replaced instruction. Thread A’s trampoline would have nonsensical instructions.
Naive implementation of this scheme doesn't allow stacking.
Meanwhile, the Microsoft Detours library supports detouring other kinds of instructions at the beginning of a function. It's not exclusively for the 'two byte nop and blank space' thing.