PA
of the Page-Map-Level-4(PML4)
table base for Kernel/System Virtual Address Space
.Directory Table Base(DTB)
(or DirBase
in WinDBG
) is the PA
of the base of the top-level paging structure(PML4
in Long Mode\x64
Paging) whose value is also contained by the CR3
register.PML4
table is also allocated. The PA
of the PML4
table is stored in nt!_KPROCESS
(Kernel process object) structure's DirectoryTableBase
member. When a process context switch is made by the processor, this PA
is moved into the CR3
register which the Memory Management Unit(MMU)
can then use along with the VA
offsets into various paging structures to walk the page tables and translate virtual addresses to appropriate physical addresses.PA
of its root page table base which is moved into CR3
when the process is selected.Kernel DTB
that maps the Kernel Virtual Address Space
? After all, that is what we are concerned about in this lab.PA
of the base of the PML4
table for the Kernel/System
process is mostly at an unrandomized PA
(More on this later).DTB
can also be referred to as Self-referencing PML4E
or in other words, an entry in the PML4
table which points to its own page table base PA
.System Space
is actually a shared one and mapped into every UM process(unless KVAS
is enabled) and therefore is process context independent albeit not accessible unless in Supervisor/Kernel
mode which is set via U/S
bit in Page Table Entry(PTE)
.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 Space
is not mapped in CPL-3
page tables. When a process context switch is made, nt!_KPROCESS.DirectoryTableBase
is moved into nt!_KPRCB.KernelDirectoryTableBase
and the CPL-3
page 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.KVAS
is the software mitigation for Meltdown(CVE-2017-5754)
introduced in Windows 10 RS4/1803
for some old(er) CPUs that are vulnerable. With newer processors (or processors that were not affected by it), KVAS
will not be enabled at boot time.KVAS
is enabled, there are some extra flags in the DirBase
. Ex: 0x1aa000
would become 0x1aa002
when KVAS
is enabled. However, in this lab, we won't be too concerned with it since those are used for determining User/Kernel-mode page tables and are masked off before moving into CR3
.KVAS
can be forcefully disabled by running the following commands from an elevated command prompt and rebooting:PML4
base address(physical) of Kernel have been recorded for the following platforms:0x1ba000
0x1ad000
0x1aa000
0x6d4000
0x1aa000
0x1ad000
PA
of the PML4
table for the Kernel/System
process does not appear to be intentionally randomized between boots in any way unlike the VA
of PML4
(and other page tables and its entries).DTB
for Kernel is required for us or what is the significance of this address.VA
to PA
and simulate the MMU
. In order to do that, we need the base address of the PML4
paging structure so that we can traverse page tables and reach the appropriate physical page, thus also giving us a Ring-0
arbitrary virtual memory R/W.PML4
base 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.PML4
base dynamically would reduce the maintenance cost of our tooling while making it more portable and universal.Kernel DTB
.PML4
base using our favourite kernel debugger.CR3
register which holds the Kernel DTB
(when breaking in to an idle system).lkd
, here is the command for doing so:4
denotes the PID
for the System
process(Minimal
process - no UM state - only for Kernel-mode threads) and 0
denotes the verbosity level(minimum) The DirBase
associated with the process object will be the Kernel DTB
. This, of course, will match the value of the CR3
register but we are unable to view register contents in local debugging.Kernel DTB
dynamically on those systems.LowStub
.Low Stub
or HalpLowStub
is actually the undocumented PROCESSOR_START_BLOCK
structure.nt!_KPROCESSOR_STATE
.CR3
register from this structure using nt!_KSPECIAL_REGISTERS.Cr3
which is a field in a sub-structure of nt!_KPROCESSOR_STATE
which otherwise would not have been possible from CPL-3
as it is a privileged register.Kernel DTB
from HalpLowStub
but this presents a recurring problem i.e. How do we get the HalpLowStub
address when we only possess a physical read primitive till now?Advanced Programmable Interrupt Controller(APIC)
systems on x64 running on bare metal, the Low Stub
is almost always located at a fixed PA
of 0x1000
unless Discard Low Memory
is disabled(enabled by default) in which case Low Stub
may not be at 0x1000
but it always has to be located at PA
less than 0x100000(1 MB)
.Discard Low Memory
may be disabled using:Low Stub
's location from the fixed 0x1000
.WinDbg
command to get Kernel DTB
:PA = 0x11090
(since testing is not done on real hardware, PA != 0x1000
) which denotes a fixed offset 0x90
of _KPROCESSOR_STATE
from _PROCESSOR_START_BLOCK
structure and the /p
flag since it is a PA
.HalpLowStub
from the PA = 0x1000 - 0x100000
range as it is practically guaranteed to be somewhere in that range.HalpLowStub
. HAL Heap VA
(now randomized) can be leaked from HalpLowStub
's approximately fixed physical address which proves a great avenue for KASLR
bypass for REMOTE
exploits.Kernel DTB
, let's implement it.Kernel DTB
:WinDbg
fu to verify our results)VirtualBox(BIOS)
and our results coincide with the aforementioned values in the tables.