[windows] kernel internals
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: