Overview

Alpc  = Advanced LPC Routines
Cc    = Cache Manager
Cm    = Config Manager
Dbgk  = Debugger Facilities
Em    = Errata Manager
Etw   = Event Tracing Facilities
Ex    = Executive Support Facilities
FsRtl = File System Runtime Library Facilities
Hvl   = Hypervisor Library Support Facilities 
Io    = I/O manager
Kd    = Kernel Debugger Facilities
Ke    = Internal Core routines
Ki    = Not exported kernel routines (i = internal)
Ldr   = Image Loading Facilities
Lpc   = Local Procedure Call Facilities
Lsa   = Local Security Authority Routines
Mm    = Memory Manager
Ob    = Object Manager
Pc    = Performance Counter Routines
Po    = Power Manager
Pp    = Plug and Play Manager
Ps    = Process & Thread Manager
Rtl   = Runtime Library Facilities Rtl 
Se    = Security Referenece Monitor
Wmi   = WMI routines

The Executive Subsystem deals with base OS features, such as memory management, process and thread management, security, I/O, networking, and inter-process communication.

The Kernel deals with low-level OS functions, such as thread scheduling, interrupts and exception dispatching, and multiprocessor synchronization.

Device drivers includes both hw and sw drivers and they usually translate user I/O calls into specific hardware device I/O requests.

The Hardware Abstraction Layer (HAL) is a layer of code that isolates the kernel, the device drivers, and the rest of the Windows executive from platform-specific hardware.

The main kernel files can be summed as follows:

File Name Components
Ntoskrnl.exe Executive and Kernel
Hal.dll HAL
Win32k.sys Kernel mode part of the GUI
*.sys in \SystemRoot\System32\Drivers Core driver files

Process and threads' most significant data structures are living both in user and kernel space, depending on their role and functionality.

Here a summary of the most important kernel structures and their role:

Kernel Structure Description
_EPROCESS executive process object
_KPROCESS kernel process object
_ETHREAD executive thread object
_KTHREAD kernel thread object
_KPCR Processor information
_KPRCB CPU state

Here is a summary of where are placed and how are interconnected together. Here is also an overview of how some process and thread structures are interlinked.

Let’s dive into processes realm now.

Process

As opposed to the *nix landscape, where a process is the one normally executing code, in the Windows world a process is just a container of resources used to execute the program. A thread is the entity actually running code. So what’s inside a process?

  • Private Address Space: gives each process the same address virtual space memory layout
  • Private Handle Table: resides in kernel memory and contains all handles to objects belonging to the process.
  • Access Token: security context used to access shared resources.
  • One or more threads: the one executing code. A process must have at least one thread.

Each process is managed by the Executive and it is represented by two objects, named EPROCESS and KPROCESS.

EPROCESS/KPROCESS

Executive Process Block (EPROCESS) is the principal process structure that resides in kernel and equivalent to the user mode counterpart *PEB If we inspect the lass process fromkdb, we can retrieve its EPROCESS value (in this case ffffd60b4aa5b240).

kd> !process  0 0 lsass.exe
PROCESS ffffd60b4aa5b240
    SessionId: 0  Cid: 02b4    Peb: fa07b9000  ParentCid: 0210
    DirBase: 3035d002  ObjectTable: ffff9d8f1e2cae80  HandleCount: 1230.
    Image: lsass.exe

And we can further analyze the structure (omitted for brevity)

kd> dt nt!_eprocess ffffd60b4aa5b240
   +0x000 Pcb              : _KPROCESS
    ...
   +0x360 Token            : _EX_FAST_REF
    ...
   +0x3f8 Peb              : 0x0000000f`a07b9000 _PEB
    ...
   +0x418 ObjectTable      : 0xffff880a`a4d56b40 _HANDLE_TABLE

The first field, the Pcb (Process Control Block) is the KPROCESS, that contains the PDA physical address that is placed in the CR3 register, together with kernel scheduling information like quantum, affinity and priority. We then have the PEB, which is pointing to user-land and won’t be covered here. Last, the ObjectTable which is ultimately pointing to the Handle Table

Let’s first inspect the KPROCESS structure further:

kd> dt  nt!_kprocess ffffd60b4aa5b240
   +0x000 Header           : _DISPATCHER_HEADER
   +0x018 ProfileListHead  : _LIST_ENTRY [ 0xffffd60b`4aa5b258 - 0xffffd60b`4aa5b258 ]
   +0x028 DirectoryTableBase : 0x3035d002
   +0x030 ThreadListHead   : _LIST_ENTRY [ 0xffffd60b`4aa5f378 - 0xffffd60b`505f5378 ]
   +0x040 ProcessLock      : 0
   +0x044 ProcessTimerDelay : 0
   +0x048 DeepFreezeStartTime : 0
   +0x050 Affinity         : _KAFFINITY_EX
   +0x0f8 ReadyListHead    : _LIST_ENTRY [ 0xffffd60b`4aa5b338 - 0xffffd60b`4aa5b338 ]
   +0x108 SwapListEntry    : _SINGLE_LIST_ENTRY
   +0x110 ActiveProcessors : _KAFFINITY_EX
   ...

Tokens

Token details of the current thread can be dumped by ANDING the current EPROCESS’s Token Object.

1: kd> dt nt!_EPROCESS  0xffffc789c7fa1480 Token.Object
   +0x360 Token        : 
      +0x000 Object       : 0xffff9f0b`dbdea777 Void

1: kd> !token @@C++(0xffff9f0b`dbdea777 & ~0xf)
_TOKEN 0xffff9f0bdbdea770
TS Session ID: 0x1
User: S-1-5-21-1552841522-3835366585-4197357653-1001
User Groups: 
 00 S-1-5-21-1552841522-3835366585-4197357653-513
    Attributes - Mandatory Default Enabled 
 01 S-1-1-0
    Attributes - Mandatory Default Enabled 
 02 S-1-5-114
    Attributes - Mandatory Default Enabled 
 03 S-1-5-32-544
    Attributes - Mandatory Default Enabled Owner 
 04 S-1-5-32-545
    Attributes - Mandatory Default Enabled 
 05 S-1-5-4
    Attributes - Mandatory Default Enabled 
 06 S-1-2-1
    Attributes - Mandatory Default Enabled 
 07 S-1-5-11
    Attributes - Mandatory Default Enabled 
 08 S-1-5-15
    Attributes - Mandatory Default Enabled 
 09 S-1-5-113
    Attributes - Mandatory Default Enabled 
 10 S-1-5-5-0-429296
    Attributes - Mandatory Default Enabled LogonId 
 11 S-1-2-0
    Attributes - Mandatory Default Enabled 
 12 S-1-5-64-10
    Attributes - Mandatory Default Enabled 
 13 S-1-16-12288
    Attributes - GroupIntegrity GroupIntegrityEnabled 
Primary Group: S-1-5-21-1552841522-3835366585-4197357653-513
Privs: 
 05 0x000000005 SeIncreaseQuotaPrivilege          Attributes - 
 08 0x000000008 SeSecurityPrivilege               Attributes - 
 09 0x000000009 SeTakeOwnershipPrivilege          Attributes - 
 10 0x00000000a SeLoadDriverPrivilege             Attributes - 
 11 0x00000000b SeSystemProfilePrivilege          Attributes - 
 12 0x00000000c SeSystemtimePrivilege             Attributes - 
 13 0x00000000d SeProfileSingleProcessPrivilege   Attributes - 
 14 0x00000000e SeIncreaseBasePriorityPrivilege   Attributes - 
 15 0x00000000f SeCreatePagefilePrivilege         Attributes - 
 17 0x000000011 SeBackupPrivilege                 Attributes - 
 18 0x000000012 SeRestorePrivilege                Attributes - 
 19 0x000000013 SeShutdownPrivilege               Attributes - 
 20 0x000000014 SeDebugPrivilege                  Attributes - 
 22 0x000000016 SeSystemEnvironmentPrivilege      Attributes - 
 23 0x000000017 SeChangeNotifyPrivilege           Attributes - Enabled Default 
 24 0x000000018 SeRemoteShutdownPrivilege         Attributes - 
 25 0x000000019 SeUndockPrivilege                 Attributes - 
 28 0x00000001c SeManageVolumePrivilege           Attributes - 
 29 0x00000001d SeImpersonatePrivilege            Attributes - Enabled Default 
 30 0x00000001e SeCreateGlobalPrivilege           Attributes - Enabled Default 
 33 0x000000021 SeIncreaseWorkingSetPrivilege     Attributes - 
 34 0x000000022 SeTimeZonePrivilege               Attributes - 
 35 0x000000023 SeCreateSymbolicLinkPrivilege     Attributes - 
 36 0x000000024 SeDelegateSessionUserImpersonatePrivilege  Attributes - 
Authentication ID:         (0,68d57)
Impersonation Level:       Anonymous
TokenType:                 Primary
Source: User32             TokenFlags: 0x2000 ( Token in use )
Token ID: c9b00            ParentToken ID: 0
Modified ID:               (0, c9af0)
RestrictedSidCount: 0      RestrictedSids: 0x0000000000000000
OriginatingLogonSession: 3e7
PackageSid: (null)
CapabilityCount: 0      Capabilities: 0x0000000000000000
LowboxNumberEntry: 0x0000000000000000
Security Attributes:
Unable to get the offset of nt!_AUTHZBASEP_SECURITY_ATTRIBUTE.ListLink
Process Token TrustLevelSid: (null)

Thread

A thread is a runtime abstraction of a program function and it encompasses of:

  • x2 stack (user and kernel mode)
  • Context (registers, flags)
  • Security Token (optional)
  • Priority (from 0 to 31)
  • State

To check default kernel stack size:

kd> dx *(int*)&nt!KeKernelStackSize
*(int*)&nt!KeKernelStackSize : 24576 [Type: int]

ETHREAD/KTHREAD

We can fetch some more details about threads, as usual viakd, by querying the target process with more details(0 2):

kd> !process 0 2 lsass.exe
PROCESS ffff8982c6e020c0
    SessionId: 0  Cid: 02a8    Peb: 8a95fdd000  ParentCid: 0200
    DirBase: 20ba46002  ObjectTable: ffffc407c2ceb080  HandleCount: 1531.
    Image: lsass.exe

        THREAD ffff8982c4fde080  Cid 02a8.02b8  Teb: 0000008a95fe2000 Win32Thread: 0000000000000000 WAIT: (WrLpcReceive) UserMode Non-Alertable
            ffff8982c4fde6d8  Semaphore Limit 0x1

And by querying the ETHREAD value from the !thread command we can obtain a fair amount of details, including priority values and various context switching statistics.

kd> !thread ffff8982c4fde080
THREAD ffff8982c4fde080  Cid 02a8.02b8  Teb: 0000008a95fe2000 Win32Thread: 0000000000000000 WAIT: (WrLpcReceive) UserMode Non-Alertable
    ffff8982c4fde6d8  Semaphore Limit 0x1
Not impersonating
DeviceMap                 ffffc407bee13360
Owning Process            ffff8982c6e020c0       Image:         lsass.exe
Attached Process          N/A            Image:         N/A
Wait Start TickCount      10663          Ticks: 378713 (0:01:38:37.390)
Context Switch Count      3              IdealProcessor: 0             
UserTime                  00:00:00.000
KernelTime                00:00:00.000
Win32 Start Address 0x00007ff633e64060
Stack Init ffffaf86f46c8c90 Current ffffaf86f46c84c0
Base ffffaf86f46c9000 Limit ffffaf86f46c3000 Call 0000000000000000
Priority 10 BasePriority 9 PriorityDecrement 0 IoPriority 2 PagePriority 5
Kernel stack not resident.

ETHREAD and KTHREAD are the thread counterpart for EPROCESS and KPROCESS, also managed by the Executive and Kernel respectively. In a similar fashion we can start dumping the whole ETHREAD struct:

