Uninformed: Informative Information for the Uninformed

Vol 6» 2007.Jan


Expanded Set of DPC Routines

Other protection mechanisms used in PatchGuard version 2 include an expanded set of DPC routines used to arrange for the execution of the PatchGuard integrity check routine. Recall that in PatchGuard version 1, there existed a set of three possible DPC routines. In PatchGuard version 2, this set of potential DPC routines that can be repurposed for PatchGuard's use has been expanded to ten possibilities. One DPC routine is selected at boot time from this set of ten possiblities, and from that point is used for all further PatchGuard operations for the lifetime of the session. The fact that only one DPC routine is used in a particular Windows session is a weakness that is inherited from the previous PatchGuard version (as the reader will discover, eventually comes in handy if one is set on bypassing PatchGuard). The DPC routine to be used for the current boot session is selected in the nt!SepAdtInitializePrivilegeAuditing routine, much the same as how the bogus pooltag to be used for all PatchGuard allocations is selected:

INIT:0000000000832741:
PatchGuard_Pick_Random_DPC:
;
; Use the time stamp counter as a random seed.
;
rdtsc
shl     rdx, 20h
mov     rcx, r15
or      rax, rdx
xor     rcx, rax
lea     rax, [rsp+0A28h+var_360]
xor     rcx, rax
mov     rax, rcx
ror     rax, 3
xor     rcx, rax
mov     rax, 7010008004002001h
mul     rcx
mov     [rsp+0A28h+var_360], rax
mov     rcx, rdx
mov     qword ptr [rsp+0A28h+arg_260], rdx
xor     rcx, rax
mov     rax, 0CCCCCCCCCCCCCCCDh
mul     rcx
shr     rdx, 3
;
; The resulting value in `rax' is the index into a switch jump table
; that is used to locate the DPC to be repurposed for initiating
; PatchGuard checks for this session.
;
lea     rax, [rdx+rdx*4]
add     rax, rax
sub     rcx, rax
jmp     PatchGuard_DPC_Switch

INIT:0000000000832317:
PatchGuard_DPC_Switch:
;
; The address of the case statement is formed by adding the image base (here,
; being loaded into `rdx') and an RVA in the table indexed by rax.
;
lea     rdx, cs:400000h
mov     eax, ecx
;
; Locate the case statement RVA by indexing the jump offset table.
;
mov     ecx, [rdx+rax*4+432E60h]
;
; Add it to the image base to form a complete 64-bit address.
;
add     rcx, rdx
;
; Execute the case handler.
;
jmp     rcx


;
; The set of case statements are as follows:
;
; Each case statement block simply loads the full 64-bit address
; of the DPC routine to be repurposed for PatchGuard checks into
; the r8 register.  This register is later stored into one of
; PatchGuard's internal data structures for future use.
;

lea     r8, CmpEnableLazyFlushDpcRoutine
jmp     short PatchGuardSelectDpcRoutine
lea     r8, _CmpLazyFlushDpcRoutine
jmp     short PatchGuardSelectDpcRoutine
lea     r8, ExpTimeRefreshDpcRoutine
jmp     short PatchGuardSelectDpcRoutine
lea     r8, ExpTimeZoneDpcRoutine
jmp     short PatchGuardSelectDpcRoutine
lea     r8, ExpCenturyDpcRoutine
jmp     short PatchGuardSelectDpcRoutine
lea     r8, ExpTimerDpcRoutine
jmp     short PatchGuardSelectDpcRoutine
lea     r8, IopTimerDispatch
jmp     short PatchGuardSelectDpcRoutine
lea     r8, IopIrpStackProfilerTimer
jmp     short PatchGuardSelectDpcRoutine
lea     r8, KiScanReadyQueues
jmp     short PatchGuardSelectDpcRoutine
lea     r8, PopThermalZoneDpc
;
; (fallthrough from last case statement)
;
INIT:0000000000832800:
PatchGuardSelectDpcRoutine:
xor     ecx, ecx
;
; Store the DPC routine into r14+178.  r14 points to one of
; the PatchGuard context structures in this particular instance.
;
mov     [r14+178h], r8

Much like PatchGuard version 1, each of the DPCs selected for use in launching the PatchGuard integrity checks has a legitimate function. Furthermore, the DPC routines are ones that are important for normal system operation, thus it is not possible for one to simply detect all DPCs that refer to these DPC routines and cancel them. Instead, much as with PatchGuard version 1, if one wanted to go the route of blocking PatchGuard's DPC, a mechanism to detect the particular PatchGuard DPC (as opposed to the legitimate system invocations thereof) must be developed. This aspect of PatchGuard's obfuscation mechanisms is relatively similar to version 1, other than the logical extension to ten DPCs instead of three DPCs.