Go to file
2020-02-24 00:32:53 +07:00
src remove warnings 2020-02-24 00:32:53 +07:00
.gitignore first init 2020-02-15 17:39:45 +07:00
Cargo.lock load driver code 2020-02-23 02:04:09 +07:00
Cargo.toml add driver to registry 2020-02-23 03:06:01 +07:00
README.md update sample ouput 2020-02-18 17:44:14 +07:00

If you came here for MmNonPagedPoolStart, MmNonPagedPoolEnd, you ended up at the right place.

NonPagedPool in Windows has two variables that defined the start and end of the section in kernel memory. Online blog posts and tutorials show an outdated version of these two variables.

Take a look at this old post. _DBGKD_GET_VERSION64 KdVersionBlock was a very important structure into the debugger block of Windows. However, if you try to find this structure in Windows 10, you will hit KdVersionBlock == 0 (Ouch!!!). But this structure provides offset into MmNonPagedPool{Start,End}, how can we get those?

Luckily, both MmNonPagedPoolStart and MmNonPagedPoolEnd in Windows XP, can be found by offseting from ntoskrnl.exe. Rekall team are very positive that their tools doesn't rely on profiles file like Volatility but use PDB provided by Windows to find these values.

In Rekall source code, the values of those variables are:

  • Windows XP: MmNonPagedPool{Start,End}
  • Windows 7 and maybe 8: MiNonPagedPoolStartAligned, MiNonPagedPoolEnd, and MiNonPagedPoolBitMap
  • Windows 10 below

In Windows 7, 8, another field was added to controll the allocation of NonPagedPool, which is why there is this paper about pool tag quick scanning.

However, from Windows 10, the whole game changed around when the global offset to those (similar) variables are gone. Instead Windows 10 introduced a new variable MiState. MiState offset is available and we can get those start/end variables by either:

  • Windows 2015: *((ntoskrnl.exe+MiState)->SystemNodeInformation->NonPagedPool{First,Last}Va)
  • Windows 2016: *((ntoskrnl.exe+MiState)->Hardware.SystemNodeInformation->NonPagedPool{First,Last}Va)

The NonPagedBitMap was still visible untill the May 2019 Update, here, take a look at these 2 consecutive update 1809 Redstone 5 (October Update) and 1903 19H1 (May 2019 Update).

Yeah, now pool tag quick scanning is useless (gah). Windows OS changes quite frequently right? Tell you more, I am using the Insider version of Windows in 2020, and guess what, I found out that they put another struct to point to those value. So now we need to go like this:

  • Windows 2020 Insider preview: *((ntoskrnl.exe+MiState)->SystemNodeNonPagedPool->NonPagedPool{First,Last}Va)

If you go with low-level, then you only care about the offset and formula to get those variables but knowing the structure is well benefit.

Anyway, I create this project to help me with my thesis, following outdated structs online yields no result. Oh, yeah, a guy seems to be asking on how to get MmNonPagedPoolStart on stackexchange, too bad the answer is not so much helpful.

Take a look at my ntoskrnl.exe pdb file parsed.

PDB for Amd64, guid: 3c6978d6-66d9-c05a-53b6-a1e1561282c8, age: 1,

Void(UNNOWN) PsActiveProcessHead 0xc1f970 23:129392
Void(UNNOWN) MiState 0xc4f200 23:324096
Void(UNNOWN) KeNumberNodes 0xcfc000 24:0
Void(UNNOWN) PsLoadedModuleList 0xc2ba30 23:178736
Void(UNNOWN) KdDebuggerDataBlock 0xc00a30 23:2608

beginstruct _LIST_ENTRY
	0x0 _LIST_ENTRY* Flink
	0x8 _LIST_ENTRY* Blink
endstruct

beginstruct _RTL_BITMAP
	0x0 U32 SizeOfBitMap
	0x8 U32 Buffer
endstruct