kd> dt nt!_ETHREAD ffff8982c4fde080
   +0x000 Tcb              : _KTHREAD
   +0x600 CreateTime       : _LARGE_INTEGER 0x01d63cc3`98068727
   +0x608 ExitTime         : _LARGE_INTEGER 0xffff8982`c4fde688
   +0x608 KeyedWaitChain   : _LIST_ENTRY [ 0xffff8982`c4fde688 - 0xffff8982`c4fde688 ]
   +0x618 PostBlockList    : _LIST_ENTRY [ 0x00000000`00000000 - 0x00007ffd`1c7ace30 ]
   +0x618 ForwardLinkShadow : (null) 
   +0x620 StartAddress     : 0x00007ffd`1c7ace30 Void
   +0x628 TerminationPort  : (null) 
   +0x628 ReaperLink       : (null) 
   +0x628 KeyedWaitValue   : (null) 
   +0x630 ActiveTimerListLock : 0
   +0x638 ActiveTimerListHead : _LIST_ENTRY [ 0xffff8982`c4fde6b8 - 0xffff8982`c4fde6b8 ]
   +0x648 Cid              : _CLIENT_ID
   +0x658 KeyedWaitSemaphore : _KSEMAPHORE
   +0x658 AlpcWaitSemaphore : _KSEMAPHORE
   +0x678 ClientSecurity   : _PS_CLIENT_SECURITY_CONTEXT
   +0x680 IrpList          : _LIST_ENTRY [ 0xffff8982`c4fde700 - 0xffff8982`c4fde700 ]
   +0x690 TopLevelIrp      : 0
   +0x698 DeviceToVerify   : (null) 
   +0x6a0 Win32StartAddress : 0x00007ff6`33e64060 Void
   +0x6a8 ChargeOnlySession : (null) 
   +0x6b0 LegacyPowerObject : (null) 
   +0x6b8 ThreadListEntry  : _LIST_ENTRY [ 0xffff8982`c4fda738 - 0xffff8982`c4fe1738 ]
   +0x6c8 RundownProtect   : _EX_RUNDOWN_REF
   +0x6d0 ThreadLock       : _EX_PUSH_LOCK
   +0x6d8 ReadClusterSize  : 7
   +0x6dc MmLockOrdering   : 0n0
   +0x6e0 CrossThreadFlags : 0x5402
   +0x6e0 Terminated       : 0y0
   +0x6e0 ThreadInserted   : 0y1
   +0x6e0 HideFromDebugger : 0y0
   +0x6e0 ActiveImpersonationInfo : 0y0
   +0x6e0 HardErrorsAreDisabled : 0y0
   +0x6e0 BreakOnTermination : 0y0
   +0x6e0 SkipCreationMsg  : 0y0
   +0x6e0 SkipTerminationMsg : 0y0
   +0x6e0 CopyTokenOnOpen  : 0y0
   +0x6e0 ThreadIoPriority : 0y010
   +0x6e0 ThreadPagePriority : 0y101
   +0x6e0 RundownFail      : 0y0
   +0x6e0 UmsForceQueueTermination : 0y0
   +0x6e0 IndirectCpuSets  : 0y0
   +0x6e0 DisableDynamicCodeOptOut : 0y0
   +0x6e0 ExplicitCaseSensitivity : 0y0
   +0x6e0 PicoNotifyExit   : 0y0
   +0x6e0 DbgWerUserReportActive : 0y0
   +0x6e0 ForcedSelfTrimActive : 0y0
   +0x6e0 SamplingCoverage : 0y0
   +0x6e0 ReservedCrossThreadFlags : 0y00000000 (0)
   +0x6e4 SameThreadPassiveFlags : 0
   +0x6e4 ActiveExWorker   : 0y0
   +0x6e4 MemoryMaker      : 0y0
   +0x6e4 StoreLockThread  : 0y00
   +0x6e4 ClonedThread     : 0y0
   +0x6e4 KeyedEventInUse  : 0y0
   +0x6e4 SelfTerminate    : 0y0
   +0x6e4 RespectIoPriority : 0y0
   +0x6e4 ActivePageLists  : 0y0
   +0x6e4 SecureContext    : 0y0
   +0x6e4 ZeroPageThread   : 0y0
   +0x6e4 WorkloadClass    : 0y0
   +0x6e4 ReservedSameThreadPassiveFlags : 0y00000000000000000000 (0)
   +0x6e8 SameThreadApcFlags : 0
   +0x6e8 OwnsProcessAddressSpaceExclusive : 0y0
   +0x6e8 OwnsProcessAddressSpaceShared : 0y0
   +0x6e8 HardFaultBehavior : 0y0
   +0x6e8 StartAddressInvalid : 0y0
   +0x6e8 EtwCalloutActive : 0y0
   +0x6e8 SuppressSymbolLoad : 0y0
   +0x6e8 Prefetching      : 0y0
   +0x6e8 OwnsVadExclusive : 0y0
   +0x6e9 SystemPagePriorityActive : 0y0
   +0x6e9 SystemPagePriority : 0y000
   +0x6e9 AllowUserWritesToExecutableMemory : 0y0
   +0x6e9 AllowKernelWritesToExecutableMemory : 0y0
   +0x6e9 OwnsVadShared    : 0y0
   +0x6ec CacheManagerActive : 0 ''
   +0x6ed DisablePageFaultClustering : 0 ''
   +0x6ee ActiveFaultCount : 0 ''
   +0x6ef LockOrderState   : 0 ''
   +0x6f0 AlpcMessageId    : 0
   +0x6f8 AlpcMessage      : (null) 
   +0x6f8 AlpcReceiveAttributeSet : 0
   +0x700 AlpcWaitListEntry : _LIST_ENTRY [ 0xffff8982`c4fd6d68 - 0xffff8982`c4fd6d68 ]
   +0x710 ExitStatus       : 0n0
   +0x714 CacheManagerCount : 0
   +0x718 IoBoostCount     : 0
   +0x71c IoQoSBoostCount  : 0
   +0x720 IoQoSThrottleCount : 0
   +0x724 KernelStackReference : 1
   +0x728 BoostList        : _LIST_ENTRY [ 0xffff8982`c4fde7a8 - 0xffff8982`c4fde7a8 ]
   +0x738 DeboostList      : _LIST_ENTRY [ 0xffff8982`c4fde7b8 - 0xffff8982`c4fde7b8 ]
   +0x748 BoostListLock    : 0
   +0x750 IrpListLock      : 0
   +0x758 ReservedForSynchTracking : (null) 
   +0x760 CmCallbackListHead : _SINGLE_LIST_ENTRY
   +0x768 ActivityId       : (null) 
   +0x770 SeLearningModeListHead : _SINGLE_LIST_ENTRY
   +0x778 VerifierContext  : (null) 
   +0x780 AdjustedClientToken : (null) 
   +0x788 WorkOnBehalfThread : (null) 
   +0x790 PropertySet      : _PS_PROPERTY_SET
   +0x7a8 PicoContext      : (null) 
   +0x7b0 UserFsBase       : 0
   +0x7b8 UserGsBase       : 0
   +0x7c0 EnergyValues     : 0xffff8982`c4fde8a0 _THREAD_ENERGY_VALUES
   +0x7c8 CmDbgInfo        : (null) 
   +0x7d0 SelectedCpuSets  : 0
   +0x7d0 SelectedCpuSetsIndirect : (null) 
   +0x7d8 Silo             : 0xffffffff`fffffffd _EJOB
   +0x7e0 ThreadName       : (null) 
   +0x7e8 SetContextState  : (null) 
   +0x7f0 LastExpectedRunTime : 0xb28cf
   +0x7f4 HeapData         : 0
   +0x7f8 OwnerEntryListHead : _LIST_ENTRY [ 0xffff8982`c4fde878 - 0xffff8982`c4fde878 ]
   +0x808 DisownedOwnerEntryListLock : 0
   +0x810 DisownedOwnerEntryListHead : _LIST_ENTRY [ 0xffff8982`c4fde890 - 0xffff8982`c4fde890 ]
   .

And the KTHREAD as well

