diff --git a/README.md b/README.md index cd4f57a..f4512e6 100644 --- a/README.md +++ b/README.md @@ -1,558 +1,35 @@ -> If you came here for `MmNonPagedPoolStart`, `MmNonPagedPoolEnd`, you ended up at the right place. +# LPUS (A live pool-tag scanning solution) -`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. +This is the frontend to the live pool tag scanning solution, the backend is a driver (which is now closed source). -Take a look at [this old post](https://web.archive.org/web/20061110120809/http://www.rootkit.com/newsread.php?newsid=153). `_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? +## How this works -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 simple way, we use PDB files to get the global variable offsets and structure definitions. +The backend finds the kernel base and use these values to calculate the nonpaged-pool range. +A more detailed report is in [nonpaged-pool-range.md](nonpaged-pool-range.md) +The frontend calls the backend to scan for a specific tag. -In [Rekall source code](https://github.com/google/rekall/blob/c5d68e31705f4b5bd2581c1d951b7f6983f7089c/rekall-core/rekall/plugins/windows/pool.py#L87), the values of those variables are: +## How to use -- Windows XP: `MmNonPagedPool{Start,End}` -- Windows 7 and maybe 8: `MiNonPagedPoolStartAligned`, `MiNonPagedPoolEnd`, and `MiNonPagedPoolBitMap` -- Windows 10 below +Example is [here](./src/bin/eprocess_scan.rs). -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](https://www.sciencedirect.com/science/article/pii/S1742287616000062). +```rust +use lpus::{ + driver_state::{DriverState} +}; -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)`](https://www.vergiliusproject.com/kernels/x64/Windows%2010%20%7C%202016/1809%20Redstone%205%20(October%20Update)/\_MI\_SYSTEM\_NODE\_INFORMATION) and [`1903 19H1 (May 2019 Update)`](https://www.vergiliusproject.com/kernels/x64/Windows%2010%20%7C%202016/1903%2019H1%20(May%202019%20Update)/\_MI\_SYSTEM\_NODE\_INFORMATION). - -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`](https://reverseengineering.stackexchange.com/q/6483) on `stackexchange`, too bad [the answer](https://reverseengineering.stackexchange.com/a/6487) 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 MitigationFlagsValues - 0x9d4 U32 MitigationFlags2 - 0x9d4 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](https://gist.github.com/Barakat/34e9924217ed81fd78c9c92d746ec9c6), 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](https://m0uk4.gitbook.io/notebooks/mouka/windowsinternal/find-kernel-module-address-todo). 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 - -```cpp -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)); +fn main() -> Result<(), Box> { + let mut driver = DriverState::new(); + println!("NtLoadDriver() -> 0x{:x}", driver.startup()); + driver.scan_pool(b"Tag ", |pool_addr, header, data_addr| { + })?; + println!("NtUnloadDriver() -> 0x{:x}", driver.shutdown()); } - -// 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. +The closure is a mutable closure, so you can just put a vector and saves the result. +The function signature for the closure is: `FnMut(u64, &[u8], u64) -> Result` +Parsing the struct data is up to you. +You can use `driver.deref_addr(addr, &value)` to dereference an address in kernel space +and `driver.pdb_store.get_offset_r("offset")?` to get an offset from PDB file. -```cpp -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) diff --git a/nonpaged-pool-range.md b/nonpaged-pool-range.md new file mode 100644 index 0000000..8c4fd03 --- /dev/null +++ b/nonpaged-pool-range.md @@ -0,0 +1,559 @@ +> 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](https://web.archive.org/web/20061110120809/http://www.rootkit.com/newsread.php?newsid=153). `_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](https://github.com/google/rekall/blob/c5d68e31705f4b5bd2581c1d951b7f6983f7089c/rekall-core/rekall/plugins/windows/pool.py#L87), 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](https://www.sciencedirect.com/science/article/pii/S1742287616000062). + +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)`](https://www.vergiliusproject.com/kernels/x64/Windows%2010%20%7C%202016/1809%20Redstone%205%20(October%20Update)/\_MI\_SYSTEM\_NODE\_INFORMATION) and [`1903 19H1 (May 2019 Update)`](https://www.vergiliusproject.com/kernels/x64/Windows%2010%20%7C%202016/1903%2019H1%20(May%202019%20Update)/\_MI\_SYSTEM\_NODE\_INFORMATION). + +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`](https://reverseengineering.stackexchange.com/q/6483) on `stackexchange`, too bad [the answer](https://reverseengineering.stackexchange.com/a/6487) 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 MitigationFlagsValues + 0x9d4 U32 MitigationFlags2 + 0x9d4 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](https://gist.github.com/Barakat/34e9924217ed81fd78c9c92d746ec9c6), 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](https://m0uk4.gitbook.io/notebooks/mouka/windowsinternal/find-kernel-module-address-todo). 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 + +```cpp +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. + +```cpp +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) +