beginstruct _EPROCESS
	0x0 _KPROCESS Pcb
	0x438 _EX_PUSH_LOCK ProcessLock
	0x440 Void UniqueProcessId
	0x448 _LIST_ENTRY ActiveProcessLinks
	0x458 _EX_RUNDOWN_REF RundownProtect
	0x460 U32 Flags2
	0x460 UNNOWN JobNotReallyActive
	0x460 UNNOWN AccountingFolded
	0x460 UNNOWN NewProcessReported
	0x460 UNNOWN ExitProcessReported
	0x460 UNNOWN ReportCommitChanges
	0x460 UNNOWN LastReportMemory
	0x460 UNNOWN ForceWakeCharge
	0x460 UNNOWN CrossSessionCreate
	0x460 UNNOWN NeedsHandleRundown
	0x460 UNNOWN RefTraceEnabled
	0x460 UNNOWN PicoCreated
	0x460 UNNOWN EmptyJobEvaluated
	0x460 UNNOWN DefaultPagePriority
	0x460 UNNOWN PrimaryTokenFrozen
	0x460 UNNOWN ProcessVerifierTarget
	0x460 UNNOWN RestrictSetThreadContext
	0x460 UNNOWN AffinityPermanent
	0x460 UNNOWN AffinityUpdateEnable
	0x460 UNNOWN PropagateNode
	0x460 UNNOWN ExplicitAffinity
	0x460 UNNOWN ProcessExecutionState
	0x460 UNNOWN EnableReadVmLogging
	0x460 UNNOWN EnableWriteVmLogging
	0x460 UNNOWN FatalAccessTerminationRequested
	0x460 UNNOWN DisableSystemAllowedCpuSet
	0x460 UNNOWN ProcessStateChangeRequest
	0x460 UNNOWN ProcessStateChangeInProgress
	0x460 UNNOWN InPrivate
	0x464 U32 Flags
	0x464 UNNOWN CreateReported
	0x464 UNNOWN NoDebugInherit
	0x464 UNNOWN ProcessExiting
	0x464 UNNOWN ProcessDelete
	0x464 UNNOWN ManageExecutableMemoryWrites
	0x464 UNNOWN VmDeleted
	0x464 UNNOWN OutswapEnabled
	0x464 UNNOWN Outswapped
	0x464 UNNOWN FailFastOnCommitFail
	0x464 UNNOWN Wow64VaSpace4Gb
	0x464 UNNOWN AddressSpaceInitialized
	0x464 UNNOWN SetTimerResolution
	0x464 UNNOWN BreakOnTermination
	0x464 UNNOWN DeprioritizeViews
	0x464 UNNOWN WriteWatch
	0x464 UNNOWN ProcessInSession
	0x464 UNNOWN OverrideAddressSpace
	0x464 UNNOWN HasAddressSpace
	0x464 UNNOWN LaunchPrefetched
	0x464 UNNOWN Background
	0x464 UNNOWN VmTopDown
	0x464 UNNOWN ImageNotifyDone
	0x464 UNNOWN PdeUpdateNeeded
	0x464 UNNOWN VdmAllowed
	0x464 UNNOWN ProcessRundown
	0x464 UNNOWN ProcessInserted
	0x464 UNNOWN DefaultIoPriority
	0x464 UNNOWN ProcessSelfDelete
	0x464 UNNOWN SetTimerResolutionLink
	0x468 _LARGE_INTEGER CreateTime
	0x470 U64[16] ProcessQuotaUsage
	0x480 U64[16] ProcessQuotaPeak
	0x490 U64 PeakVirtualSize
	0x498 U64 VirtualSize
	0x4a0 _LIST_ENTRY SessionProcessLinks
	0x4b0 Void ExceptionPortData
	0x4b0 U64 ExceptionPortValue
	0x4b0 UNNOWN ExceptionPortState
	0x4b8 _EX_FAST_REF Token
	0x4c0 U64 MmReserved
	0x4c8 _EX_PUSH_LOCK AddressCreationLock
	0x4d0 _EX_PUSH_LOCK PageTableCommitmentLock
	0x4d8 _ETHREAD* RotateInProgress
	0x4e0 _ETHREAD* ForkInProgress
	0x4e8 _EJOB* CommitChargeJob
	0x4f0 _RTL_AVL_TREE CloneRoot
	0x4f8 volatile U64 NumberOfPrivatePages
	0x500 volatile U64 NumberOfLockedPages
	0x508 Void Win32Process
	0x510 _EJOB* Job
	0x518 Void SectionObject
	0x520 Void SectionBaseAddress
	0x528 U32 Cookie
	0x530 _PAGEFAULT_HISTORY* WorkingSetWatch
	0x538 Void Win32WindowStation
	0x540 Void InheritedFromUniqueProcessId
	0x548 volatile U64 OwnerProcessId
	0x550 _PEB* Peb
	0x558 _MM_SESSION_SPACE* Session
	0x560 Void Spare1
	0x568 _EPROCESS_QUOTA_BLOCK* QuotaBlock
	0x570 _HANDLE_TABLE* ObjectTable
	0x578 Void DebugPort
	0x580 _EWOW64PROCESS* WoW64Process
	0x588 Void DeviceMap
	0x590 Void EtwDataSource
	0x598 U64 PageDirectoryPte
	0x5a0 _FILE_OBJECT* ImageFilePointer
	0x5a8 UChar[15] ImageFileName
	0x5b7 UChar PriorityClass
	0x5b8 Void SecurityPort
	0x5c0 _SE_AUDIT_PROCESS_CREATION_INFO SeAuditProcessCreationInfo
	0x5c8 _LIST_ENTRY JobLinks
	0x5d8 Void HighestUserAddress
	0x5e0 _LIST_ENTRY ThreadListHead
	0x5f0 volatile U32 ActiveThreads
	0x5f4 U32 ImagePathHash
	0x5f8 U32 DefaultHardErrorProcessing
	0x5fc I32 LastThreadExitStatus
	0x600 _EX_FAST_REF PrefetchTrace
	0x608 Void LockedPagesList
	0x610 _LARGE_INTEGER ReadOperationCount
	0x618 _LARGE_INTEGER WriteOperationCount
	0x620 _LARGE_INTEGER OtherOperationCount
	0x628 _LARGE_INTEGER ReadTransferCount
	0x630 _LARGE_INTEGER WriteTransferCount
	0x638 _LARGE_INTEGER OtherTransferCount
	0x640 U64 CommitChargeLimit
	0x648 volatile U64 CommitCharge
	0x650 volatile U64 CommitChargePeak
	0x680 _MMSUPPORT_FULL Vm
	0x7c0 _LIST_ENTRY MmProcessLinks
	0x7d0 U32 ModifiedPageCount
	0x7d4 I32 ExitStatus
	0x7d8 _RTL_AVL_TREE VadRoot
	0x7e0 Void VadHint
	0x7e8 U64 VadCount
	0x7f0 volatile U64 VadPhysicalPages
	0x7f8 U64 VadPhysicalPagesLimit
	0x800 _ALPC_PROCESS_CONTEXT AlpcContext
	0x820 _LIST_ENTRY TimerResolutionLink
	0x830 _PO_DIAG_STACK_RECORD* TimerResolutionStackRecord
	0x838 U32 RequestedTimerResolution
	0x83c U32 SmallestTimerResolution
	0x840 _LARGE_INTEGER ExitTime
	0x848 _INVERTED_FUNCTION_TABLE* InvertedFunctionTable
	0x850 _EX_PUSH_LOCK InvertedFunctionTableLock
	0x858 U32 ActiveThreadsHighWatermark
	0x85c U32 LargePrivateVadCount
	0x860 _EX_PUSH_LOCK ThreadListLock
	0x868 Void WnfContext
	0x870 _EJOB* ServerSilo
	0x878 UChar SignatureLevel
	0x879 UChar SectionSignatureLevel
	0x87a _PS_PROTECTION Protection
	0x87b UNNOWN HangCount
	0x87b UNNOWN GhostCount
	0x87b UNNOWN PrefilterException
	0x87c U32 Flags3
	0x87c UNNOWN Minimal
	0x87c UNNOWN ReplacingPageRoot
	0x87c UNNOWN Crashed
	0x87c UNNOWN JobVadsAreTracked
	0x87c UNNOWN VadTrackingDisabled
	0x87c UNNOWN AuxiliaryProcess
	0x87c UNNOWN SubsystemProcess
	0x87c UNNOWN IndirectCpuSets
	0x87c UNNOWN RelinquishedCommit
	0x87c UNNOWN HighGraphicsPriority
	0x87c UNNOWN CommitFailLogged
	0x87c UNNOWN ReserveFailLogged
	0x87c UNNOWN SystemProcess
	0x87c UNNOWN HideImageBaseAddresses
	0x87c UNNOWN AddressPolicyFrozen
	0x87c UNNOWN ProcessFirstResume
	0x87c UNNOWN ForegroundExternal
	0x87c UNNOWN ForegroundSystem
	0x87c UNNOWN HighMemoryPriority
	0x87c UNNOWN EnableProcessSuspendResumeLogging
	0x87c UNNOWN EnableThreadSuspendResumeLogging
	0x87c UNNOWN SecurityDomainChanged
	0x87c UNNOWN SecurityFreezeComplete
	0x87c UNNOWN VmProcessorHost
	0x87c UNNOWN VmProcessorHostTransition
	0x87c UNNOWN AltSyscall
	0x87c UNNOWN TimerResolutionIgnore
	0x880 I32 DeviceAsid
	0x888 Void SvmData
	0x890 _EX_PUSH_LOCK SvmProcessLock
	0x898 U64 SvmLock
	0x8a0 _LIST_ENTRY SvmProcessDeviceListHead
	0x8b0 U64 LastFreezeInterruptTime
	0x8b8 _PROCESS_DISK_COUNTERS* DiskCounters
	0x8c0 Void PicoContext
	0x8c8 Void EnclaveTable
	0x8d0 U64 EnclaveNumber
	0x8d8 _EX_PUSH_LOCK EnclaveLock
	0x8e0 U32 HighPriorityFaultsAllowed
	0x8e8 _PO_PROCESS_ENERGY_CONTEXT* EnergyContext
	0x8f0 Void VmContext
	0x8f8 U64 SequenceNumber
	0x900 U64 CreateInterruptTime
	0x908 U64 CreateUnbiasedInterruptTime
	0x910 U64 TotalUnbiasedFrozenTime
	0x918 U64 LastAppStateUpdateTime
	0x920 UNNOWN LastAppStateUptime
	0x920 UNNOWN LastAppState
	0x928 volatile U64 SharedCommitCharge
	0x930 _EX_PUSH_LOCK SharedCommitLock
	0x938 _LIST_ENTRY SharedCommitLinks
	0x948 U64 AllowedCpuSets
	0x950 U64 DefaultCpuSets
	0x948 U64 AllowedCpuSetsIndirect
	0x950 U64 DefaultCpuSetsIndirect
	0x958 Void DiskIoAttribution
	0x960 Void DxgProcess
	0x968 U32 Win32KFilterSet
	0x970 volatile _PS_INTERLOCKED_TIMER_DELAY_VALUES ProcessTimerDelay
	0x978 volatile U32 KTimerSets
	0x97c volatile U32 KTimer2Sets
	0x980 volatile U32 ThreadTimerSets
	0x988 U64 VirtualTimerListLock
	0x990 _LIST_ENTRY VirtualTimerListHead
	0x9a0 _WNF_STATE_NAME WakeChannel
	0x9a0 _PS_PROCESS_WAKE_INFORMATION WakeInfo
	0x9d0 U32 MitigationFlags
	0x9d0 <anonymous-tag> MitigationFlagsValues
	0x9d4 U32 MitigationFlags2
	0x9d4 <anonymous-tag> MitigationFlags2Values
	0x9d8 Void PartitionObject
	0x9e0 U64 SecurityDomain
	0x9e8 U64 ParentSecurityDomain
	0x9f0 Void CoverageSamplerContext
	0x9f8 Void MmHotPatchContext
	0xa00 _KE_IDEAL_PROCESSOR_ASSIGNMENT_BLOCK IdealProcessorAssignmentBlock
	0xab8 _RTL_AVL_TREE DynamicEHContinuationTargetsTree
	0xac0 _EX_PUSH_LOCK DynamicEHContinuationTargetsLock