kd> dx -r1 (*((ntkrnlmp!_KTHREAD *)0xffff8982c4fde080))
(*((ntkrnlmp!_KTHREAD *)0xffff8982c4fde080))                 [Type: _KTHREAD]
    [+0x000] Header           [Type: _DISPATCHER_HEADER]
    [+0x018] SListFaultAddress : 0x0 [Type: void *]
    [+0x020] QuantumTarget    : 0x50e711f [Type: unsigned __int64]
    [+0x028] InitialStack     : 0xffffaf86f46c8c90 [Type: void *]
    [+0x030] StackLimit       : 0xffffaf86f46c3000 [Type: void *]
    [+0x038] StackBase        : 0xffffaf86f46c9000 [Type: void *]
    [+0x040] ThreadLock       : 0x0 [Type: unsigned __int64]
    [+0x048] CycleTime        : 0x6ed8a [Type: unsigned __int64]
    [+0x050] CurrentRunTime   : 0x0 [Type: unsigned long]
    [+0x054] ExpectedRunTime  : 0x2e939 [Type: unsigned long]
    [+0x058] KernelStack      : 0xffffaf86f46c84c0 [Type: void *]
    [+0x060] StateSaveArea    : 0xffffaf86f46c8cc0 [Type: _XSAVE_FORMAT *]
    [+0x068] SchedulingGroup  : 0x0 [Type: _KSCHEDULING_GROUP *]
    [+0x070] WaitRegister     [Type: _KWAIT_STATUS_REGISTER]
    [+0x071] Running          : 0x0 [Type: unsigned char]
    [+0x072] Alerted          [Type: unsigned char [2]]
    [+0x074 ( 0: 0)] AutoBoostActive  : 0x1 [Type: unsigned long]
    [+0x074 ( 1: 1)] ReadyTransition  : 0x0 [Type: unsigned long]
    [+0x074 ( 2: 2)] WaitNext         : 0x0 [Type: unsigned long]
    [+0x074 ( 3: 3)] SystemAffinityActive : 0x0 [Type: unsigned long]
    [+0x074 ( 4: 4)] Alertable        : 0x0 [Type: unsigned long]
    [+0x074 ( 5: 5)] UserStackWalkActive : 0x0 [Type: unsigned long]
    [+0x074 ( 6: 6)] ApcInterruptRequest : 0x0 [Type: unsigned long]
    [+0x074 ( 7: 7)] QuantumEndMigrate : 0x0 [Type: unsigned long]
    [+0x074 ( 8: 8)] UmsDirectedSwitchEnable : 0x0 [Type: unsigned long]
    [+0x074 ( 9: 9)] TimerActive      : 0x0 [Type: unsigned long]
    [+0x074 (10:10)] SystemThread     : 0x0 [Type: unsigned long]
    [+0x074 (11:11)] ProcessDetachActive : 0x0 [Type: unsigned long]
    [+0x074 (12:12)] CalloutActive    : 0x0 [Type: unsigned long]
    [+0x074 (13:13)] ScbReadyQueue    : 0x0 [Type: unsigned long]
    [+0x074 (14:14)] ApcQueueable     : 0x1 [Type: unsigned long]
    [+0x074 (15:15)] ReservedStackInUse : 0x0 [Type: unsigned long]
    [+0x074 (16:16)] UmsPerformingSyscall : 0x0 [Type: unsigned long]
    [+0x074 (17:17)] TimerSuspended   : 0x0 [Type: unsigned long]
    [+0x074 (18:18)] SuspendedWaitMode : 0x0 [Type: unsigned long]
    [+0x074 (19:19)] SuspendSchedulerApcWait : 0x0 [Type: unsigned long]
    [+0x074 (20:20)] CetUserShadowStack : 0x0 [Type: unsigned long]
    [+0x074 (21:21)] BypassProcessFreeze : 0x0 [Type: unsigned long]
    [+0x074 (31:22)] Reserved         : 0x0 [Type: unsigned long]
    [+0x074] MiscFlags        : 16385 [Type: long]
    [+0x078 ( 1: 0)] BamQosLevel      : 0x0 [Type: unsigned long]
    [+0x078 ( 2: 2)] AutoAlignment    : 0x0 [Type: unsigned long]
    [+0x078 ( 3: 3)] DisableBoost     : 0x0 [Type: unsigned long]
    [+0x078 ( 4: 4)] AlertedByThreadId : 0x0 [Type: unsigned long]
    [+0x078 ( 5: 5)] QuantumDonation  : 0x0 [Type: unsigned long]
    [+0x078 ( 6: 6)] EnableStackSwap  : 0x1 [Type: unsigned long]
    [+0x078 ( 7: 7)] GuiThread        : 0x0 [Type: unsigned long]
    [+0x078 ( 8: 8)] DisableQuantum   : 0x0 [Type: unsigned long]
    [+0x078 ( 9: 9)] ChargeOnlySchedulingGroup : 0x0 [Type: unsigned long]
    [+0x078 (10:10)] DeferPreemption  : 0x0 [Type: unsigned long]
    [+0x078 (11:11)] QueueDeferPreemption : 0x0 [Type: unsigned long]
    [+0x078 (12:12)] ForceDeferSchedule : 0x0 [Type: unsigned long]
    [+0x078 (13:13)] SharedReadyQueueAffinity : 0x1 [Type: unsigned long]
    [+0x078 (14:14)] FreezeCount      : 0x0 [Type: unsigned long]
    [+0x078 (15:15)] TerminationApcRequest : 0x0 [Type: unsigned long]
    [+0x078 (16:16)] AutoBoostEntriesExhausted : 0x0 [Type: unsigned long]
    [+0x078 (17:17)] KernelStackResident : 0x1 [Type: unsigned long]
    [+0x078 (19:18)] TerminateRequestReason : 0x0 [Type: unsigned long]
    [+0x078 (20:20)] ProcessStackCountDecremented : 0x0 [Type: unsigned long]
    [+0x078 (21:21)] RestrictedGuiThread : 0x0 [Type: unsigned long]
    [+0x078 (22:22)] VpBackingThread  : 0x0 [Type: unsigned long]
    [+0x078 (23:23)] ThreadFlagsSpare : 0x0 [Type: unsigned long]
    [+0x078 (31:24)] EtwStackTraceApcInserted : 0x0 [Type: unsigned long]
    [+0x078] ThreadFlags      : 139328 [Type: long]
    [+0x07c] Tag              : 0x0 [Type: unsigned char]
    [+0x07d] SystemHeteroCpuPolicy : 0x0 [Type: unsigned char]
    [+0x07e ( 6: 0)] UserHeteroCpuPolicy : 0x8 [Type: unsigned char]
    [+0x07e ( 7: 7)] ExplicitSystemHeteroCpuPolicy : 0x0 [Type: unsigned char]
    [+0x07f ( 0: 0)] RunningNonRetpolineCode : 0x0 [Type: unsigned char]
    [+0x07f ( 7: 1)] SpecCtrlSpare    : 0x0 [Type: unsigned char]
    [+0x07f] SpecCtrl         : 0x0 [Type: unsigned char]
    [+0x080] SystemCallNumber : 0xb [Type: unsigned long]
    [+0x084] ReadyTime        : 0x0 [Type: unsigned long]
    [+0x088] FirstArgument    : 0x84 [Type: void *]
    [+0x090] TrapFrame        : 0xffffaf86f46c8b00 [Type: _KTRAP_FRAME *]
    [+0x098] ApcState         [Type: _KAPC_STATE]
    [+0x098] ApcStateFill     [Type: unsigned char [43]]
    [+0x0c3] Priority         : 10 '\n' [Type: char]
    [+0x0c4] UserIdealProcessor : 0x0 [Type: unsigned long]
    [+0x0c8] WaitStatus       : 0 [Type: __int64]
    [+0x0d0] WaitBlockList    : 0xffff8982c4fde1c0 [Type: _KWAIT_BLOCK *]
    [+0x0d8] WaitListEntry    [Type: _LIST_ENTRY]
    [+0x0d8] SwapListEntry    [Type: _SINGLE_LIST_ENTRY]
    [+0x0e8] Queue            : 0x0 [Type: _DISPATCHER_HEADER *]
    [+0x0f0] Teb              : 0x8a95fe2000 [Type: void *]
    [+0x0f8] RelativeTimerBias : 0x0 [Type: unsigned __int64]
    [+0x100] Timer            [Type: _KTIMER]
    [+0x140] WaitBlock        [Type: _KWAIT_BLOCK [4]]
    [+0x140] WaitBlockFill4   [Type: unsigned char [20]]
    [+0x154] ContextSwitches  : 0x5 [Type: unsigned long]
    [+0x140] WaitBlockFill5   [Type: unsigned char [68]]
    [+0x184] State            : 0x5 [Type: unsigned char]
    [+0x185] Spare13          : 0 [Type: char]
    [+0x186] WaitIrql         : 0x0 [Type: unsigned char]
    [+0x187] WaitMode         : 1 [Type: char]
    [+0x140] WaitBlockFill6   [Type: unsigned char [116]]
    [+0x1b4] WaitTime         : 0xc14d0 [Type: unsigned long]
    [+0x140] WaitBlockFill7   [Type: unsigned char [164]]
    [+0x1e4] KernelApcDisable : 0 [Type: short]
    [+0x1e6] SpecialApcDisable : 0 [Type: short]
    [+0x1e4] CombinedApcDisable : 0x0 [Type: unsigned long]
    [+0x140] WaitBlockFill8   [Type: unsigned char [40]]
    [+0x168] ThreadCounters   : 0x0 [Type: _KTHREAD_COUNTERS *]
    [+0x140] WaitBlockFill9   [Type: unsigned char [88]]
    [+0x198] XStateSave       : 0x0 [Type: _XSTATE_SAVE *]
    [+0x140] WaitBlockFill10  [Type: unsigned char [136]]
    [+0x1c8] Win32Thread      : 0x0 [Type: void *]
    [+0x140] WaitBlockFill11  [Type: unsigned char [176]]
    [+0x1f0] Ucb              : 0x0 [Type: _UMS_CONTROL_BLOCK *]
    [+0x1f8] Uch              : 0x0 [Type: _KUMS_CONTEXT_HEADER *]
    [+0x200] Spare21          : 0x0 [Type: void *]
    [+0x208] QueueListEntry   [Type: _LIST_ENTRY]
    [+0x218] NextProcessor    : 0x1 [Type: unsigned long]
    [+0x218 (30: 0)] NextProcessorNumber : 0x1 [Type: unsigned long]
    [+0x218 (31:31)] SharedReadyQueue : 0x0 [Type: unsigned long]
    [+0x21c] QueuePriority    : 0 [Type: long]
    [+0x220] Process          : 0xffff8982c6e020c0 [Type: _KPROCESS *]
    [+0x228] UserAffinity     [Type: _GROUP_AFFINITY]
    [+0x228] UserAffinityFill [Type: unsigned char [10]]
    [+0x232] PreviousMode     : 1 [Type: char]
    [+0x233] BasePriority     : 9 '\t' [Type: char]
    [+0x234] PriorityDecrement : 0 [Type: char]
    [+0x234 ( 3: 0)] ForegroundBoost  : 0x0 [Type: unsigned char]
    [+0x234 ( 7: 4)] UnusualBoost     : 0x0 [Type: unsigned char]
    [+0x235] Preempted        : 0x0 [Type: unsigned char]
    [+0x236] AdjustReason     : 0x0 [Type: unsigned char]
    [+0x237] AdjustIncrement  : 1 [Type: char]
    [+0x238] AffinityVersion  : 0x40 [Type: unsigned __int64]
    [+0x240] Affinity         [Type: _GROUP_AFFINITY]
    [+0x240] AffinityFill     [Type: unsigned char [10]]
    [+0x24a] ApcStateIndex    : 0x0 [Type: unsigned char]
    [+0x24b] WaitBlockCount   : 0x1 [Type: unsigned char]
    [+0x24c] IdealProcessor   : 0x0 [Type: unsigned long]
    [+0x250] NpxState         : 0x5 [Type: unsigned __int64]
    [+0x258] SavedApcState    [Type: _KAPC_STATE]
    [+0x258] SavedApcStateFill [Type: unsigned char [43]]
    [+0x283] WaitReason       : 0x10 [Type: unsigned char]
    [+0x284] SuspendCount     : 0 [Type: char]
    [+0x285] Saturation       : 0 [Type: char]
    [+0x286] SListFaultCount  : 0x0 [Type: unsigned short]
    [+0x288] SchedulerApc     [Type: _KAPC]
    [+0x288] SchedulerApcFill0 [Type: unsigned char [1]]
    [+0x289] ResourceIndex    : 0x0 [Type: unsigned char]
    [+0x288] SchedulerApcFill1 [Type: unsigned char [3]]
    [+0x28b] QuantumReset     : 0x6 [Type: unsigned char]
    [+0x288] SchedulerApcFill2 [Type: unsigned char [4]]
    [+0x28c] KernelTime       : 0x0 [Type: unsigned long]
    [+0x288] SchedulerApcFill3 [Type: unsigned char [64]]
    [+0x2c8] WaitPrcb         : 0xffffb1816a625180 [Type: _KPRCB *]
    [+0x288] SchedulerApcFill4 [Type: unsigned char [72]]
    [+0x2d0] LegoData         : 0x0 [Type: void *]
    [+0x288] SchedulerApcFill5 [Type: unsigned char [83]]
    [+0x2db] CallbackNestingLevel : 0x0 [Type: unsigned char]
    [+0x2dc] UserTime         : 0x0 [Type: unsigned long]
    [+0x2e0] SuspendEvent     [Type: _KEVENT]
    [+0x2f8] ThreadListEntry  [Type: _LIST_ENTRY]
    [+0x308] MutantListHead   [Type: _LIST_ENTRY]
    [+0x318] AbEntrySummary   : 0x3f [Type: unsigned char]
    [+0x319] AbWaitEntryCount : 0x0 [Type: unsigned char]
    [+0x31a] AbAllocationRegionCount : 0x0 [Type: unsigned char]
    [+0x31b] SystemPriority   : 0 [Type: char]
    [+0x31c] SecureThreadCookie : 0x0 [Type: unsigned long]
    [+0x320] LockEntries      [Type: _KLOCK_ENTRY [6]]
    [+0x560] PropagateBoostsEntry [Type: _SINGLE_LIST_ENTRY]
    [+0x568] IoSelfBoostsEntry [Type: _SINGLE_LIST_ENTRY]
    [+0x570] PriorityFloorCounts [Type: unsigned char [16]]
    [+0x580] PriorityFloorSummary : 0x0 [Type: unsigned long]
    [+0x584] AbCompletedIoBoostCount : 0 [Type: long]
    [+0x588] AbCompletedIoQoSBoostCount : 0 [Type: long]
    [+0x58c] KeReferenceCount : 0 [Type: short]
    [+0x58e] AbOrphanedEntrySummary : 0x0 [Type: unsigned char]
    [+0x58f] AbOwnedEntryCount : 0x0 [Type: unsigned char]
    [+0x590] ForegroundLossTime : 0x0 [Type: unsigned long]
    [+0x598] GlobalForegroundListEntry [Type: _LIST_ENTRY]
    [+0x598] ForegroundDpcStackListEntry [Type: _SINGLE_LIST_ENTRY]
    [+0x5a0] InGlobalForegroundList : 0x0 [Type: unsigned __int64]
    [+0x5a8] ReadOperationCount : 0 [Type: __int64]
    [+0x5b0] WriteOperationCount : 0 [Type: __int64]
    [+0x5b8] OtherOperationCount : 0 [Type: __int64]
    [+0x5c0] ReadTransferCount : 0 [Type: __int64]
    [+0x5c8] WriteTransferCount : 0 [Type: __int64]
    [+0x5d0] OtherTransferCount : 0 [Type: __int64]
    [+0x5d8] QueuedScb        : 0x0 [Type: _KSCB *]
    [+0x5e0] ThreadTimerDelay : 0x0 [Type: unsigned long]
    [+0x5e4] ThreadFlags2     : 0 [Type: long]
    [+0x5e4 ( 1: 0)] PpmPolicy        : 0x0 [Type: unsigned long]
    [+0x5e4 (31: 2)] ThreadFlags2Reserved : 0x0 [Type: unsigned long]
    [+0x5e8] TracingPrivate   [Type: unsigned __int64 [1]]
    [+0x5f0] SchedulerAssist  : 0x0 [Type: void *]
    [+0x5f8] AbWaitObject     : 0x0 [Type: void *]

