Uninformed: Informative Information for the Uninformed

Vol 2» 2005.Sept

Case Study: Windows NT SharedUserData

With all the generic background information out of the way, a real world practical use of this technique can be illustrated through an analysis of a region of memory that happens to be found in every process on Windows NT+. This region of memory is referred to as SharedUserData and has a backward compatible format for all versions of NT, though new fields have been appended over time. At present, the data structure that represents SharedUserData is _KUSER_SHARED_DATA which is defined as follows on Windows XP SP2:

   +0x000 TickCountLow     : Uint4B
   +0x004 TickCountMultiplier : Uint4B
   +0x008 InterruptTime    : _KSYSTEM_TIME
   +0x014 SystemTime       : _KSYSTEM_TIME
   +0x020 TimeZoneBias     : _KSYSTEM_TIME
   +0x02c ImageNumberLow   : Uint2B
   +0x02e ImageNumberHigh  : Uint2B
   +0x030 NtSystemRoot     : [260] Uint2B
   +0x238 MaxStackTraceDepth : Uint4B
   +0x23c CryptoExponent   : Uint4B
   +0x240 TimeZoneId       : Uint4B
   +0x244 Reserved2        : [8] Uint4B
   +0x264 NtProductType    : _NT_PRODUCT_TYPE
   +0x268 ProductTypeIsValid : UChar
   +0x26c NtMajorVersion   : Uint4B
   +0x270 NtMinorVersion   : Uint4B
   +0x274 ProcessorFeatures : [64] UChar
   +0x2b4 Reserved1        : Uint4B
   +0x2b8 Reserved3        : Uint4B
   +0x2bc TimeSlip         : Uint4B
   +0x2c0 AlternativeArchitecture : _ALTERNATIVE_ARCHITECTURE_TYPE
   +0x2c8 SystemExpirationDate : _LARGE_INTEGER
   +0x2d0 SuiteMask        : Uint4B
   +0x2d4 KdDebuggerEnabled : UChar
   +0x2d5 NXSupportPolicy  : UChar
   +0x2d8 ActiveConsoleId  : Uint4B
   +0x2dc DismountCount    : Uint4B
   +0x2e0 ComPlusPackage   : Uint4B
   +0x2e4 LastSystemRITEventTickCount : Uint4B
   +0x2e8 NumberOfPhysicalPages : Uint4B
   +0x2ec SafeBootMode     : UChar
   +0x2f0 TraceLogging     : Uint4B
   +0x2f8 TestRetInstruction : Uint8B
   +0x300 SystemCall       : Uint4B
   +0x304 SystemCallReturn : Uint4B
   +0x308 SystemCallPad    : [3] Uint8B
   +0x320 TickCount        : _KSYSTEM_TIME
   +0x320 TickCountQuad    : Uint8B
   +0x330 Cookie           : Uint4B

One of the purposes of SharedUserData is to provide processes with a global and consistent method of obtaining certain information that may be requested frequently, thus making it more efficient than having to incur the performance hit of a system call. Furthermore, as of Windows XP, SharedUserData acts as an indirect system call re-director such that the most optimized system call instructions can be used based on the current hardware's support, such as by using sysenter over the standard int 0x2e.

As can be seen right off the bat, SharedUserData contains a few fields that pertain to the timing of the current system. Furthermore, if one looks closely, it can be seen that these timer fields are actually updated constantly as would be expected for any timer variable:

0:000> dd 0x7ffe0000 L8
7ffe0000  055d7525 0fa00000 93fd5902 00000cca
7ffe0010  00000cca a78f0b48 01c59a46 01c59a46
0:000> dd 0x7ffe0000 L8
7ffe0000  055d7558 0fa00000 9477d5d2 00000cca
7ffe0010  00000cca a808a336 01c59a46 01c59a46
0:000> dd 0x7ffe0000 L8
7ffe0000  055d7587 0fa00000 94e80a7e 00000cca
7ffe0010  00000cca a878b1bc 01c59a46 01c59a46

The three timing-related fields of most interest are TickCountLow, InterruptTime, and SystemTime. These three fields will be explained individually later in this chapter. Prior to that, though, it is important to understand some of the properties of SharedUserData and why it is that it's quite useful when it comes to temporal addresses.