endstruct

beginstruct _RTL_BITMAP_EX
	0x0 U64 SizeOfBitMap
	0x8 U64 Buffer
endstruct

beginstruct _MI_SYSTEM_INFORMATION
	0x0 _MI_POOL_STATE Pools
	0xc0 _MI_SECTION_STATE Sections
	0x400 _MI_SYSTEM_IMAGE_STATE SystemImages
	0x4a8 _MI_SESSION_STATE Sessions
	0x1530 _MI_PROCESS_STATE Processes
	0x1580 _MI_HARDWARE_STATE Hardware
	0x1740 _MI_SYSTEM_VA_STATE SystemVa
	0x1c00 _MI_COMBINE_STATE PageCombines
	0x1c20 _MI_PAGELIST_STATE PageLists
	0x1cc0 _MI_PARTITION_STATE Partitions
	0x1d80 _MI_SHUTDOWN_STATE Shutdowns
	0x1df8 _MI_ERROR_STATE Errors
	0x1f00 _MI_ACCESS_LOG_STATE AccessLog
	0x1f80 _MI_DEBUGGER_STATE Debugger
	0x20a0 _MI_STANDBY_STATE Standby
	0x2140 _MI_SYSTEM_PTE_STATE SystemPtes
	0x2340 _MI_IO_PAGE_STATE IoPages
	0x2400 _MI_PAGING_IO_STATE PagingIo
	0x24b0 _MI_COMMON_PAGE_STATE CommonPages
	0x2580 _MI_SYSTEM_TRIM_STATE Trims
	0x25c0 _MI_SYSTEM_ZEROING Zeroing
	0x25e0 _MI_ENCLAVE_STATE Enclaves
	0x2628 U64 Cookie
	0x2630 Void** BootRegistryRuns
	0x2638 volatile I32 ZeroingDisabled
	0x263c UChar FullyInitialized
	0x263d UChar SafeBooted
	0x2640 const _tlgProvider_t* TraceLogging
	0x2680 _MI_VISIBLE_STATE Vs