Logical Processor Kernel Structures

Kernel Processor Control Region (KPCR).

  • Current IRQL
  • Contains pointers to CPU structures such as IDT, GDT and task segment (TSS)
  • Current registered SEH

KPCR can be dumped with:

kd> !pcr 0
KPCR for Processor 0 at fffff8005c635000:
[...ommitted due too inconsitent data]

kd> dx (nt! _KPCR*)0xfffff8005c635000
(nt! _KPCR*)0xfffff8005c635000                 : 0xfffff8005c635000 [Type: _KPCR *]
    [+0x000] NtTib            [Type: _NT_TIB]
    [+0x000] GdtBase          : 0xfffff80064480fb0 [Type: _KGDTENTRY64 *]
    [+0x008] TssBase          : 0xfffff8006447f000 [Type: _KTSS64 *]
    [+0x010] UserRsp          : 0x0 [Type: unsigned __int64]
    [+0x018] Self             : 0xfffff8005c635000 [Type: _KPCR *]
    [+0x020] CurrentPrcb      : 0xfffff8005c635180 [Type: _KPRCB *]
    [+0x028] LockArray        : 0xfffff8005c635870 [Type: _KSPIN_LOCK_QUEUE *]
    [+0x030] Used_Self        : 0x6e83c77000 [Type: void *]
    [+0x038] IdtBase          : 0xfffff8006447e000 [Type: _KIDTENTRY64 *]
    [+0x040] Unused           [Type: unsigned __int64 [2]]
    [+0x050] Irql             : 0x0 [Type: unsigned char]
    [+0x051] SecondLevelCacheAssociativity : 0x10 [Type: unsigned char]
    [+0x052] ObsoleteNumber   : 0x0 [Type: unsigned char]
    [+0x053] Fill0            : 0x0 [Type: unsigned char]
    [+0x054] Unused0          [Type: unsigned long [3]]
    [+0x060] MajorVersion     : 0x1 [Type: unsigned short]
    [+0x062] MinorVersion     : 0x1 [Type: unsigned short]
    [+0x064] StallScaleFactor : 0xa98 [Type: unsigned long]
    [+0x068] Unused1          [Type: void * [3]]
    [+0x080] KernelReserved   [Type: unsigned long [15]]
    [+0x0bc] SecondLevelCacheSize : 0x800000 [Type: unsigned long]
    [+0x0c0] HalReserved      [Type: unsigned long [16]]
    [+0x100] Unused2          : 0x0 [Type: unsigned long]
    [+0x108]kdVersionBlock   : 0x0 [Type: void *]
    [+0x110] Unused3          : 0x0 [Type: void *]
    [+0x118] PcrAlign1        [Type: unsigned long [24]]
    [+0x180] Prcb             [Type: _KPRCB]

Kernel Processor Control Block (KPRCB)

  • PerfCounters
  • Thread Scheduling
  • CPU info
  • Power state
  • LP context/registers

At offsex 0x180 of the KPCR from the previous output, we can obtain the address of the KPRCB, and dump this lengthy structure.

