Finding Object Roots in Vista (KPCR)

This is the third of a series of posts describing how  the volatility memory forensics application was ported to a new Windows operating system version.

Apart from the inevitable changes in kernel data structures which typically come with a new kernel version, Vista brought with it a change which broke one of volatility’s key techniques for identifying kernel objects. The change was Address Space Layout Randomisation (ALSR). Thanks to Gil Peterson for sharing this detail.

Structural interpretation approaches to volatile memory analysis rely on finding an initial kernel object from which one may traverse to other objects, in order to find  objects of interest to the investigator. With XP, volatility employed “the KPCR trick”. XP reliably stored the “Kernel Processor Control Region” at a fixed kernel virtual address (0xffdff000). From the KPCR structure, one then traverses intermediate structures (KdVersionBlock, then DebuggerDataList)  to access interesting structures such as the active process list.

In Vista, KPCR is not stored at a fixed address, so the first problem in porting volatility to Vista and above, to reliably get an initial reference to a valid KPCR structure.

Damien Aumaitre points out in his 2009 paper "A little journey inside Windows memory" that KPCR is self referencing. Based on this observation I undertook the following investigations:

1. I loaded up windbg to look at the KPCR of a XP dump file.

2. Set the symbol path

.sympath SRV*C:\dev\symbolcache\symbols*http://msdl.microsoft.com/download/symbols

.reload

3. Examined the KPCR

kd> !pcr
KPCR for Processor 0 at ffdff000:
    Major 1 Minor 1
    NtTib.ExceptionList: ed89dcf0
        NtTib.StackBase: ed89ddf0
       NtTib.StackLimit: ed89a000
     NtTib.SubSystemTib: 00000000
          NtTib.Version: 00000000
      NtTib.UserPointer: 00000000
          NtTib.SelfTib: 7ffdf000

                SelfPcr: ffdff000
                   Prcb: ffdff120
                   Irql: 00000000
                    IRR: 00000000
                    IDR: ffffffff
          InterruptMode: 00000000
                    IDT: 8003f400
                    GDT: 8003f000
                    TSS: 80042000

          CurrentThread: 86724020
             NextThread: 00000000
             IdleThread: 80552740

              DpcQueue:

4. Note that the first line indicates that KPCR is at VA 0xffdff000, which is to be expected. Note also that the SelfPcr attribute (at offset 0x1c from the start of the structure) has the same value at the address of the KPCR. This is what Aumaitre means by self referencing. There exists an additional self referencing property here related to the Prcb field which I will not go into.

5. Repeating the above on a Vista image gives the following. Note that the KPCR structure is not at 0xffdff000, and again, that the SelfPcr field points to the KPCR address.

kd> !pcr
KPCR for Processor 0 at 818f4700:
    Major 1 Minor 1
    NtTib.ExceptionList: 9a7bfcf0
        NtTib.StackBase: 00000000
       NtTib.StackLimit: 00000000
     NtTib.SubSystemTib: 80148000
          NtTib.Version: 000c3fac
      NtTib.UserPointer: 00000001
          NtTib.SelfTib: 7ffdf000

                SelfPcr: 818f4700
                   Prcb: 818f4820
                   Irql: 00000000
                    IRR: 00000000
                    IDR: ffffffff
          InterruptMode: 00000000
                    IDT: 822eb400
                    GDT: 822eb000
                    TSS: 80148000

          CurrentThread: 89d5eac0
             NextThread: 00000000
             IdleThread: 818f8300

              DpcQueue:

6. I checked the offsets for the SelfPcr as below:

kd> dt -r0 _KPCR 818f4700
ntdll!_KPCR
   +0×000 NtTib            : _NT_TIB
   +0×000 Used_ExceptionList : 0x9a7bfcf0 _EXCEPTION_REGISTRATION_RECORD
   +0×004 Used_StackBase   : (null)
   +0×008 Spare2           : (null)
   +0x00c TssCopy          : 0×80148000 Void
   +0×010 ContextSwitches  : 0xc3fac
   +0×014 SetMemberCopy    : 1
   +0×018 Used_Self        : 0x7ffdf000 Void
   +0x01c SelfPcr          : 0x818f4700 _KPCR
   +0×020 Prcb             : 0x818f4820 _KPRCB
   +0×024 Irql             : 0 ”
   +0×028 IRR              : 0
   +0x02c IrrActive        : 0
   +0×030 IDR              : 0xffffffff
   +0×034 KdVersionBlock   : 0x818f3c18 Void
   +0×038 IDT              : 0x822eb400 _KIDTENTRY
   +0x03c GDT              : 0x822eb000 _KGDTENTRY
   +0×040 TSS              : 0×80148000 _KTSS
   +0×044 MajorVersion     : 1
   +0×046 MinorVersion     : 1
   +0×048 SetMember        : 1
   +0x04c StallScaleFactor : 0×962
   +0×050 SpareUnused      : 0 ”
   +0×051 Number           : 0 ”
   +0×052 Spare0           : 0 ”
   +0×053 SecondLevelCacheAssociativity : 0 ”
   +0×054 VdmAlert         : 0
   +0×058 KernelReserved   : [14] 0
   +0×090 SecondLevelCacheSize : 0
   +0×094 HalReserved      : [16] 0
   +0x0d4 InterruptMode    : 0
   +0x0d8 Spare1           : 0 ”
   +0x0dc KernelReserved2  : [17] 0

Scanning KPCR in Vista memory dumps

With the former in mind, I set about writing a volatility scanner that scans the kernel address space for potential KPCR structures. I note here that in my development I have relied on dump files generated by Matthieu Suiche’s win32dd. Dump files store the physical address of the kernel page directory base, which is enough to reconstruct the kernel address space, however, other means will be necessary if operating on raw (DD) style memory images.

The scanner runs through each kernel address space memory region, looking for memory patterns that match the following constraints:

  1. The VA of the start of candidate bytes  >= 0×80000000 (i.e. it is in the kernel address space)
  2. The SelfPcr field at offset 0x1c from the start of the candidate bytes contains a pointer to the virtual address of the start of the KPCR structure
  3. The Prcb field at offset 0×20 within the structure contains a pointer to the start of the _KPRCB structure, which is embedded within the KPCR structure at offset 0×120.

I have observed the above scanning technique to identify one KPCR value per processor, which is consistent with the described function of the KPCR – it is a per processor structure.

Usage

The above scanner is usable as the volatility command kpcrscan, and the output of it used via the parameter –kpcr=

An example of usage is presented in the screen capture below:

image

No related posts.

Related posts brought to you by Yet Another Related Posts Plugin.

One Response to “Finding Object Roots in Vista (KPCR)”

  1. [...] kernel variables in Windows XP [PDF] Re: How to get the path/filename from a driver name [WEB] Finding Object Roots in Vista (KPCR) Share this:TwitterFacebookLike [...]

Leave a Reply