endstruct

beginstruct _PEB
	0x0 UChar InheritedAddressSpace
	0x1 UChar ReadImageFileExecOptions
	0x2 UChar BeingDebugged
	0x3 UChar BitField
	0x3 UNNOWN ImageUsesLargePages
	0x3 UNNOWN IsProtectedProcess
	0x3 UNNOWN IsImageDynamicallyRelocated
	0x3 UNNOWN SkipPatchingUser32Forwarders
	0x3 UNNOWN IsPackagedProcess
	0x3 UNNOWN IsAppContainer
	0x3 UNNOWN IsProtectedProcessLight
	0x3 UNNOWN IsLongPathAwareProcess
	0x4 UChar[4] Padding0
	0x8 Void Mutant
	0x10 Void ImageBaseAddress
	0x18 _PEB_LDR_DATA* Ldr
	0x20 _RTL_USER_PROCESS_PARAMETERS* ProcessParameters
	0x28 Void SubSystemData
	0x30 Void ProcessHeap
	0x38 _RTL_CRITICAL_SECTION* FastPebLock
	0x40 _SLIST_HEADER* AtlThunkSListPtr
	0x48 Void IFEOKey
	0x50 U32 CrossProcessFlags
	0x50 UNNOWN ProcessInJob
	0x50 UNNOWN ProcessInitializing
	0x50 UNNOWN ProcessUsingVEH
	0x50 UNNOWN ProcessUsingVCH
	0x50 UNNOWN ProcessUsingFTH
	0x50 UNNOWN ProcessPreviouslyThrottled
	0x50 UNNOWN ProcessCurrentlyThrottled
	0x50 UNNOWN ProcessImagesHotPatched
	0x50 UNNOWN ReservedBits0
	0x54 UChar[4] Padding1
	0x58 Void KernelCallbackTable
	0x58 Void UserSharedInfoPtr
	0x60 U32 SystemReserved
	0x64 U32 AtlThunkSListPtr32
	0x68 Void ApiSetMap
	0x70 U32 TlsExpansionCounter
	0x74 UChar[4] Padding2
	0x78 Void TlsBitmap
	0x80 U32[8] TlsBitmapBits
	0x88 Void ReadOnlySharedMemoryBase
	0x90 Void SharedData
	0x98 Void* ReadOnlyStaticServerData
	0xa0 Void AnsiCodePageData
	0xa8 Void OemCodePageData
	0xb0 Void UnicodeCaseTableData
	0xb8 U32 NumberOfProcessors
	0xbc U32 NtGlobalFlag
	0xc0 _LARGE_INTEGER CriticalSectionTimeout
	0xc8 U64 HeapSegmentReserve
	0xd0 U64 HeapSegmentCommit
	0xd8 U64 HeapDeCommitTotalFreeThreshold
	0xe0 U64 HeapDeCommitFreeBlockThreshold
	0xe8 U32 NumberOfHeaps
	0xec U32 MaximumNumberOfHeaps
	0xf0 Void* ProcessHeaps
	0xf8 Void GdiSharedHandleTable
	0x100 Void ProcessStarterHelper
	0x108 U32 GdiDCAttributeList
	0x10c UChar[4] Padding3
	0x110 _RTL_CRITICAL_SECTION* LoaderLock
	0x118 U32 OSMajorVersion
	0x11c U32 OSMinorVersion
	0x120 U16 OSBuildNumber
	0x122 U16 OSCSDVersion
	0x124 U32 OSPlatformId
	0x128 U32 ImageSubsystem
	0x12c U32 ImageSubsystemMajorVersion
	0x130 U32 ImageSubsystemMinorVersion
	0x134 UChar[4] Padding4
	0x138 U64 ActiveProcessAffinityMask
	0x140 U32[240] GdiHandleBuffer
	0x230 Void(UNNOWN)* PostProcessInitRoutine
	0x238 Void TlsExpansionBitmap
	0x240 U32[128] TlsExpansionBitmapBits
	0x2c0 U32 SessionId
	0x2c4 UChar[4] Padding5
	0x2c8 _ULARGE_INTEGER AppCompatFlags
	0x2d0 _ULARGE_INTEGER AppCompatFlagsUser
	0x2d8 Void pShimData
	0x2e0 Void AppCompatInfo
	0x2e8 _UNICODE_STRING CSDVersion
	0x2f8 const _ACTIVATION_CONTEXT_DATA* ActivationContextData
	0x300 _ASSEMBLY_STORAGE_MAP* ProcessAssemblyStorageMap
	0x308 const _ACTIVATION_CONTEXT_DATA* SystemDefaultActivationContextData
	0x310 _ASSEMBLY_STORAGE_MAP* SystemAssemblyStorageMap
	0x318 U64 MinimumStackCommit
	0x320 Void[32] SparePointers
	0x340 U32[20] SpareUlongs
	0x358 Void WerRegistrationData
	0x360 Void WerShipAssertPtr
	0x368 Void pUnused
	0x370 Void pImageHeaderHash
	0x378 U32 TracingFlags
	0x378 UNNOWN HeapTracingEnabled
	0x378 UNNOWN CritSecTracingEnabled
	0x378 UNNOWN LibLoaderTracingEnabled
	0x378 UNNOWN SpareTracingBits
	0x37c UChar[4] Padding6
	0x380 U64 CsrServerReadOnlySharedMemoryBase
	0x388 U64 TppWorkerpListLock
	0x390 _LIST_ENTRY TppWorkerpList
	0x3a0 Void[1024] WaitOnAddressHashTable
	0x7a0 Void TelemetryCoverageHeader
	0x7a8 U32 CloudFileFlags
	0x7ac U32 CloudFileDiagFlags
	0x7b0 RChar PlaceholderCompatibilityMode
	0x7b1 RChar[7] PlaceholderCompatibilityModeReserved
	0x7b8 _LEAP_SECOND_DATA* LeapSecondData
	0x7c0 U32 LeapSecondFlags
	0x7c0 UNNOWN SixtySecondEnabled
	0x7c0 UNNOWN Reserved
	0x7c4 U32 NtGlobalFlag2
