Win32k Elevation of Privilege in ResetDC [CVE-2021-40449, CallbackHell]

We discussed this vulnerability during Episode 96 on 02 November 2021

Always a fun issue to see, the root of it being that a user-mode callback during a ResetDC (Reset Device Context) can unexpectedly tamper with the device context data that the kernel thinks will be stable.

ResetDC as a function updates a specified printer or plotter device context (DC). Internally it seems that it does this by freeing the old one and allocating a new device context. A user-mode application calls ResetDC, eventually reaching GreResetDCInternal in the kernel. This function get a pointer to a device context object and calls hdcOpenDCW which will execute a user-mode callback. During this callback the attacker can unexpectedly trigger another call to ResetDC on the same handle again kicking off the above process a second time.

Ignoring the second run’s callback, allowing the second call of ResetDC to proceed normally will result in the current device context (the one the first call has a pointer to) being freed. Once the second call finished, the first callback can return, and will have a use-after-free due to the dangling pointer to the device context.