kd> dx -r1 (*((ntkrnlmp!_KPRCB *)0xffffbe80a6225180))
(*((ntkrnlmp!_KPRCB *)0xffffbe80a6225180))                 [Type: _KPRCB]
    [+0x000] MxCsr            : 0x1f80 [Type: unsigned long]
    [+0x004] LegacyNumber     : 0x1 [Type: unsigned char]
    [+0x005] ReservedMustBeZero : 0x0 [Type: unsigned char]
    [+0x006] InterruptRequest : 0x0 [Type: unsigned char]
    [+0x007] IdleHalt         : 0x0 [Type: unsigned char]
    [+0x008] CurrentThread    : 0xffffa78fdc54c080 [Type: _KTHREAD *]
    [+0x010] NextThread       : 0x0 [Type: _KTHREAD *]
    [+0x018] IdleThread       : 0xffffbe80a6236100 [Type: _KTHREAD *]
    [+0x020] NestingLevel     : 0x1 [Type: unsigned char]
    [+0x021] ClockOwner       : 0x0 [Type: unsigned char]
    [+0x022] PendingTickFlags : 0x0 [Type: unsigned char]
    [+0x022 ( 0: 0)] PendingTick      : 0x0 [Type: unsigned char]
    [+0x022 ( 1: 1)] PendingBackupTick : 0x0 [Type: unsigned char]
    [+0x023] IdleState        : 0x1 [Type: unsigned char]
    [+0x024] Number           : 0x1 [Type: unsigned long]
    [+0x028] RspBase          : 0xfffffd0bb4dc6fd0 [Type: unsigned __int64]
    [+0x030] PrcbLock         : 0x0 [Type: unsigned __int64]
    [+0x038] PriorityState    : 0xfffff8005c63b911 : "???" [Type: char *]
    [+0x040] CpuType          : 6 [Type: char]
    [+0x041] CpuID            : 1 [Type: char]
    [+0x042] CpuStep          : 0x8e0a [Type: unsigned short]
    [+0x042] CpuStepping      : 0xa [Type: unsigned char]
    [+0x043] CpuModel         : 0x8e [Type: unsigned char]
    [+0x044] MHz              : 0xa98 [Type: unsigned long]
    [+0x048] HalReserved      [Type: unsigned __int64 [8]]
    [+0x088] MinorVersion     : 0x1 [Type: unsigned short]
    [+0x08a] MajorVersion     : 0x1 [Type: unsigned short]
    [+0x08c] BuildType        : 0x0 [Type: unsigned char]
    [+0x08d] CpuVendor        : 0x2 [Type: unsigned char]
    [+0x08e] CoresPerPhysicalProcessor : 0x4 [Type: unsigned char]
    [+0x08f] LogicalProcessorsPerCore : 0x1 [Type: unsigned char]
    [+0x090] TscFrequency     : 0x0 [Type: unsigned __int64]
    [+0x098] PrcbPad04        [Type: unsigned __int64 [5]]
    [+0x0c0] ParentNode       : 0xfffff8005fb8f240 [Type: _KNODE *]
    [+0x0c8] GroupSetMember   : 0x2 [Type: unsigned __int64]
    [+0x0d0] Group            : 0x0 [Type: unsigned char]
    [+0x0d1] GroupIndex       : 0x1 [Type: unsigned char]
    [+0x0d2] PrcbPad05        [Type: unsigned char [2]]
    [+0x0d4] InitialApicId    : 0x1 [Type: unsigned long]
    [+0x0d8] ScbOffset        : 0x228 [Type: unsigned long]
    [+0x0dc] ApicMask         : 0xfffffffc [Type: unsigned long]
    [+0x0e0] AcpiReserved     : 0x0 [Type: void *]
    [+0x0e8] CFlushSize       : 0x40 [Type: unsigned long]
    [+0x0ec] PrcbFlags        [Type: _KPRCBFLAG]
    [+0x0f0] TrappedSecurityDomain : 0x0 [Type: unsigned __int64]
    [+0x0f8] BpbState         : 0x0 [Type: unsigned char]
    [+0x0f8 ( 0: 0)] BpbCpuIdle       : 0x0 [Type: unsigned char]
    [+0x0f8 ( 1: 1)] BpbFlushRsbOnTrap : 0x0 [Type: unsigned char]
    [+0x0f8 ( 2: 2)] BpbIbpbOnReturn  : 0x0 [Type: unsigned char]
    [+0x0f8 ( 3: 3)] BpbIbpbOnTrap    : 0x0 [Type: unsigned char]
    [+0x0f8 ( 4: 4)] BpbIbpbOnRetpolineExit : 0x0 [Type: unsigned char]
    [+0x0f8 ( 7: 5)] BpbStateReserved : 0x0 [Type: unsigned char]
    [+0x0f9] BpbFeatures      : 0x6 [Type: unsigned char]
    [+0x0f9 ( 0: 0)] BpbClearOnIdle   : 0x0 [Type: unsigned char]
    [+0x0f9 ( 1: 1)] BpbEnabled       : 0x1 [Type: unsigned char]
    [+0x0f9 ( 2: 2)] BpbSmep          : 0x1 [Type: unsigned char]
    [+0x0f9 ( 7: 3)] BpbFeaturesReserved : 0x0 [Type: unsigned char]
    [+0x0fa] BpbCurrentSpecCtrl : 0x2 [Type: unsigned char]
    [+0x0fb] BpbKernelSpecCtrl : 0x2 [Type: unsigned char]
    [+0x0fc] BpbNmiSpecCtrl   : 0x1 [Type: unsigned char]
    [+0x0fd] BpbUserSpecCtrl  : 0x2 [Type: unsigned char]
    [+0x0fe] PairRegister     : 0 [Type: short]
    [+0x0f0] PrcbPad11        [Type: unsigned __int64 [2]]
    [+0x100] ProcessorState   [Type: _KPROCESSOR_STATE]
    [+0x6c0] ExtendedSupervisorState : 0x0 [Type: _XSAVE_AREA_HEADER *]
    [+0x6c8] ProcessorSignature : 0x806ea [Type: unsigned long]
    [+0x6cc] ProcessorFlags   : 0x1 [Type: unsigned long]
    [+0x6d0] BpbRetpolineExitSpecCtrl : 0x2 [Type: unsigned char]
    [+0x6d1] BpbTrappedRetpolineExitSpecCtrl : 0x2 [Type: unsigned char]
    [+0x6d2] BpbTrappedBpbState : 0x0 [Type: unsigned char]
    [+0x6d2 ( 0: 0)] BpbTrappedCpuIdle : 0x0 [Type: unsigned char]
    [+0x6d2 ( 1: 1)] BpbTrappedFlushRsbOnTrap : 0x0 [Type: unsigned char]
    [+0x6d2 ( 2: 2)] BpbTrappedIbpbOnReturn : 0x0 [Type: unsigned char]
    [+0x6d2 ( 3: 3)] BpbTrappedIbpbOnTrap : 0x0 [Type: unsigned char]
    [+0x6d2 ( 4: 4)] BpbTrappedIbpbOnRetpolineExit : 0x0 [Type: unsigned char]
    [+0x6d2 ( 7: 5)] BpbtrappedBpbStateReserved : 0x0 [Type: unsigned char]
    [+0x6d3] BpbRetpolineState : 0x0 [Type: unsigned char]
    [+0x6d3 ( 0: 0)] BpbRunningNonRetpolineCode : 0x0 [Type: unsigned char]
    [+0x6d3 ( 1: 1)] BpbIndirectCallsSafe : 0x0 [Type: unsigned char]
    [+0x6d3 ( 2: 2)] BpbRetpolineEnabled : 0x0 [Type: unsigned char]
    [+0x6d3 ( 7: 3)] BpbRetpolineStateReserved : 0x0 [Type: unsigned char]
    [+0x6d4] PrcbPad12b       : 0x0 [Type: unsigned long]
    [+0x6d0] PrcbPad12a       : 0x202 [Type: unsigned __int64]
    [+0x6d8] PrcbPad12        [Type: unsigned __int64 [3]]
    [+0x6f0] LockQueue        [Type: _KSPIN_LOCK_QUEUE [17]]
    [+0x800] PPLookasideList  [Type: _PP_LOOKASIDE_LIST [16]]
    [+0x900] PPNxPagedLookasideList [Type: _GENERAL_LOOKASIDE_POOL [32]]
    [+0x1500] PPNPagedLookasideList [Type: _GENERAL_LOOKASIDE_POOL [32]]
    [+0x2100] PPPagedLookasideList [Type: _GENERAL_LOOKASIDE_POOL [32]]
    [+0x2d00] MsrIa32TsxCtrl   : 0x0 [Type: unsigned __int64]
    [+0x2d08] DeferredReadyListHead [Type: _SINGLE_LIST_ENTRY]
    [+0x2d10] MmPageFaultCount : 1154356 [Type: long]
    [+0x2d14] MmCopyOnWriteCount : 20781 [Type: long]
    [+0x2d18] MmTransitionCount : 392381 [Type: long]
    [+0x2d1c] MmDemandZeroCount : 698067 [Type: long]
    [+0x2d20] MmPageReadCount  : 187320 [Type: long]
    [+0x2d24] MmPageReadIoCount : 29937 [Type: long]
    [+0x2d28] MmDirtyPagesWriteCount : 0 [Type: long]
    [+0x2d2c] MmDirtyWriteIoCount : 0 [Type: long]
    [+0x2d30] MmMappedPagesWriteCount : 0 [Type: long]
    [+0x2d34] MmMappedWriteIoCount : 0 [Type: long]
    [+0x2d38] KeSystemCalls    : 0x7886bb [Type: unsigned long]
    [+0x2d3c] KeContextSwitches : 0xb2632 [Type: unsigned long]
    [+0x2d40] PrcbPad40        : 0x0 [Type: unsigned long]
    [+0x2d44] CcFastReadNoWait : 0x0 [Type: unsigned long]
    [+0x2d48] CcFastReadWait   : 0x86d5 [Type: unsigned long]
    [+0x2d4c] CcFastReadNotPossible : 0x4b [Type: unsigned long]
    [+0x2d50] CcCopyReadNoWait : 0xcb [Type: unsigned long]
    [+0x2d54] CcCopyReadWait   : 0x9318 [Type: unsigned long]
    [+0x2d58] CcCopyReadNoWaitMiss : 0x7e [Type: unsigned long]
    [+0x2d5c] IoReadOperationCount : 41446 [Type: long]
    [+0x2d60] IoWriteOperationCount : 11328 [Type: long]
    [+0x2d64] IoOtherOperationCount : 250433 [Type: long]
    [+0x2d68] IoReadTransferCount : {231566873} [Type: _LARGE_INTEGER]
    [+0x2d70] IoWriteTransferCount : {46797832} [Type: _LARGE_INTEGER]
    [+0x2d78] IoOtherTransferCount : {145452248} [Type: _LARGE_INTEGER]
    [+0x2d80] PacketBarrier    : 0 [Type: long]
    [+0x2d84] TargetCount      : 0 [Type: long]
    [+0x2d88] IpiFrozen        : 0x0 [Type: unsigned long]
    [+0x2d8c] PrcbPad30        : 0x0 [Type: unsigned long]
    [+0x2d90] IsrDpcStats      : 0x1 [Type: void *]
    [+0x2d98] DeviceInterrupts : 0x1d [Type: unsigned long]
    [+0x2d9c] LookasideIrpFloat : 2147483647 [Type: long]
    [+0x2da0] InterruptLastCount : 0x72b16 [Type: unsigned long]
    [+0x2da4] InterruptRate    : 0x43 [Type: unsigned long]
    [+0x2da8] LastNonHrTimerExpiration : 0x0 [Type: unsigned __int64]
    [+0x2db0] PairPrcb         : 0x0 [Type: _KPRCB *]
    [+0x2db8] PrcbPad35        [Type: unsigned __int64 [1]]
    [+0x2dc0] InterruptObjectPool [Type: _SLIST_HEADER]
    [+0x2dd0] PrcbPad41        [Type: unsigned __int64 [6]]
    [+0x2e00] DpcData          [Type: kdPC_DATA [2]]
    [+0x2e50] DpcStack         : 0xfffffd0bb2e30fb0 [Type: void *]
    [+0x2e58] MaximumDpcQueueDepth : 4 [Type: long]
    [+0x2e5c] DpcRequestRate   : 0x216 [Type: unsigned long]
    [+0x2e60] MinimumDpcRate   : 0x3 [Type: unsigned long]
    [+0x2e64] DpcLastCount     : 0xebfe2 [Type: unsigned long]
    [+0x2e68] ThreadDpcEnable  : 0x1 [Type: unsigned char]
    [+0x2e69] QuantumEnd       : 0x0 [Type: unsigned char]
    [+0x2e6a] DpcRoutineActive : 0x1 [Type: unsigned char]
    [+0x2e6b] IdleSchedule     : 0x0 [Type: unsigned char]
    [+0x2e6c] DpcRequestSummary : 1 [Type: long]
    [+0x2e6c] DpcRequestSlot   [Type: short [2]]
    [+0x2e6c] NormalDpcState   : 1 [Type: short]
    [+0x2e6e] ThreadDpcState   : 0 [Type: short]
    [+0x2e6c ( 0: 0)] DpcNormalProcessingActive : 0x1 [Type: unsigned long]
    [+0x2e6c ( 1: 1)] DpcNormalProcessingRequested : 0x0 [Type: unsigned long]
    [+0x2e6c ( 2: 2)] DpcNormalThreadSignal : 0x0 [Type: unsigned long]
    [+0x2e6c ( 3: 3)] DpcNormalTimerExpiration : 0x0 [Type: unsigned long]
    [+0x2e6c ( 4: 4)] DpcNormalDpcPresent : 0x0 [Type: unsigned long]
    [+0x2e6c ( 5: 5)] DpcNormalLocalInterrupt : 0x0 [Type: unsigned long]
    [+0x2e6c (15: 6)] DpcNormalSpare   : 0x0 [Type: unsigned long]
    [+0x2e6c (16:16)] DpcThreadActive  : 0x0 [Type: unsigned long]
    [+0x2e6c (17:17)] DpcThreadRequested : 0x0 [Type: unsigned long]
    [+0x2e6c (31:18)] DpcThreadSpare   : 0x0 [Type: unsigned long]
    [+0x2e70] LastTimerHand    : 0xb096 [Type: unsigned long]
    [+0x2e74] LastTick         : 0x12844 [Type: unsigned long]
    [+0x2e78] ClockInterrupts  : 0x1426a [Type: unsigned long]
    [+0x2e7c] ReadyScanTick    : 0x1285c [Type: unsigned long]
    [+0x2e80] InterruptObject  [Type: void * [256]]
    [+0x3680] TimerTable       [Type: _KTIMER_TABLE]
    [+0x5880] DpcGate          [Type: _KGATE]
    [+0x5898] PrcbPad52        : 0x0 [Type: void *]
    [+0x58a0] CallDpc          [Type: kdPC]
    [+0x58e0] ClockKeepAlive   : 1 [Type: long]
    [+0x58e4] PrcbPad60        [Type: unsigned char [2]]
    [+0x58e6] NmiActive        : 0x0 [Type: unsigned short]
    [+0x58e8] DpcWatchdogPeriod : 0 [Type: long]
    [+0x58ec] DpcWatchdogCount : 0 [Type: long]
    [+0x58f0] KeSpinLockOrdering : 0 [Type: long]
    [+0x58f4] DpcWatchdogProfileCumulativeDpcThreshold : 0x0 [Type: unsigned long]
    [+0x58f8] CachedPtes       : 0x0 [Type: void *]
    [+0x5900] WaitListHead     [Type: _LIST_ENTRY]
    [+0x5910] WaitLock         : 0x0 [Type: unsigned __int64]
    [+0x5918] ReadySummary     : 0x0 [Type: unsigned long]
    [+0x591c] AffinitizedSelectionMask : 0 [Type: long]
    [+0x5920] QueueIndex       : 0x1 [Type: unsigned long]
    [+0x5924] PrcbPad75        [Type: unsigned long [3]]
    [+0x5930] TimerExpirationDpc [Type: kdPC]
    [+0x5970] ScbQueue         [Type: _RTL_RB_TREE]
    [+0x5980] DispatcherReadyListHead [Type: _LIST_ENTRY [32]]
    [+0x5b80] InterruptCount   : 0x72b88 [Type: unsigned long]
    [+0x5b84] KernelTime       : 0x11ff5 [Type: unsigned long]
    [+0x5b88] UserTime         : 0x83d [Type: unsigned long]
    [+0x5b8c] DpcTime          : 0x5b [Type: unsigned long]
    [+0x5b90] InterruptTime    : 0x73 [Type: unsigned long]
    [+0x5b94] AdjustDpcThreshold : 0xb [Type: unsigned long]
    [+0x5b98] DebuggerSavedIRQL : 0x0 [Type: unsigned char]
    [+0x5b99] GroupSchedulingOverQuota : 0x0 [Type: unsigned char]
    [+0x5b9a] DeepSleep        : 0x0 [Type: unsigned char]
    [+0x5b9b] PrcbPad80        : 0x0 [Type: unsigned char]
    [+0x5b9c] DpcTimeCount     : 0x0 [Type: unsigned long]
    [+0x5ba0] DpcTimeLimit     : 0x0 [Type: unsigned long]
    [+0x5ba4] PeriodicCount    : 0x0 [Type: unsigned long]
    [+0x5ba8] PeriodicBias     : 0x0 [Type: unsigned long]
    [+0x5bac] AvailableTime    : 0x82a [Type: unsigned long]
    [+0x5bb0] KeExceptionDispatchCount : 0x4463 [Type: unsigned long]
    [+0x5bb4] ReadyThreadCount : 0x0 [Type: unsigned long]
    [+0x5bb8] ReadyQueueExpectedRunTime : 0x0 [Type: unsigned __int64]
    [+0x5bc0] StartCycles      : 0x33d53e5f496 [Type: unsigned __int64]
    [+0x5bc8] TaggedCyclesStart : 0x0 [Type: unsigned __int64]
    [+0x5bd0] TaggedCycles     [Type: unsigned __int64 [2]]
    [+0x5be0] GenerationTarget : 0x12864 [Type: unsigned __int64]
    [+0x5be8] AffinitizedCycles : 0x1068d99188 [Type: unsigned __int64]
    [+0x5bf0] ImportantCycles  : 0x0 [Type: unsigned __int64]
    [+0x5bf8] UnimportantCycles : 0x0 [Type: unsigned __int64]
    [+0x5c00] DpcWatchdogProfileSingleDpcThreshold : 0x0 [Type: unsigned long]
    [+0x5c04] MmSpinLockOrdering : 0 [Type: long]
    [+0x5c08] CachedStack      : 0x0 [Type: void *]
    [+0x5c10] PageColor        : 0x895 [Type: unsigned long]
    [+0x5c14] NodeColor        : 0x0 [Type: unsigned long]
    [+0x5c18] NodeShiftedColor : 0x0 [Type: unsigned long]
    [+0x5c1c] SecondaryColorMask : 0xff [Type: unsigned long]
    [+0x5c20] PrcbPad81        [Type: unsigned char [6]]
    [+0x5c26] ExceptionStackActive : 0x0 [Type: unsigned char]
    [+0x5c27] TbFlushListActive : 0x0 [Type: unsigned char]
    [+0x5c28] ExceptionStack   : 0xffffbe80a626dfb0 [Type: void *]
    [+0x5c30] PrcbPad82        [Type: unsigned __int64 [1]]
    [+0x5c38] CycleTime        : 0x8d42dc2c9 [Type: unsigned __int64]
    [+0x5c40] Cycles           [Type: unsigned __int64 [4][2]]
    [+0x5c80] CcFastMdlReadNoWait : 0x0 [Type: unsigned long]
    [+0x5c84] CcFastMdlReadWait : 0x0 [Type: unsigned long]
    [+0x5c88] CcFastMdlReadNotPossible : 0x0 [Type: unsigned long]
    [+0x5c8c] CcMapDataNoWait  : 0x0 [Type: unsigned long]
    [+0x5c90] CcMapDataWait    : 0x224b7 [Type: unsigned long]
    [+0x5c94] CcPinMappedDataCount : 0x6dd8 [Type: unsigned long]
    [+0x5c98] CcPinReadNoWait  : 0x12 [Type: unsigned long]
    [+0x5c9c] CcPinReadWait    : 0x78d0 [Type: unsigned long]
    [+0x5ca0] CcMdlReadNoWait  : 0x0 [Type: unsigned long]
    [+0x5ca4] CcMdlReadWait    : 0xa [Type: unsigned long]
    [+0x5ca8] CcLazyWriteHotSpots : 0x3a [Type: unsigned long]
    [+0x5cac] CcLazyWriteIos   : 0x43f [Type: unsigned long]
    [+0x5cb0] CcLazyWritePages : 0xb18 [Type: unsigned long]
    [+0x5cb4] CcDataFlushes    : 0x10c1 [Type: unsigned long]
    [+0x5cb8] CcDataPages      : 0x2d83 [Type: unsigned long]
    [+0x5cbc] CcLostDelayedWrites : 0x0 [Type: unsigned long]
    [+0x5cc0] CcFastReadResourceMiss : 0x0 [Type: unsigned long]
    [+0x5cc4] CcCopyReadWaitMiss : 0x1980 [Type: unsigned long]
    [+0x5cc8] CcFastMdlReadResourceMiss : 0x0 [Type: unsigned long]
    [+0x5ccc] CcMapDataNoWaitMiss : 0x0 [Type: unsigned long]
    [+0x5cd0] CcMapDataWaitMiss : 0xf4c [Type: unsigned long]
    [+0x5cd4] CcPinReadNoWaitMiss : 0x4c35 [Type: unsigned long]
    [+0x5cd8] CcPinReadWaitMiss : 0x74 [Type: unsigned long]
    [+0x5cdc] CcMdlReadNoWaitMiss : 0x0 [Type: unsigned long]
    [+0x5ce0] CcMdlReadWaitMiss : 0x0 [Type: unsigned long]
    [+0x5ce4] CcReadAheadIos   : 0x54de [Type: unsigned long]
    [+0x5ce8] MmCacheTransitionCount : 0 [Type: long]
    [+0x5cec] MmCacheReadCount : 0 [Type: long]
    [+0x5cf0] MmCacheIoCount   : 0 [Type: long]
    [+0x5cf4] PrcbPad91        : 0x0 [Type: unsigned long]
    [+0x5cf8] MmInternal       : 0xffffa78fdc3be000 [Type: void *]
    [+0x5d00] PowerState       [Type: _PROCESSOR_POWER_STATE]
    [+0x5f00] HyperPte         : 0xffffbe80a6439000 [Type: void *]
    [+0x5f08] ScbList          [Type: _LIST_ENTRY]
    [+0x5f18] ForceIdleDpc     [Type: kdPC]
    [+0x5f58] DpcWatchdogDpc   [Type: kdPC]
    [+0x5f98] DpcWatchdogTimer [Type: _KTIMER]
    [+0x5fd8] Cache            [Type: _CACHE_DESCRIPTOR [5]]
    [+0x6014] CacheCount       : 0x4 [Type: unsigned long]
    [+0x6018] CachedCommit     : 0xa9 [Type: unsigned long]
    [+0x601c] CachedResidentAvailable : 0xc4 [Type: unsigned long]
    [+0x6020] WheaInfo         : 0xffffa78fdc29dbb8 [Type: void *]
    [+0x6028] EtwSupport       : 0xffffa78fdc2b0050 [Type: void *]
    [+0x6030] ExSaPageArray    : 0xffffa78fdc27a330 [Type: void *]
    [+0x6038] KeAlignmentFixupCount : 0x0 [Type: unsigned long]
    [+0x603c] PrcbPad95        : 0x0 [Type: unsigned long]
    [+0x6040] HypercallPageList [Type: _SLIST_HEADER]
    [+0x6050] StatisticsPage   : 0x0 [Type: unsigned __int64 *]
    [+0x6058] PrcbPad85        [Type: unsigned __int64 [5]]
    [+0x6080] HypercallCachedPages : 0xffffbe80a63be000 [Type: void *]
    [+0x6088] VirtualApicAssist : 0xffffbe80a623e000 [Type: void *]
    [+0x6090] PackageProcessorSet [Type: _KAFFINITY_EX]
    [+0x6138] PackageId        : 0x0 [Type: unsigned long]
    [+0x613c] PrcbPad86        : 0x0 [Type: unsigned long]
    [+0x6140] SharedReadyQueueMask : 0x7 [Type: unsigned __int64]
    [+0x6148] SharedReadyQueue : 0xfffff8005c63b700 [Type: _KSHARED_READY_QUEUE *]
    [+0x6150] SharedQueueScanOwner : 0x0 [Type: unsigned long]
    [+0x6154] ScanSiblingIndex : 0x0 [Type: unsigned long]
    [+0x6158] CoreProcessorSet : 0x2 [Type: unsigned __int64]
    [+0x6160] ScanSiblingMask  : 0x7 [Type: unsigned __int64]
    [+0x6168] LLCMask          : 0x7 [Type: unsigned __int64]
    [+0x6170] CacheProcessorMask [Type: unsigned __int64 [5]]
    [+0x6198] ProcessorProfileControlArea : 0x0 [Type: _PROCESSOR_PROFILE_CONTROL_AREA *]
    [+0x61a0] ProfileEventIndexAddress : 0xffffbe80a622b320 [Type: void *]
    [+0x61a8] DpcWatchdogProfile : 0x0 [Type: void * *]
    [+0x61b0] DpcWatchdogProfileCurrentEmptyCapture : 0x0 [Type: void * *]
    [+0x61b8] SchedulerAssist  : 0x0 [Type: void *]
    [+0x61c0] SynchCounters    [Type: _SYNCH_COUNTERS]
    [+0x6278] PrcbPad94        : 0x0 [Type: unsigned __int64]
    [+0x6280] FsCounters       [Type: _FILESYSTEM_DISK_COUNTERS]
    [+0x6290] VendorString     [Type: unsigned char [13]]
    [+0x629d] PrcbPad100       [Type: unsigned char [3]]
    [+0x62a0] FeatureBits      : 0x242f311b3dff [Type: unsigned __int64]
    [+0x62a8] UpdateSignature  : {867583393792} [Type: _LARGE_INTEGER]
    [+0x62b0] PteBitCache      : 0x3fe03 [Type: unsigned __int64]
    [+0x62b8] PteBitOffset     : 0xa7dc0 [Type: unsigned long]
    [+0x62bc] PrcbPad105       : 0x0 [Type: unsigned long]
    [+0x62c0] Context          : 0xffffbe80a6272340 [Type: _CONTEXT *]
    [+0x62c8] ContextFlagsInit : 0x10004b [Type: unsigned long]
    [+0x62cc] PrcbPad115       : 0x0 [Type: unsigned long]
    [+0x62d0] ExtendedState    : 0xffffbe80a6272000 [Type: _XSAVE_AREA *]
    [+0x62d8] IsrStack         : 0xffffbe80a6267000 [Type: void *]
    [+0x62e0] EntropyTimingState [Type: _KENTROPY_TIMING_STATE]
    [+0x6430] PrcbPad110       : 0x0 [Type: unsigned __int64]
    [+0x6438] StibpPairingTrace [Type: <anonymous-tag>]
    [+0x6470] AbSelfIoBoostsList [Type: _SINGLE_LIST_ENTRY]
    [+0x6478] AbPropagateBoostsList [Type: _SINGLE_LIST_ENTRY]
    [+0x6480] AbDpc            [Type: kdPC]
    [+0x64c0] IoIrpStackProfilerCurrent [Type: _IOP_IRP_STACK_PROFILER]
    [+0x6514] IoIrpStackProfilerPrevious [Type: _IOP_IRP_STACK_PROFILER]
    [+0x6568] SecureFault      [Type: _KSECURE_FAULT_INFORMATION]
    [+0x6578] PrcbPad120       : 0x0 [Type: unsigned __int64]
    [+0x6580] LocalSharedReadyQueue [Type: _KSHARED_READY_QUEUE]
    [+0x67f0] PrcbPad125       [Type: unsigned __int64 [2]]
    [+0x6800] TimerExpirationTraceCount : 0x0 [Type: unsigned long]
    [+0x6804] PrcbPad127       : 0x0 [Type: unsigned long]
    [+0x6808] TimerExpirationTrace [Type: _KTIMER_EXPIRATION_TRACE [16]]
    [+0x6908] PrcbPad128       [Type: unsigned __int64 [7]]
    [+0x6940] Mailbox          : 0x0 [Type: _REQUEST_MAILBOX *]
    [+0x6948] PrcbPad130       [Type: unsigned __int64 [7]]
    [+0x6980] McheckContext    [Type: _MACHINE_CHECK_CONTEXT [2]]
    [+0x6a20] PrcbPad134       [Type: unsigned __int64 [4]]
    [+0x6a40] SelfmapLockHandle [Type: _KLOCK_QUEUE_HANDLE [4]]
    [+0x6aa0] PrcbPad134a      [Type: unsigned __int64 [4]]
    [+0x6ac0] PrcbPad138       [Type: unsigned char [896]]
    [+0x6e40] PrcbPad138a      [Type: unsigned char [64]]
    [+0x6e80] KernelDirectoryTableBase : 0x80000001e028c002 [Type: unsigned __int64]
    [+0x6e88] RspBaseShadow    : 0xfffffd0bb4dc6fd0 [Type: unsigned __int64]
    [+0x6e90] UserRspShadow    : 0x6e83e7c188 [Type: unsigned __int64]
    [+0x6e98] ShadowFlags      : 0x2 [Type: unsigned long]
    [+0x6e9c] PrcbPad138b      : 0x0 [Type: unsigned long]
    [+0x6ea0] PrcbPad138c      : 0x0 [Type: unsigned __int64]
    [+0x6ea8] PrcbPad138d      : 0x0 [Type: unsigned short]
    [+0x6eaa] VerwSelector     : 0x18 [Type: unsigned short]
    [+0x6eac] PrcbPad139       : 0x0 [Type: unsigned long]
    [+0x6eb0] DbgMceNestingLevel : 0x0 [Type: unsigned long]
    [+0x6eb4] DbgMceFlags      : 0x0 [Type: unsigned long]
    [+0x6eb8] PrcbPad140       [Type: unsigned __int64 [505]]
    [+0x7e80] PrcbPad140a      [Type: unsigned __int64 [8]]
    [+0x7ec0] PrcbPad141       [Type: unsigned __int64 [504]]
    [+0x8e80] PrcbPad141a      [Type: unsigned char [64]]
    [+0x8ec0] RequestMailbox   [Type: _REQUEST_MAILBOX [1]]
    