endstruct

beginstruct _MI_DYNAMIC_BITMAP
	0x0 _RTL_BITMAP_EX Bitmap
	0x10 U64 MaximumSize
	0x18 U64 Hint
	0x20 Void BaseVa
	0x28 U64 SizeTopDown
	0x30 U64 HintTopDown
	0x38 Void BaseVaTopDown
	0x40 U64 SpinLock
endstruct

beginstruct _MI_HARDWARE_STATE
	0x0 U32 NodeMask
	0x4 U32 NumaHintIndex
	0x8 U32 NumaLastRangeIndexInclusive
	0xc UChar NodeShift
	0xd UChar ChannelShift
	0x10 U32 ChannelHintIndex
	0x14 U32 ChannelLastRangeIndexInclusive
	0x18 _MI_NODE_NUMBER_ZERO_BASED* NodeGraph
	0x20 _MI_SYSTEM_NODE_NONPAGED_POOL* SystemNodeNonPagedPool
	0x28 _HAL_NODE_RANGE[32] TemporaryNumaRanges
	0x48 _HAL_NODE_RANGE* NumaMemoryRanges
	0x50 _HAL_CHANNEL_MEMORY_RANGES* ChannelMemoryRanges
	0x58 U32 SecondLevelCacheSize
	0x5c U32 FirstLevelCacheSize
	0x60 U32 PhysicalAddressBits
	0x64 U32 PfnDatabasePageBits
	0x68 U32 LogicalProcessorsPerCore
	0x6c UChar ProcessorCachesFlushedOnPowerLoss
	0x70 U64 TotalPagesAllowed
	0x78 U32 SecondaryColorMask
	0x7c U32 SecondaryColors
	0x80 U32 FlushTbForAttributeChange
	0x84 U32 FlushCacheForAttributeChange
	0x88 U32 FlushCacheForPageAttributeChange
	0x8c U32 CacheFlushPromoteThreshold
	0x90 _LARGE_INTEGER PerformanceCounterFrequency
	0xc0 U64 InvalidPteMask
	0x100 U32[12] LargePageColors
	0x110 U64 FlushTbThreshold
	0x118 _MI_PFN_CACHE_ATTRIBUTE[16][64] OptimalZeroingAttribute
	0x158 UChar AttributeChangeRequiresReZero
	0x160 _MI_ZERO_COST_COUNTS[32] ZeroCostCounts
	0x180 U64 HighestPossiblePhysicalPage
	0x188 U64 VsmKernelPageCount
