|
|
|
|
@ -1,5 +1,6 @@
|
|
|
|
|
from __future__ import annotations
|
|
|
|
|
|
|
|
|
|
import math
|
|
|
|
|
from typing import List
|
|
|
|
|
from typing import Tuple
|
|
|
|
|
|
|
|
|
|
@ -8,38 +9,83 @@ import pwndbg.aglib.vmmap_custom
|
|
|
|
|
import pwndbg.color.message as M
|
|
|
|
|
import pwndbg.lib.cache
|
|
|
|
|
import pwndbg.lib.memory
|
|
|
|
|
from pwndbg import config
|
|
|
|
|
|
|
|
|
|
ENTRYMASK = ~((1 << 12) - 1) & ((1 << 51) - 1)
|
|
|
|
|
# don't return None but rather an invalid value for address markers
|
|
|
|
|
# this way arithmetic ops do not panic if physmap is not found
|
|
|
|
|
INVALID_ADDR = 1 << 64
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@pwndbg.lib.cache.cache_until("start", "stop")
|
|
|
|
|
@pwndbg.lib.cache.cache_until("stop")
|
|
|
|
|
def get_memory_map_raw() -> Tuple[pwndbg.lib.memory.Page, ...]:
|
|
|
|
|
return pwndbg.aglib.kernel.vmmap.kernel_vmmap(False)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def find_kbase(pages) -> int | None:
|
|
|
|
|
arch_name = pwndbg.aglib.arch.name
|
|
|
|
|
def guess_physmap():
|
|
|
|
|
# this is mostly true
|
|
|
|
|
# https://www.kernel.org/doc/Documentation/x86/x86_64/mm.txt
|
|
|
|
|
for page in get_memory_map_raw():
|
|
|
|
|
if page.start and pwndbg.aglib.memory.is_kernel(page.start):
|
|
|
|
|
return page.start
|
|
|
|
|
return INVALID_ADDR
|
|
|
|
|
|
|
|
|
|
address = 0
|
|
|
|
|
|
|
|
|
|
if arch_name == "x86-64":
|
|
|
|
|
address = pwndbg.aglib.kernel.get_idt_entries()[0].offset
|
|
|
|
|
elif arch_name == "aarch64":
|
|
|
|
|
address = pwndbg.aglib.regs.vbar
|
|
|
|
|
else:
|
|
|
|
|
return None
|
|
|
|
|
class ArchPagingInfo:
|
|
|
|
|
USERLAND = "userland"
|
|
|
|
|
KERNELLAND = "kernel [.text]"
|
|
|
|
|
KERNELRO = "kernel [.rodata]"
|
|
|
|
|
KERNELBSS = "kernel [.bss]"
|
|
|
|
|
KERNELDRIVER = "kernel [.driver .bpf]"
|
|
|
|
|
ESPSTACK = "espfix"
|
|
|
|
|
PHYSMAP = "physmap"
|
|
|
|
|
VMALLOC = "vmalloc"
|
|
|
|
|
VMEMMAP = "vmemmap"
|
|
|
|
|
|
|
|
|
|
physmap: int
|
|
|
|
|
vmalloc: int
|
|
|
|
|
vmemmap: int
|
|
|
|
|
kbase: int
|
|
|
|
|
addr_marker_sz: int
|
|
|
|
|
|
|
|
|
|
@property
|
|
|
|
|
@pwndbg.lib.cache.cache_until("start")
|
|
|
|
|
def STRUCT_PAGE_SIZE(self):
|
|
|
|
|
a = pwndbg.aglib.typeinfo.load("struct page")
|
|
|
|
|
if a is None:
|
|
|
|
|
# this has been the case for all v5 and v6 releases
|
|
|
|
|
return 0x40
|
|
|
|
|
return a.sizeof
|
|
|
|
|
|
|
|
|
|
mappings = pages
|
|
|
|
|
for mapping in mappings:
|
|
|
|
|
@property
|
|
|
|
|
@pwndbg.lib.cache.cache_until("start")
|
|
|
|
|
def STRUCT_PAGE_SHIFT(self):
|
|
|
|
|
return int(math.log2(self.STRUCT_PAGE_SIZE))
|
|
|
|
|
|
|
|
|
|
@property
|
|
|
|
|
def page_shift(self) -> int:
|
|
|
|
|
raise NotImplementedError()
|
|
|
|
|
|
|
|
|
|
@property
|
|
|
|
|
def paging_level(self) -> int:
|
|
|
|
|
raise NotImplementedError()
|
|
|
|
|
|
|
|
|
|
def adjust(self, name: str) -> str:
|
|
|
|
|
raise NotImplementedError()
|
|
|
|
|
|
|
|
|
|
def markers(self) -> Tuple[Tuple[str, int], ...]:
|
|
|
|
|
raise NotImplementedError()
|
|
|
|
|
|
|
|
|
|
def handle_kernel_pages(self, pages):
|
|
|
|
|
# this is arch dependent
|
|
|
|
|
raise NotImplementedError()
|
|
|
|
|
|
|
|
|
|
def kbase_helper(self, address):
|
|
|
|
|
for mapping in get_memory_map_raw():
|
|
|
|
|
# should be page aligned -- either from pt-dump or info mem
|
|
|
|
|
|
|
|
|
|
# only search in kernel mappings:
|
|
|
|
|
# https://www.kernel.org/doc/html/v5.3/arm64/memory.html
|
|
|
|
|
if mapping.vaddr & (0xFFFF << 48) == 0:
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
if not mapping.execute:
|
|
|
|
|
if not pwndbg.aglib.memory.is_kernel(mapping.vaddr):
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
if address in mapping:
|
|
|
|
|
@ -48,57 +94,330 @@ def find_kbase(pages) -> int | None:
|
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@pwndbg.aglib.proc.OnlyWithArch(["x86-64"])
|
|
|
|
|
def uses_5lvl_paging() -> bool:
|
|
|
|
|
class x86_64PagingInfo(ArchPagingInfo):
|
|
|
|
|
@property
|
|
|
|
|
@pwndbg.lib.cache.cache_until("stop")
|
|
|
|
|
def physmap(self):
|
|
|
|
|
pob = pwndbg.aglib.symbol.lookup_symbol_addr("page_offset_base")
|
|
|
|
|
result = None
|
|
|
|
|
if pob is not None:
|
|
|
|
|
if pwndbg.aglib.memory.peek(pob):
|
|
|
|
|
result = pwndbg.aglib.memory.u64(pob)
|
|
|
|
|
if result is None:
|
|
|
|
|
return guess_physmap()
|
|
|
|
|
return result
|
|
|
|
|
|
|
|
|
|
@property
|
|
|
|
|
@pwndbg.lib.cache.cache_until("stop")
|
|
|
|
|
def kbase(self):
|
|
|
|
|
return self.kbase_helper(pwndbg.aglib.kernel.get_idt_entries()[0].offset)
|
|
|
|
|
|
|
|
|
|
@property
|
|
|
|
|
def page_shift(self) -> int:
|
|
|
|
|
return 12
|
|
|
|
|
|
|
|
|
|
@property
|
|
|
|
|
@pwndbg.lib.cache.cache_until("stop")
|
|
|
|
|
def vmalloc(self):
|
|
|
|
|
addr = pwndbg.aglib.symbol.lookup_symbol_addr("vmalloc_base")
|
|
|
|
|
if addr:
|
|
|
|
|
return pwndbg.aglib.memory.u64(addr)
|
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
|
@property
|
|
|
|
|
@pwndbg.lib.cache.cache_until("stop")
|
|
|
|
|
def vmemmap(self):
|
|
|
|
|
addr = pwndbg.aglib.symbol.lookup_symbol_addr("vmemmap_base")
|
|
|
|
|
if addr:
|
|
|
|
|
return pwndbg.aglib.memory.u64(addr)
|
|
|
|
|
# resort to default
|
|
|
|
|
if self.paging_level == 5:
|
|
|
|
|
return 0xFFD4000000000000
|
|
|
|
|
return 0xFFFFEA0000000000
|
|
|
|
|
|
|
|
|
|
@property
|
|
|
|
|
def paging_level(self) -> int:
|
|
|
|
|
if pwndbg.aglib.kernel.has_debug_syms():
|
|
|
|
|
ops: pwndbg.aglib.kernel.x86_64Ops = pwndbg.aglib.kernel.arch_ops()
|
|
|
|
|
return ops.uses_5lvl_paging()
|
|
|
|
|
# https://elixir.bootlin.com/linux/v6.2/source/arch/x86/include/asm/cpufeatures.h#L381
|
|
|
|
|
X86_FEATURE_LA57 = 16 * 32 + 16
|
|
|
|
|
feature = X86_FEATURE_LA57
|
|
|
|
|
# Separate to avoid using kconfig if possible
|
|
|
|
|
boot_cpu_data = pwndbg.aglib.symbol.lookup_symbol("boot_cpu_data")
|
|
|
|
|
assert boot_cpu_data is not None, "Symbol boot_cpu_data not exists"
|
|
|
|
|
boot_cpu_data = boot_cpu_data.dereference()
|
|
|
|
|
|
|
|
|
|
capabilities = boot_cpu_data["x86_capability"]
|
|
|
|
|
cpu_feature_capability = (int(capabilities[feature // 32]) >> (feature % 32)) & 1 == 1
|
|
|
|
|
if not cpu_feature_capability or "no5lvl" in pwndbg.aglib.kernel.kcmdline():
|
|
|
|
|
return 4
|
|
|
|
|
return 5
|
|
|
|
|
# CONFIG_X86_5LEVEL is only a hint -- whether 5lvl paging is used depends on the hardware
|
|
|
|
|
# see also: https://www.kernel.org/doc/html/next/x86/x86_64/mm.html
|
|
|
|
|
pages = get_memory_map_raw()
|
|
|
|
|
for page in pages:
|
|
|
|
|
if page.start & (1 << 63) > 0:
|
|
|
|
|
return page.start < (0xFFF << (4 * 13))
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
if pwndbg.aglib.memory.is_kernel(page.start):
|
|
|
|
|
if page.start < (0xFFF << (4 * 13)):
|
|
|
|
|
return 5
|
|
|
|
|
return 4
|
|
|
|
|
|
|
|
|
|
guess_physmap = config.add_param(
|
|
|
|
|
"guess-physmap",
|
|
|
|
|
False,
|
|
|
|
|
"Should guess physmap base address when debug symbols are not present",
|
|
|
|
|
)
|
|
|
|
|
@pwndbg.lib.cache.cache_until("stop")
|
|
|
|
|
def markers(self) -> Tuple[Tuple[str, int], ...]:
|
|
|
|
|
return (
|
|
|
|
|
(self.USERLAND, 0),
|
|
|
|
|
(None, 0x8000000000000000),
|
|
|
|
|
("ldt remap", 0xFFFF880000000000 if self.paging_level == 4 else 0xFF10000000000000),
|
|
|
|
|
(self.PHYSMAP, self.physmap),
|
|
|
|
|
(self.VMALLOC, self.vmalloc),
|
|
|
|
|
(self.VMEMMAP, self.vmemmap),
|
|
|
|
|
# TODO: find better ways to handle the following constants
|
|
|
|
|
# I cound not find kernel symbols that reference their values
|
|
|
|
|
# the actual region base may differ but the region always falls within the below range
|
|
|
|
|
# even if KASLR is enabled
|
|
|
|
|
("cpu entry", 0xFFFFFE0000000000),
|
|
|
|
|
(self.ESPSTACK, 0xFFFFFF0000000000),
|
|
|
|
|
("EFI", 0xFFFFFFEF00000000),
|
|
|
|
|
(self.KERNELLAND, self.kbase),
|
|
|
|
|
("fixmap", 0xFFFFFFFFFF000000),
|
|
|
|
|
("legacy abi", 0xFFFFFFFFFF600000),
|
|
|
|
|
(None, 0xFFFFFFFFFFFFFFFF),
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
def adjust(self, name):
|
|
|
|
|
name = name.lower()
|
|
|
|
|
if "low kernel" in name:
|
|
|
|
|
return self.PHYSMAP
|
|
|
|
|
if "high kernel" in name:
|
|
|
|
|
return self.KERNELLAND
|
|
|
|
|
if self.VMALLOC in name:
|
|
|
|
|
return self.VMALLOC
|
|
|
|
|
if self.VMEMMAP in name:
|
|
|
|
|
return self.VMEMMAP
|
|
|
|
|
if " area" in name:
|
|
|
|
|
return name[:-5]
|
|
|
|
|
return name
|
|
|
|
|
|
|
|
|
|
def physmap_base() -> int:
|
|
|
|
|
if pwndbg.aglib.kernel.has_debug_syms() and pwndbg.aglib.arch.name == "x86-64":
|
|
|
|
|
result = pwndbg.aglib.symbol.lookup_symbol_addr("page_offset_base")
|
|
|
|
|
if pwndbg.aglib.memory.peek(result):
|
|
|
|
|
result = pwndbg.aglib.memory.u64(result)
|
|
|
|
|
def handle_kernel_pages(self, pages):
|
|
|
|
|
kernel_idx = None
|
|
|
|
|
for i, page in enumerate(pages):
|
|
|
|
|
if kernel_idx is None and self.kbase in page:
|
|
|
|
|
kernel_idx = i
|
|
|
|
|
kbase = self.kbase
|
|
|
|
|
if kernel_idx is None:
|
|
|
|
|
return
|
|
|
|
|
has_loadable_driver = False
|
|
|
|
|
for i in range(kernel_idx, len(pages)):
|
|
|
|
|
page = pages[i]
|
|
|
|
|
if page.objfile != self.KERNELLAND:
|
|
|
|
|
break
|
|
|
|
|
if not page.execute:
|
|
|
|
|
if page.write:
|
|
|
|
|
page.objfile = self.KERNELBSS
|
|
|
|
|
else:
|
|
|
|
|
page.objfile = self.KERNELRO
|
|
|
|
|
if has_loadable_driver:
|
|
|
|
|
page.objfile = self.KERNELDRIVER
|
|
|
|
|
if page.execute and page.start != kbase:
|
|
|
|
|
page.objfile = self.KERNELDRIVER
|
|
|
|
|
has_loadable_driver = True
|
|
|
|
|
if pwndbg.aglib.regs[pwndbg.aglib.regs.stack] in page:
|
|
|
|
|
page.objfile = "kernel [stack]"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class Aarch64PagingInfo(ArchPagingInfo):
|
|
|
|
|
def __init__(self):
|
|
|
|
|
self.tcr_el1 = pwndbg.lib.regs.aarch64_tcr_flags
|
|
|
|
|
self.tcr_el1.value = pwndbg.aglib.regs.TCR_EL1
|
|
|
|
|
# TODO: this is probably not entirely correct
|
|
|
|
|
# https://elixir.bootlin.com/linux/v6.16-rc2/source/arch/arm64/include/asm/memory.h#L56
|
|
|
|
|
self.va_bits = 64 - self.tcr_el1["T1SZ"] # this is prob only `vabits_actual`
|
|
|
|
|
self.va_bits_min = 48 if self.va_bits > 48 else self.va_bits
|
|
|
|
|
# https://elixir.bootlin.com/linux/v6.13.12/source/arch/arm64/include/asm/memory.h#L47
|
|
|
|
|
module_start_wo_kaslr = (-1 << (self.va_bits_min - 1)) + 2**64
|
|
|
|
|
self.vmalloc = module_start_wo_kaslr + 0x80000000
|
|
|
|
|
shift = self.page_shift - self.STRUCT_PAGE_SHIFT
|
|
|
|
|
self.VMEMMAP_SIZE = (module_start_wo_kaslr - ((-1 << self.va_bits) + 2**64)) >> shift
|
|
|
|
|
|
|
|
|
|
@property
|
|
|
|
|
@pwndbg.lib.cache.cache_until("stop")
|
|
|
|
|
def physmap(self):
|
|
|
|
|
# addr = pwndbg.aglib.symbol.lookup_symbol_addr("memstart_addr")
|
|
|
|
|
# if addr is None:
|
|
|
|
|
# return guess_physmap()
|
|
|
|
|
# return pwndbg.aglib.memory.u(addr)
|
|
|
|
|
return guess_physmap()
|
|
|
|
|
|
|
|
|
|
@property
|
|
|
|
|
@pwndbg.lib.cache.cache_until("stop")
|
|
|
|
|
def kbase(self):
|
|
|
|
|
return self.kbase_helper(pwndbg.aglib.regs.vbar)
|
|
|
|
|
|
|
|
|
|
@property
|
|
|
|
|
@pwndbg.lib.cache.cache_until("stop")
|
|
|
|
|
def kversion(self):
|
|
|
|
|
try:
|
|
|
|
|
return pwndbg.aglib.kernel.krelease()
|
|
|
|
|
except Exception:
|
|
|
|
|
return None
|
|
|
|
|
if result is not None:
|
|
|
|
|
return result
|
|
|
|
|
if guess_physmap or pwndbg.aglib.arch.name == "aarch64":
|
|
|
|
|
# this is mostly true
|
|
|
|
|
# https://www.kernel.org/doc/Documentation/x86/x86_64/mm.txt
|
|
|
|
|
|
|
|
|
|
@property
|
|
|
|
|
@pwndbg.lib.cache.cache_until("stop")
|
|
|
|
|
def physmap_end(self):
|
|
|
|
|
res = None
|
|
|
|
|
for page in get_memory_map_raw():
|
|
|
|
|
if page.start & (1 << 63) > 0:
|
|
|
|
|
return page.start
|
|
|
|
|
print(M.warn("physmap base cannot be determined, resort to default"))
|
|
|
|
|
if uses_5lvl_paging():
|
|
|
|
|
return 0xFF11000000000000
|
|
|
|
|
return 0xFFFF888000000000
|
|
|
|
|
if page.end >= self.vmalloc:
|
|
|
|
|
break
|
|
|
|
|
res = page.end
|
|
|
|
|
if res is None:
|
|
|
|
|
return INVALID_ADDR
|
|
|
|
|
return res
|
|
|
|
|
|
|
|
|
|
@property
|
|
|
|
|
@pwndbg.lib.cache.cache_until("stop")
|
|
|
|
|
def module_start(self):
|
|
|
|
|
# this is only used for marking the end of module_start
|
|
|
|
|
self.module_end = -1
|
|
|
|
|
res = None
|
|
|
|
|
for page in get_memory_map_raw():
|
|
|
|
|
if page.start >= self.kbase:
|
|
|
|
|
break
|
|
|
|
|
if page.execute:
|
|
|
|
|
res = page.start
|
|
|
|
|
if res is None:
|
|
|
|
|
return INVALID_ADDR
|
|
|
|
|
prev = None
|
|
|
|
|
for page in get_memory_map_raw():
|
|
|
|
|
if page.start >= res:
|
|
|
|
|
if prev is not None and page.start > prev + 0x1000:
|
|
|
|
|
break
|
|
|
|
|
prev = self.module_end = page.end
|
|
|
|
|
return res
|
|
|
|
|
|
|
|
|
|
@pwndbg.lib.cache.cache_until("start")
|
|
|
|
|
def kbase():
|
|
|
|
|
return find_kbase(get_memory_map_raw())
|
|
|
|
|
@property
|
|
|
|
|
@pwndbg.lib.cache.cache_until("stop")
|
|
|
|
|
def vmemmap(self):
|
|
|
|
|
if self.kversion is None:
|
|
|
|
|
return None
|
|
|
|
|
if self.kversion >= (6, 9):
|
|
|
|
|
# https://elixir.bootlin.com/linux/v6.16-rc2/source/arch/arm64/include/asm/memory.h#L33
|
|
|
|
|
return (-0x40000000 % INVALID_ADDR) - self.VMEMMAP_SIZE
|
|
|
|
|
if self.kversion >= (5, 11):
|
|
|
|
|
# Linux 5.11 changed the calculation for VMEMMAP_START
|
|
|
|
|
# https://elixir.bootlin.com/linux/v5.11/source/arch/arm64/include/asm/memory.h#L53
|
|
|
|
|
VMEMMAP_SHIFT = self.page_shift - self.STRUCT_PAGE_SHIFT
|
|
|
|
|
return -(1 << (self.va_bits - VMEMMAP_SHIFT)) % INVALID_ADDR
|
|
|
|
|
return (-self.VMEMMAP_SIZE - 2 * 1024 * 1024) + 2**64
|
|
|
|
|
|
|
|
|
|
@property
|
|
|
|
|
@pwndbg.lib.cache.cache_until("stop")
|
|
|
|
|
def pci(self):
|
|
|
|
|
if self.kversion is None:
|
|
|
|
|
return None
|
|
|
|
|
self.pci_end = INVALID_ADDR
|
|
|
|
|
if self.kversion >= (6, 9):
|
|
|
|
|
pci = self.vmemmap + self.VMEMMAP_SIZE + 0x00800000
|
|
|
|
|
self.pci_end = pci + 0x01000000
|
|
|
|
|
return pci
|
|
|
|
|
if self.kversion >= (5, 11):
|
|
|
|
|
self.pci_end = self.vmemmap - 0x00800000
|
|
|
|
|
return self.pci_end - 0x01000000
|
|
|
|
|
self.pci_end = self.vmemmap - 0x00200000
|
|
|
|
|
return self.pci_end - 0x01000000
|
|
|
|
|
|
|
|
|
|
@property
|
|
|
|
|
@pwndbg.lib.cache.cache_until("stop")
|
|
|
|
|
def ksize(self):
|
|
|
|
|
start = pwndbg.aglib.symbol.lookup_symbol_addr("_text")
|
|
|
|
|
end = pwndbg.aglib.symbol.lookup_symbol_addr("_end")
|
|
|
|
|
if start is not None and end is not None:
|
|
|
|
|
return end - start
|
|
|
|
|
# fallback
|
|
|
|
|
return 100 << 21 # 100M
|
|
|
|
|
|
|
|
|
|
@property
|
|
|
|
|
@pwndbg.lib.cache.cache_until("stop")
|
|
|
|
|
def page_shift(self) -> int:
|
|
|
|
|
# TODO: this might be arm version dependent
|
|
|
|
|
if self.tcr_el1["TG1"] == 1:
|
|
|
|
|
return 14
|
|
|
|
|
elif self.tcr_el1["TG1"] == 0:
|
|
|
|
|
return 12
|
|
|
|
|
else:
|
|
|
|
|
return 16
|
|
|
|
|
|
|
|
|
|
@pwndbg.lib.cache.cache_until("stop")
|
|
|
|
|
def markers(self) -> Tuple[Tuple[str, int], ...]:
|
|
|
|
|
address_markers = pwndbg.aglib.symbol.lookup_symbol_addr("address_markers")
|
|
|
|
|
if address_markers is not None:
|
|
|
|
|
sections = [(self.USERLAND, 0)]
|
|
|
|
|
value = 0
|
|
|
|
|
name = None
|
|
|
|
|
for i in range(20):
|
|
|
|
|
value = pwndbg.aglib.memory.u64(address_markers + i * 0x10)
|
|
|
|
|
name_ptr = pwndbg.aglib.memory.u64(address_markers + i * 0x10 + 8)
|
|
|
|
|
name = None
|
|
|
|
|
if name_ptr > 0:
|
|
|
|
|
name = pwndbg.aglib.memory.string(name_ptr).decode()
|
|
|
|
|
name = self.adjust(name)
|
|
|
|
|
if value > 0:
|
|
|
|
|
sections.append((name, value))
|
|
|
|
|
if value == 0xFFFFFFFFFFFFFFFF:
|
|
|
|
|
break
|
|
|
|
|
return tuple(sections)
|
|
|
|
|
if self.kversion is None:
|
|
|
|
|
return ()
|
|
|
|
|
return (
|
|
|
|
|
(self.USERLAND, 0),
|
|
|
|
|
(None, 0x8000000000000000),
|
|
|
|
|
(self.PHYSMAP, self.physmap),
|
|
|
|
|
(None, self.physmap_end),
|
|
|
|
|
(self.VMALLOC, self.vmalloc),
|
|
|
|
|
(self.VMEMMAP, self.vmemmap),
|
|
|
|
|
(None, self.vmemmap + self.VMEMMAP_SIZE),
|
|
|
|
|
("pci", self.pci),
|
|
|
|
|
(None, self.pci_end),
|
|
|
|
|
# TODO: prob not entirely correct but the computation is too complicated
|
|
|
|
|
("fixmap", self.pci_end),
|
|
|
|
|
(None, 0xFFFFFFFFFFFFFFFF),
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
def adjust(self, name):
|
|
|
|
|
name = name.lower()
|
|
|
|
|
if "end" in name:
|
|
|
|
|
return None
|
|
|
|
|
if "linear" in name:
|
|
|
|
|
return self.PHYSMAP
|
|
|
|
|
if "modules" in name:
|
|
|
|
|
return self.KERNELDRIVER
|
|
|
|
|
if self.VMEMMAP in name:
|
|
|
|
|
return self.VMEMMAP
|
|
|
|
|
if self.VMALLOC in name:
|
|
|
|
|
return self.VMALLOC
|
|
|
|
|
return " ".join(name.strip().split()[:-1])
|
|
|
|
|
|
|
|
|
|
def handle_kernel_pages(self, pages):
|
|
|
|
|
for i in range(len(pages)):
|
|
|
|
|
page = pages[i]
|
|
|
|
|
if page.start < self.module_start or page.start > self.kbase + self.ksize:
|
|
|
|
|
continue
|
|
|
|
|
if self.module_start <= page.start < self.module_end:
|
|
|
|
|
page.objfile = self.KERNELDRIVER
|
|
|
|
|
continue
|
|
|
|
|
if page.start < self.kbase:
|
|
|
|
|
continue
|
|
|
|
|
page.objfile = self.KERNELLAND
|
|
|
|
|
if not page.execute:
|
|
|
|
|
if page.write:
|
|
|
|
|
page.objfile = self.KERNELBSS
|
|
|
|
|
else:
|
|
|
|
|
page.objfile = self.KERNELRO
|
|
|
|
|
if pwndbg.aglib.regs[pwndbg.aglib.regs.stack] in page:
|
|
|
|
|
page.objfile = "kernel [stack]"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@pwndbg.aglib.proc.OnlyWithArch(["x86-64"])
|
|
|
|
|
def pagewalk(target, entry=None) -> List[Tuple[int | None, int | None]]:
|
|
|
|
|
level = 4
|
|
|
|
|
if uses_5lvl_paging():
|
|
|
|
|
level = 5
|
|
|
|
|
base = physmap_base()
|
|
|
|
|
level = pwndbg.aglib.kernel.arch_paginginfo().paging_level
|
|
|
|
|
base = pwndbg.aglib.kernel.arch_paginginfo().physmap
|
|
|
|
|
if entry is None:
|
|
|
|
|
entry = pwndbg.aglib.regs["cr3"]
|
|
|
|
|
else:
|
|
|
|
|
@ -124,5 +443,5 @@ def pagewalk(target, entry=None) -> List[Tuple[int | None, int | None]]:
|
|
|
|
|
if entry == 0:
|
|
|
|
|
return result
|
|
|
|
|
result[i] = (entry, vaddr)
|
|
|
|
|
result[0] = (None, (entry & ENTRYMASK) + base + offset)
|
|
|
|
|
result[0] = (entry, (entry & ENTRYMASK) + base + offset)
|
|
|
|
|
return result
|
|
|
|
|
|