diff --git a/pwndbg/aglib/kernel/__init__.py b/pwndbg/aglib/kernel/__init__.py index 54c9505eb..f2ecaf280 100644 --- a/pwndbg/aglib/kernel/__init__.py +++ b/pwndbg/aglib/kernel/__init__.py @@ -116,9 +116,11 @@ def first_kernel_ro_page() -> pwndbg.lib.memory.Page | None: if base is None: return None - for mapping in pwndbg.aglib.kernel.paging.get_memory_map_raw(): + for mapping in pwndbg.aglib.kernel.vmmap.kernel_vmmap_pages(): if mapping.vaddr < base: continue + if not mapping.read or mapping.write or mapping.execute: + continue result = next(pwndbg.search.search(b"Linux version", mappings=[mapping]), None) @@ -438,13 +440,21 @@ class Aarch64Ops(ArchOps): return int(pwndbg.aglib.regs.SCTLR) & BIT(0) != 0 +_arch_paginginfo: ArchPagingInfo = None + + @pwndbg.lib.cache.cache_until("start") -def arch_paginginfo() -> ArchPagingInfo | None: - if pwndbg.aglib.arch.name == "aarch64": - return pwndbg.aglib.kernel.paging.Aarch64PagingInfo() - elif pwndbg.aglib.arch.name == "x86-64": - return pwndbg.aglib.kernel.paging.x86_64PagingInfo() - return None +def arch_paginginfo() -> ArchPagingInfo: + _arch_paginginfo = None + + if _arch_paginginfo is None: + if pwndbg.aglib.arch.name == "aarch64": + _arch_paginginfo = pwndbg.aglib.kernel.paging.Aarch64PagingInfo() + + elif pwndbg.aglib.arch.name == "x86-64": + _arch_paginginfo = pwndbg.aglib.kernel.paging.x86_64PagingInfo() + + return _arch_paginginfo @pwndbg.lib.cache.cache_until("start") diff --git a/pwndbg/aglib/kernel/paging.py b/pwndbg/aglib/kernel/paging.py index 1de8c5eda..22d3f17e6 100644 --- a/pwndbg/aglib/kernel/paging.py +++ b/pwndbg/aglib/kernel/paging.py @@ -11,6 +11,7 @@ import pwndbg.aglib.vmmap_custom import pwndbg.color.message as M import pwndbg.lib.cache import pwndbg.lib.memory +from pwndbg.aglib.kernel.vmmap import kernel_vmmap_pages from pwndbg.lib.regs import BitFlags # don't return None but rather an invalid value for address markers @@ -18,14 +19,9 @@ from pwndbg.lib.regs import BitFlags INVALID_ADDR = 1 << 64 -@pwndbg.lib.cache.cache_until("stop") -def get_memory_map_raw() -> Tuple[pwndbg.lib.memory.Page, ...]: - return pwndbg.aglib.kernel.vmmap.kernel_vmmap(False) - - @pwndbg.lib.cache.cache_until("stop") def first_kernel_page_start(): - for page in get_memory_map_raw(): + for page in kernel_vmmap_pages(): if page.start and pwndbg.aglib.memory.is_kernel(page.start): return page.start return INVALID_ADDR @@ -95,7 +91,7 @@ class ArchPagingInfo: raise NotImplementedError() def kbase_helper(self, address): - for mapping in get_memory_map_raw(): + for mapping in kernel_vmmap_pages(): # should be page aligned -- either from pt-dump or info mem # only search in kernel mappings: @@ -215,12 +211,7 @@ class x86_64PagingInfo(ArchPagingInfo): def physmap(self): result = pwndbg.aglib.kernel.symbol.try_usymbol("page_offset_base") if result is None: - result = INVALID_ADDR - min = 0xFFFF888000000000 if self.paging_level == 4 else 0xFF11000000000000 - for page in get_memory_map_raw(): - if page.start and page.start >= min: - result = page.start - break + result = first_kernel_page_start() return result @property @@ -393,7 +384,7 @@ class Aarch64PagingInfo(ArchPagingInfo): # this is only used for marking the end of module_start self.module_end = -1 res = None - for page in get_memory_map_raw(): + for page in kernel_vmmap_pages(): if page.start >= self.kbase: break if page.execute: @@ -401,7 +392,7 @@ class Aarch64PagingInfo(ArchPagingInfo): if res is None: return INVALID_ADDR prev = None - for page in get_memory_map_raw(): + for page in kernel_vmmap_pages(): if page.start >= res: if prev is not None and page.start > prev + 0x1000: break diff --git a/pwndbg/aglib/kernel/vmmap.py b/pwndbg/aglib/kernel/vmmap.py index 6bd342924..82b89abf8 100644 --- a/pwndbg/aglib/kernel/vmmap.py +++ b/pwndbg/aglib/kernel/vmmap.py @@ -396,7 +396,19 @@ Note that the page-tables method will require the QEMU kernel process to be on t ) -def kernel_vmmap(process_pages=True) -> Tuple[pwndbg.lib.memory.Page, ...]: +@pwndbg.lib.cache.cache_until("stop") +def kernel_vmmap_pages() -> Tuple[pwndbg.lib.memory.Page, ...]: + pages = None + if kernel_vmmap_mode == "page-tables": + pages = kernel_vmmap_via_page_tables() + elif kernel_vmmap_mode == "monitor": + pages = kernel_vmmap_via_monitor_info_mem() + if pages is None: + pages = () + return pages + + +def kernel_vmmap() -> Tuple[pwndbg.lib.memory.Page, ...]: if not pwndbg.aglib.qemu.is_qemu_kernel(): return () @@ -409,23 +421,16 @@ def kernel_vmmap(process_pages=True) -> Tuple[pwndbg.lib.memory.Page, ...]: ): return () - pages = None - if kernel_vmmap_mode == "page-tables": - pages = kernel_vmmap_via_page_tables() - elif kernel_vmmap_mode == "monitor": - pages = kernel_vmmap_via_monitor_info_mem() - if pages is None: - return () - if process_pages: - kv = KernelVmmap(pages) - kv.adjust() - if kernel_vmmap_mode == "monitor" and pwndbg.aglib.arch.name == "x86-64": - # TODO: check version here when QEMU displays the x bit for x64 - for page in pages: - if page.objfile == kv.pi.ESPSTACK: - continue - entry = pwndbg.aglib.kernel.pagewalk(page.start)[0].entry - if entry and entry >> 63 == 0: - page.flags |= 1 + pages = kernel_vmmap_pages() + kv = KernelVmmap(pages) + kv.adjust() + if kernel_vmmap_mode == "monitor" and pwndbg.aglib.arch.name == "x86-64": + # TODO: check version here when QEMU displays the x bit for x64 + for page in pages: + if page.objfile == kv.pi.ESPSTACK: + continue + entry = pwndbg.aglib.kernel.pagewalk(page.start)[0].entry + if entry and entry >> 63 == 0: + page.flags |= 1 return tuple(pages)