endstruct

beginstruct _MI_SYSTEM_NODE_NONPAGED_POOL
	0x0 _MI_DYNAMIC_BITMAP DynamicBitMapNonPagedPool
	0x48 U64 CachedNonPagedPoolCount
	0x50 U64 NonPagedPoolSpinLock
	0x58 _MMPFN* CachedNonPagedPool
	0x60 Void NonPagedPoolFirstVa
	0x68 Void NonPagedPoolLastVa
	0x70 _MI_SYSTEM_NODE_INFORMATION* SystemNodeInformation
endstruct

beginstruct _MI_SYSTEM_NODE_INFORMATION
	0x0 _CACHED_KSTACK_LIST[64] CachedKernelStacks
	0x40 _GROUP_AFFINITY GroupAffinity
	0x50 U16 ProcessorCount
	0x58 Void BootZeroPageTimesPerProcessor
	0x60 U64 CyclesToZeroOneLargePage
	0x68 U64 ScaledCyclesToZeroOneLargePage
	0x70 _MI_WRITE_CALIBRATION WriteCalibration
	0xc0 volatile I32 IoPfnLock
endstruct


Global variables offset are parsed and can be queried by nt! in Windbg. In a kernel driver, we need to get the kernel base address (which is nt!). Kernel base address is the loaded address of ntoskrnl.exe. There is a shellcode to get the address here, using IDT table. But when I use the shellcode with the Windows Insider preview 2020, the address is wrong (it still a loaded PE though). Other ways to get the address are listed here. And hereby I present another way to get the kernel base address.

