Page-Map-Level-4(PML4)table base for
Kernel/System Virtual Address Space.
Directory Table Base(DTB)(or
WinDBG) is the
PAof the base of the top-level paging structure(
Long Mode\x64Paging) whose value is also contained by the
PML4table is also allocated. The
PML4table is stored in
nt!_KPROCESS(Kernel process object) structure's
DirectoryTableBasemember. When a process context switch is made by the processor, this
PAis moved into the
CR3register which the
Memory Management Unit(MMU)can then use along with the
VAoffsets into various paging structures to walk the page tables and translate virtual addresses to appropriate physical addresses.
PAof its root page table base which is moved into
CR3when the process is selected.
Kernel DTBthat maps the
Kernel Virtual Address Space? After all, that is what we are concerned about in this lab.
PAof the base of the
PML4table for the Kernel/
Systemprocess is mostly at an unrandomized
PA(More on this later).
Kernel Virtual Address Shadow(KVAS)is enabled to mitigate
Meltdown. This involves the separation of User and Kernel-mode page tables for each process. This means that
System Spaceis not mapped in
CPL-3page tables. When a process context switch is made,
nt!_KPROCESS.DirectoryTableBaseis moved into
CPL-3page table base is stored into
nt!_KPROCESS.UserDirectoryTableBase. However, this is not important for our discussion and we won't be concerned with it as such.
KVAScan be forcefully disabled by running the following commands from an elevated command prompt and rebooting:
PML4base address(physical) of Kernel have been recorded for the following platforms:
PML4table for the Kernel/
Systemprocess does not appear to be intentionally randomized between boots in any way unlike the
PML4(and other page tables and its entries).
DTBfor Kernel is required for us or what is the significance of this address.
PAand simulate the
MMU. In order to do that, we need the base address of the
PML4paging structure so that we can traverse page tables and reach the appropriate physical page, thus also giving us a
Ring-0arbitrary virtual memory R/W.
PML4base for Kernel is at unrandomized
PA? So can we just hard-code it in our tools and get it done with? Because surely with our extensive reconnaissance we can just find out our target's platform and use an appropriate address.
PML4base dynamically would reduce the maintenance cost of our tooling while making it more portable and universal.
PML4base using our favourite kernel debugger.
CR3register which holds the
Kernel DTB(when breaking in to an idle system).
lkd, here is the command for doing so:
Minimalprocess - no UM state - only for Kernel-mode threads) and
0denotes the verbosity level(minimum) The
DirBaseassociated with the process object will be the
Kernel DTB. This, of course, will match the value of the
CR3register but we are unable to view register contents in local debugging.
Kernel DTBdynamically on those systems.
CR3register from this structure using
nt!_KSPECIAL_REGISTERS.Cr3which is a field in a sub-structure of
nt!_KPROCESSOR_STATEwhich otherwise would not have been possible from
CPL-3as it is a privileged register.
HalpLowStubbut this presents a recurring problem i.e. How do we get the
HalpLowStubaddress when we only possess a physical read primitive till now?
Advanced Programmable Interrupt Controller(APIC)systems on x64 running on bare metal, the
Low Stubis almost always located at a fixed
Discard Low Memoryis disabled(enabled by default) in which case
Low Stubmay not be at
0x1000but it always has to be located at
Discard Low Memorymay be disabled using:
Low Stub's location from the fixed
WinDbgcommand to get
PA = 0x11090(since testing is not done on real hardware,
PA != 0x1000) which denotes a fixed offset
_PROCESSOR_START_BLOCKstructure and the
/pflag since it is a
PA = 0x1000 - 0x100000range as it is practically guaranteed to be somewhere in that range.
Kernel DTB, let's implement it.
WinDbgfu to verify our results)