We can dump all KPRCBs (in this case x3 virtual LP running on an hypervisor)

kd> !running

System Processors:  (0000000000000007)
  Idle Processors:  (0000000000000000)

       Prcbs             Current         (pri) Next            (pri) Idle
  0    fffff8005c635180  ffffa78fe3d8e080 (15)                       fffff8005fb91400  ................
  1    ffffbe80a6225180  ffffa78fe3cbf2c0 ( 8)                       ffffbe80a6236100  ................
  2    ffffbe80a6480180  ffffa78fe3f80080 ( 9)                       ffffbe80a6491100  ................

We can also dump the Summary of the multithreaded process information.

kd> !smt
SMT Summary:
------------

KeActiveProcessors:
***------------------------------------------------------------- (0000000000000007)
IdleSummary:
-**------------------------------------------------------------- (0000000000000006)
 No PRCB             SMT Set                                                                             APIC Id
  0 fffff8005c635180 *--------------------------------------------------------------- (0000000000000001) 0x00000000
  1 ffffbe80a6225180 -*-------------------------------------------------------------- (0000000000000002) 0x00000001
  2 ffffbe80a6480180 --*------------------------------------------------------------- (0000000000000004) 0x00000002

Maximum cores per physical processor:   4
Maximum logical processors per core:    1