A device driver can get a pointer to a EPROCESS through the use of PEPROCESS IoGetCurrentProcess. And as we know, EPROCESS has pointer to other EPROCESS as a doubly linked list. If we dump them all out, we can notice a few things:

  • The image name returned by calling IoGetCurrentProcess is System
  • The EPROCESS before System is somehow empty
PVOID eprocess = (PVOID)IoGetCurrentProcess();
DbgPrint("eprocess : 0x%p, [%15s]\n", eprocess, (char*)((ULONG64)eprocess + ImageBaseNameOffset));
for (int i = 0; i < 100; i++) {
  eprocess = (PVOID)(*(ULONG64*)((ULONG64)eprocess + ActiveProcessLinksOffset) - ActiveProcessLinksOffset);
  DbgPrint("eprocess : 0x%p, [%15s]\n", eprocess, (char*)((ULONG64)eprocess + ImageBaseOffset));
}

// sample output
eprocess : 0xFFFFF8037401F528, [               ]
eprocess : 0xFFFF840F5A0D9080, [         System]
eprocess : 0xFFFF840F5A28C040, [  Secure System]
eprocess : 0xFFFF840F5A2EF040, [       Registry]
eprocess : 0xFFFF840F622BF040, [       smss.exe]
eprocess : 0xFFFF840F6187D080, [       smss.exe]
eprocess : 0xFFFF840F6263D140, [      csrss.exe]
eprocess : 0xFFFF840F6277F0C0, [       smss.exe]
eprocess : 0xFFFF840F627C2080, [    wininit.exe]
eprocess : 0xFFFF840F64187140, [      csrss.exe]
eprocess : 0xFFFF840F641CD080, [   services.exe]

And if we debug and compare the address of that Empty EPROCESS+ActiveProcessLinksOffset with nt!PsActiveProcessHead, it is just the same. And with the given offset parsed from the PDB file, we can get kernel base address.

PVOID eprocess = (PVOID)IoGetCurrentProcess();
DbgPrint("eprocess               : 0x%p, [%15s]\n", eprocess, (char*)((ULONG64)eprocess + ImageBaseNameOffset));
PVOID processHead = (PVOID)(*(ULONG64*)((ULONG64)eprocess + ActiveProcessLinksOffset + BLinkOffset));
DbgPrint("PsActiveProcessHead    : 0x%p\n", processHead);
PVOID ntosbase = (PVOID)((ULONG64)processHead - ActiveHeadOffset);
DbgPrint("ntoskrnl.exe           : 0x%p\n", ntosbase);

From now we have successfully get the kernel base address to index into other global variables.

(In this way we use PsActiveProcessHead, but a better way maybe traversing PsLoadedModuleList which could get the correct address of ntoskrnl.exe but I do not know)