Uninformed: Informative Information for the Uninformed

Vol 3» 2006.Jan


Implementation

The anti-patching technology provided in the Windows x64 kernel, nicknamed PatchGuard, is intended to protect critical kernel structures from being modified outside of the context of approved modifications, such as through Microsoft-controlled hot patching. At the time of this writing, PatchGuard is designed to protect the following critical structures:

  • SSDT (System Service Descriptor Table)
  • GDT (Global Descriptor Table)
  • IDT (Interrupt Descriptor Table)
  • System images (ntoskrnl.exe, ndis.sys, hal.dll)
  • Processor MSRs (syscall)

At a high-level, PatchGuard is implemented in the form of a set of routines that cache known-good copies and/or checksums of structures which are then validated at certain random time intervals (roughly every 5 - 10 minutes). The reason PatchGuard is implemented in a polling fashion rather than in an event-driven or hardware-backed fashion is because there is no native hardware level support for the things that PatchGuard is attempting to accomplish. For that reason, a number of the tricks that PatchGuard resorted to were done so out of necessity.

The team that worked on PatchGuard was admittedly very clever. They realized the limitations of implementing an anti-patching model in a fashion described in the introduction and thus were forced to resort to other means by which they might augment the protection mechanisms. In particular, PatchGuard makes extensive use of security through obscurity by using tactics like misdirection, misnamed functions, and general code obfuscation. While many would argue that security through obscurity adds nothing, the authors believe that it's merely a matter of raising the bar high enough so as to eliminate a significant number of people from being able to completely understand something.

The code to initialize PatchGuard begins early on in the boot process as part of nt!KeInitSystem. The diagram in figure [*] shows roughly where in the boot process it's initialized.

Figure: PatchGuard initialization vector
\includegraphics{fig-init-stack}

And that's where the fun begins.



Subsections