How logical CPU keeps track of the current process/thread?

The GSBase MSR register holds the address of the KPCR structure.

0: kd> rdmsr c0000101
msr[c0000101] = fffff805`72f0f000

0: kd> !pcr
KPCR for Processor 0 at fffff80572f0f000:

We can then find the value of the CurrentThread inside the KPCR. The last value is _KPRCB which points to the KTHREAD structure.

0: kd> dt _KPCR fffff805`72f0f000 Prcb.CurrentThread
nt!_KPCR
   +0x180 Prcb               : 
      +0x008 CurrentThread      : 0xfffff805`76d91400 _KTHREAD

We can go even further by inspecting the ApcState struct which holds a pointer to KTHREAD

0: kd> dt _KPCR fffff805`72f0f000 Prcb.CurrentThread->ApcState.
nt!_KPCR
   +0x180 Prcb                          : 
      +0x008 CurrentThread                 : 
         +0x098 ApcState                      : 
            +0x000 ApcListHead                   : [2] _LIST_ENTRY [ 0xfffff805`76d91498 - 0xfffff805`76d91498 ]
            +0x020 Process                       : 0xffffbb0d`c826d300 _KPROCESS

We can now summarize the above section by stating that KPRCB holds a pointer to the current thread, which in turns points to its KTRHEAD and back into the KPROCESS/EPROCESS structure via the APcState field.

KUSER SHARED DATA

Amount of kernel information shared with user-mode, in order to avoid multiple transition to kernel. !kuser command returns only a limited subset, so it’s better to use the dx command. It can be reached at the fixed address 0x7ffe0000 from user-mode, while from kernel is located at fffff78000000000 on x64 architectures.

kd> dx (nt!_KUSER_SHARED_DATA*)0x7ffe0000
(nt!_KUSER_SHARED_DATA*)0x7ffe0000                 : 0x7ffe0000 [Type: _KUSER_SHARED_DATA *]
    [+0x000] TickCountLowDeprecated : 0x0 [Type: unsigned long]
    [+0x004] TickCountMultiplier : 0xfa00000 [Type: unsigned long]
    [+0x008] InterruptTime    [Type: _KSYSTEM_TIME]
    [+0x014] SystemTime       [Type: _KSYSTEM_TIME]
    [+0x020] TimeZoneBias     [Type: _KSYSTEM_TIME]
    [+0x02c] ImageNumberLow   : 0x8664 [Type: unsigned short]
    [+0x02e] ImageNumberHigh  : 0x8664 [Type: unsigned short]
    [+0x030] NtSystemRoot     : "C:\Windows" [Type: wchar_t [260]]
    [...]
    [+0x250] RNGSeedVersion   : 0xb [Type: unsigned __int64]
    [+0x258] GlobalValidationRunlevel : 0x0 [Type: unsigned long]
    [+0x25c] TimeZoneBiasStamp : 6 [Type: long]
    [+0x260] NtBuildNumber    : 0x47bb [Type: unsigned long]
    [+0x264] NtProductType    : NtProductWinNt (1) [Type: _NT_PRODUCT_TYPE]
    [+0x268] ProductTypeIsValid : 0x1 [Type: unsigned char]
    [+0x269] Reserved0        [Type: unsigned char [1]]
    [+0x26a] NativeProcessorArchitecture : 0x9 [Type: unsigned short]
    [+0x26c] NtMajorVersion   : 0xa [Type: unsigned long]
    [+0x270] NtMinorVersion   : 0x0 [Type: unsigned long]
    [...]
    [+0x2d4]kdDebuggerEnabled : 0x1 [Type: unsigned char]
    [...]
    [+0x330] Cookie           : 0x4f02913b [Type: unsigned long]
    [...]

Interesting fields are Cookie, used for validating pointers and kdDebuggerEnabled` which tells if Kernel Debugging is enabled on the system. Other system specific values that can be used for fingerprinting purpose.

IRQLs

System Calls

Interrupt Dispatch Table (IDT)

We can inspect the interrupt service routines (ISRs) on a specified interrupt dispatch table (IDT).

kd> rM 0x100
gdtr=fffff8011465dfb0   gdtl=0057 idtr=fffff8011465b000   idtl=0fff tr=0040  ldtr=0000
nt!DbgBreakPointWithStatus:


kd> !idt -a

Dumping IDT: fffff8011465b000

00:	fffff80111d5a100 nt!KiDivideErrorFaultShadow
01:	fffff80111d5a180 nt!KiDebugTrapOrFaultShadow	Stack = 0xFFFFF8011465F9D0
02:	fffff80111d5a200 nt!KiNmiInterruptShadow	Stack = 0xFFFFF8011465F7D0
03:	fffff80111d5a280 nt!KiBreakpointTrapShadow
04:	fffff80111d5a300 nt!KiOverflowTrapShadow
05:	fffff80111d5a380 nt!KiBoundFaultShadow
06:	fffff80111d5a400 nt!KiInvalidOpcodeFaultShadow
07:	fffff80111d5a480 nt!KiNpxNotAvailableFaultShadow
08:	fffff80111d5a500 nt!KiDoubleFaultAbortShadow	Stack = 0xFFFFF8011465F3D0
09:	fffff80111d5a580 nt!KiNpxSegmentOverrunAbortShadow
0a:	fffff80111d5a600 nt!KiInvalidTssFaultShadow
0b:	fffff80111d5a680 nt!KiSegmentNotPresentFaultShadow
0c:	fffff80111d5a700 nt!KiStackFaultShadow
0d:	fffff80111d5a780 nt!KiGeneralProtectionFaultShadow
0e:	fffff80111d5a800 nt!KiPageFaultShadow
0f:	fffff80111d5b2f8 nt!KiIsrThunkShadow+0x78
10:	fffff80111d5a880 nt!KiFloatingErrorFaultShadow
11:	fffff80111d5a900 nt!KiAlignmentFaultShadow
12:	fffff80111d5a980 nt!KiMcheckAbortShadow	Stack = 0xFFFFF8011465F5D0
13:	fffff80111d5aa80 nt!KiXmmExceptionShadow
14:	fffff80111d5ab00 nt!KiVirtualizationExceptionShadow
15:	fffff80111d5ab80 nt!KiControlProtectionFaultShadow
16:	fffff80111d5b330 nt!KiIsrThunkShadow+0xB0

kd> u fffff80111d5b330
nt!KiIsrThunkShadow+0xb0:
fffff801`11d5b330 6a16            push    16h
fffff801`11d5b332 e989070000      jmp     nt!KxIsrLinkageShadow (fffff801`11d5bac0)
fffff801`11d5b337 cc              int     3

Service Descriptor Table

kd> dt nt!*DescriptorTable* -v
Enumerating symbols matching nt!*DescriptorTable*
Address   Size Symbol
fffff80111e51cfc   000 ntkrnlmp!KiOpDescriptorTableStoreSkip (no type info)
fffff80111f95880   000 ntkrnlmp!KeServiceDescriptorTable (no type info)
fffff80111f7da80   000 ntkrnlmp!KeServiceDescriptorTableShadow (no type info)

These two tables contain System Service Tables (SSTs) and specifically, KeServiceDescriptorTableShadow contains GUI-related functions (GDI). An SST is a Windows lookup struct table

kd> dps nt!KeServiceDescriptorTable
fffff801`11f95880  fffff801`11e2dc10 nt!KiServiceTable
fffff801`11f95888  00000000`00000000
fffff801`11f95890  00000000`000001d0
fffff801`11f95898  fffff801`11e2e354 nt!KiArgumentTable
fffff801`11f958a0  00000000`00000000
fffff801`11f958a8  00000000`00000000
fffff801`11f958b0  00000000`00000000
fffff801`11f958b8  00000000`00000000
fffff801`11f958c0  fffff801`11d5a280 nt!KiBreakpointTrapShadow
fffff801`11f958c8  fffff801`11d5a300 nt!KiOverflowTrapShadow
fffff801`11f958d0  fffff801`11d5ad00 nt!KiRaiseSecurityCheckFailureShadow
fffff801`11f958d8  fffff801`11d5ad80 nt!KiRaiseAssertionShadow
fffff801`11f958e0  fffff801`11d5ae00 nt!KiDebugServiceTrapShadow
fffff801`11f958e8  fffff801`11d5c180 nt!KiSystemCall64Shadow
fffff801`11f958f0  fffff801`11d5be00 nt!KiSystemCall32Shadow
fffff801`11f958f8  00000000`00000000

If we inspect the content of the ServiceTable we can verify that contains offset of actual kernel routines.

kd> dd /c1 KiServiceTable L4
fffff801`11e2dc10  fced7304
fffff801`11e2dc14  fcf77c00
fffff801`11e2dc18  02b98402
fffff801`11e2dc1c  04746e00

These can be calculated this way (taking the 3rd value here as an example - nt!NtAccessCheck)

kd> u KiServiceTable + (fced7304 >>> 4)
nt!NtAccessCheck:
fffff801`11b1b340 4c8bdc          mov     r11,rsp
fffff801`11b1b343 4883ec68        sub     rsp,68h
fffff801`11b1b347 488b8424a8000000 mov     rax,qword ptr [rsp+0A8h]
fffff801`11b1b34f 4533d2          xor     r10d,r10d
fffff801`11b1b352 458853f0        mov     byte ptr [r11-10h],r10b
fffff801`11b1b356 498943e8        mov     qword ptr [r11-18h],rax
fffff801`11b1b35a 488b8424a0000000 mov     rax,qword ptr [rsp+0A0h]
fffff801`11b1b362 498943e0        mov     qword ptr [r11-20h],rax

We can now, as an example take a random API from NTDLL, like ntReadFile and find its dispatch routine.

kd> u ntdll!ntreadfile L2
ntdll!NtReadFile:
00007ff9`d285c170 4c8bd1          mov     r10,rcx
00007ff9`d285c173 b806000000      mov     eax,6
```copy
he above syscall number is 6, so we can use this value as an offset in the ServiceTable.

```copy
kd> dd /c1 KiServiceTable+4*0x6 L1
fffff801`11e2dc28  01c06105

And finally verify that we have an analogous symbol in the kernel routine.

kd> u KiServiceTable + (01c06105 >>> 4) L1
nt!NtReadFile:
fffff801`11fee220 4c894c2420      mov     qword ptr [rsp+20h],r9

Thanks to spotless contribution, we can also dump the whole SSDT list togethr with the symbols names.

kd> .foreach /ps 1 /pS 1 ( offset {dd /c 1 nt!KiServiceTable L poi(nt!KeServiceDescriptorTable+10)}){ r $t0 = ( offset >>> 4) + nt!KiServiceTable; .printf "%p - %y\n", $t0, $t0 }

fffff80111b1b340 - nt!NtAccessCheck (fffff801`11b1b340)
fffff80111b253d0 - nt!NtWorkerFactoryWorkerReady (fffff801`11b253d0)
fffff801120e7450 - nt!NtAcceptConnectPort (fffff801`120e7450)
fffff801122a22f0 - nt!NtMapUserPhysicalPagesScatter (fffff801`122a22f0)
fffff80111ffcb50 - nt!NtWaitForSingleObject (fffff801`11ffcb50)
fffff80111bcde10 - nt!NtCallbackReturn (fffff801`11bcde10)
fffff80111fee220 - nt!NtReadFile (fffff801`11fee220)
fffff80111ff1770 - nt!NtDeviceIoControlFile (fffff801`11ff1770)
fffff8011204eef0 - nt!NtWriteFile (fffff801`1204eef0)
fffff801120b7da0 - nt!NtRemoveIoCompletion (fffff801`120b7da0)
fffff801120b9d10 - nt!NtReleaseSemaphore (fffff801`120b9d10)
fffff80111fd74f0 - nt!NtReplyWaitReceivePort (fffff801`11fd74f
[...]

Syscall Walkthrough

As an example, we can inspect the lifecycle of the ReadFile API.

From KERNELBASE (an abstaction of KERNEL32) we se that the actual UserLand function is imported from NTDLL.

kd> uf ReadFile
Flow analysis was incomplete, some code may be missing
KERNELBASE!ReadFile:
00007fff`048651b0 48895c2410      mov     qword ptr [rsp+10h],rbx
00007fff`048651b5 4c894c2420      mov     qword ptr [rsp+20h],r9
[...]
00007fff`04865220 48ff15e9171800  call    qword ptr [KERNELBASE!_imp_NtReadFile (00007fff`049e6a10)]


kd> dps 00007fff`049e6a10
00007fff`049e6a10  00007fff`06bbc170 ntdll!NtReadFile
00007fff`049e6a18  00007fff`06c1bf40 ntdll!RtlRaiseStatus
00007fff`049e6a20  00007fff`06b39f60 ntdll!RtlCompareUnicodeString
00007fff`049e6a28  00007fff`06b66b90 ntdll!RtlTryAcquirePebLock
00007fff`049e6a30  00007fff`06b954b0 ntdll!RtlReleasePebLock
00007fff`049e6a38  00007fff`06bb1f60 ntdll!wcsspn

As we inspect NTDLL NtReadFile function, we can spot the 0x6 value, that refers to the SYSCALL number Then a check in K_USER_SHARED_DATA is performed to verify the system capabilities and if is a x64 CPU is running, it will execute the SYSCALL instruction, otherwise a 0x2e interrupt will be triggered

kd> uf  ntdll!NtReadFile
ntdll!NtReadFile:
00007fff`06bbc170 4c8bd1          mov     r10,rcx
00007fff`06bbc173 b806000000      mov     eax,6
00007fff`06bbc178 f604250803fe7f01 test    byte ptr [SharedUserData+0x308 (00000000`7ffe0308)],1
00007fff`06bbc180 7503            jne     ntdll!NtReadFile+0x15 (00007fff`06bbc185)  Branch

ntdll!NtReadFile+0x12:
00007fff`06bbc182 0f05            syscall
00007fff`06bbc184 c3              ret

ntdll!NtReadFile+0x15:
00007fff`06bbc185 cd2e            int     2Eh
00007fff`06bbc187 c3              ret

Once we hit the userland side of the function, we can inspect its privileges and PL level, which 3 as expected.

reakpoint 1 hit
ntdll!NtReadFile+0x12:
0033:00007ff9`8ae5c182 0f05            syscall
kd> r cs
cs=0033
kd> dg 33
                                                    P Si Gr Pr Lo
Sel        Base              Limit          Type    l ze an es ng Flags
---- ----------------- ----------------- ---------- - -- -- -- -- --------
0033 00000000`00000000 00000000`00000000 Code RE Ac 3 Nb By P  Lo 000002fb

On the other end, if we continue on the kernel-side version, we’ll se the actual Ring 0 in the code segment.

kd> g
Breakpoint 0 hit
nt!NtReadFile:
fffff805`54cb1830 4c894c2420      mov     qword ptr [rsp+20h],r9
kd> r cs
cs=0010
kd> dg 10
                                                    P Si Gr Pr Lo
Sel        Base              Limit          Type    l ze an es ng Flags
---- ----------------- ----------------- ---------- - -- -- -- -- --------
0010 00000000`00000000 00000000`00000000 Code RE Ac 0 Nb By P  Lo 0000029b

We can also double check in the Service Table that the correct offset will point to the actual kernel system call implementation.

kd> dd /c1 kiservicetable+4*0x6 L1
fffff803`75e2dc28  01c06105

kd> u kiservicetable + (01c06105>>>4) L1
nt!NtReadFile:
fffff803`75fee220 4c894c2420      mov     qword ptr [rsp+20h],r9

nt!KiSystemCall64Shadow under the miscroscope

Analyzing the SYSCALL instruction itself, we can see it takes the value saved in EAX (0x6) and jump to the system call handler that is saved into the IA32_LSTAR MSR register (from the Intel manual) which is aptly named nt!KiSystemCall64Shadow. This this the Kernel RIP Syscall handler in long mode (64-bit only). When the SYSCALL instructions are performed, the code jumps to kernel-mode routine whose address is pointed to by a Model Specific Register (MSR). MSRs are special, CPU specific, registers that must be accessed through rdmsr (read) and wrmsr (write) CPU instructions through an index. For x64, the three values we are after are:

MSR Index Description
IA32_STAR 0xC0000081 Ring 0 and Ring 3 Segments + SYSCALL EIP:00-31 = SYSCALL EIP32-47 = kernel segment base48-63 = user segment base.
IA32_LSTAR 0xC0000082 The kernel’s RIP for SYSCALL in long mode (64-bit software)
IA32_CSTAR 0xC0000083 The kernel’s RIP for SYSCALL in compatibility mode.
IA32_SFMASK 0xC0000084 The low 32 bits are the SYSCALL flag mask. If a bit in this is set, the corresponding bit in EFLAGS is cleared.

If we take a peek at the IA32_STAR register:

kd> rdmsr 0xc0000081
msr[c0000081] = 00230010`00000000

which deflates to: 0023001000000000, according to the structure of that STAR:

sysret CS : 0023 sysret SS : 002B ; CS + 8 sysret CS 64bit : 0033 ; CS + 16 syscall CS : 0010 syscall SS : 0018 ; CS + 8

syscall 32bit EIP : 00000000

We can verify both the SYSRET and SYSCALL values by placing two breakpoints, one in ntdll!NtReadFile (SYSRET) and the other at nt!NtReadFile (SYSCALL)

kd> bl
     0 e Disable Clear  fffff807`3c3f1220     0001 (0001) nt!NtReadFile
     1 e Disable Clear  00007ff8`ed23c170     0001 (0001) ntdll!NtReadFile

kd> g
Breakpoint 1 hit
ntdll!NtReadFile:
0033:00007ff8`ed23c170 4c8bd1          mov     r10,rcx

kd> r
rax=00007ff8ed23c170 rbx=0000000000000000 rcx=0000000000000768
rdx=0000000000000000 rsi=0000000000000000 rdi=000000f7e4b1f398
rip=00007ff8ed23c170 rsp=000000f7e4b1f298 rbp=0000000000000001
 r8=0000000000000000  r9=0000000000000000 r10=00000fff1da4782f
r11=8888848888555555 r12=0000000000000019 r13=0000020640231700
r14=000000f7e4b1f384 r15=0000000000000768
iopl=0         nv up ei pl nz na pe cy
cs=0033  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000203
ntdll!NtReadFile:
0033:00007ff8`ed23c170 4c8bd1          mov     r10,rcx

cs=0033 ss=002b match our SYSRET values as expected.

kd> g
Breakpoint 0 hit
nt!NtReadFile:
fffff807`3c3f1220 4c894c2420      mov     qword ptr [rsp+20h],r9
kd> r
rax=fffff8073c3f1220 rbx=ffff838352610080 rcx=0000000000000768
rdx=0000000000000000 rsi=000000f7e4b1f2b8 rdi=ffffdb0b0408fa28
rip=fffff8073c3f1220 rsp=ffffdb0b0408fa08 rbp=ffffdb0b0408fb00
 r8=0000000000000000  r9=0000000000000000 r10=fffff8073c3f1220
r11=fffff8073bfdecc8 r12=0000000000000019 r13=0000020640231700
r14=000000f7e4b1f384 r15=0000000000000768
iopl=0         nv up ei pl zr na po nc
cs=0010  ss=0018  ds=002b  es=002b  fs=0053  gs=002b             efl=00040246
nt!NtReadFile:
fffff807`3c3f1220 4c894c2420      mov     qword ptr [rsp+20h],r9 ss:0018:ffffdb0b`0408fa28=0000000000000000

And cs=0010 ss=0018 match the above values from IA32_STAR MSR register as well. Now let’s see what is the content of the IA32_LSTAR MSR, which is supposed to be the syscall handler.

kd> rdmsr 0xc0000082
msr[c0000082] = fffff803`75d5c180

kd> u fffff803`75d5c180
nt!KiSystemCall64Shadow:
fffff803`75d5c180 0f01f8          swapgs
fffff803`75d5c183 654889242510700000 mov   qword ptr gs:[7010h],rsp
fffff803`75d5c18c 65488b242500700000 mov   rsp,qword ptr gs:[7000h]
fffff803`75d5c195 650fba24251870000001 bt  dword ptr gs:[7018h],1
fffff803`75d5c19f 7203            jb      nt!KiSystemCall64Shadow+0x24 (fffff803`75d5c1a4)
fffff803`75d5c1a1 0f22dc          mov     cr3,rsp
fffff803`75d5c1a4 65488b242508700000 mov   rsp,qword ptr gs:[7008h]
fffff803`75d5c1ad 6a2b            push    2Bh

There are actually two different SysCall handlers, with and without the ‘Shadow’ keyword. The “Shadow” comes from the “Kernel Virtual Address Shadow” feature aimed to fix the Meltdown bug.

The swapgs privileged instruction is used to swap/exchange the current GS base register value with the value residing in the MSR address C0000102H (IA32_KERNEL_GS_BASE). To be more clear, the value of GS base register equals to the value contained into the IA32_GS_BASE MSR. In x64 Windows systems, the values are:

  • IA32_KERNEL_GS_BASE – Pointer to current processor control region (PCR), specifically the Kernel Processor Control Region(KPCR)
  • IA32_GS_BASE – Pointer to current execution thread TEB

So, in 64 long-mode, the GS segment always points to current thread TEB,in user mode, whereas in kernel mode points to current processor PCR.

The next instruction, mov qword ptr gs:[7010h],rsp saves the user-land stack pointer into the

Continuing reading the Syscall routine, the GS:7000h value is saved at RSP, containing the x64 page directory (PML4) Quoting the Fortinet article about the next instruction bt dword ptr gs:[7018h],1 mov cr3,rsp

A flag […] will be checked, and if swapping is needed then the base of PML4 (corresponding to the kernel address space) will be moved into CR3. At this point the kernel stack is finally accessible and everything works normally. We note that swapping may not always be needed as it may have already happened previously (for example, interrupt while servicing system calls).One subtle thing to notice is that after the new PML4 has been moved into CR3 the address space is switched instantaneously, and the very next instruction fetch happens on the new address space (private to the kernel). But since KiSystemCall64Shadow is mapped into the very same virtual address, everything “just works”.

A summary of the GS values:

value description
gs:7000 PML4
gs:7008 Kernel Stack
gs:7010 Previous Stack
gs:7018 Flag

So let’s expand once more the syscall routine code with comment on each instruction:

nt!KiSystemCall64Shadow:
fffff804`17f63180 0f01f8          swapgs                             ; swap the value inside GS base register from TEB (user) to PCR (kernel)
fffff804`17f63183 654889242510700000 mov   qword ptr gs:[7010h],rsp  ; saves current user stack into 
fffff804`17f6318c 65488b242500700000 mov   rsp,qword ptr gs:[7000h]  ; saves KPCR base into RSP
fffff804`17f63195 650fba24251870000001 bt  dword ptr gs:[7018h],1    ; checks if last bit of KPCR has Kernel Page Table Integrity KPTI enabled for this process
fffff804`17f6319f 7203            jb      nt!KiSystemCall64Shadow+0x24 
nt!KiSystemCall64Shadow+0x21:
fffff804`17f631a1 0f22dc          mov     cr3,rsp                     ; if so, the kernel KPCR will be loaded in CR3

As a summary, the whole system call flow can be visualized through the following graph:

syscall_flow