fixes for determining x86_64 address markers and aarch64 page size (#3322)

* fixes for determining x86_64 address markers and aarch64 page size

* code improvements

* removed redundant check
pull/3317/head^2
jxuanli 2 months ago committed by GitHub
parent 581a7df9e4
commit 13fdf21253
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -1,6 +1,7 @@
from __future__ import annotations from __future__ import annotations
import math import math
import re
from typing import Dict from typing import Dict
from typing import List from typing import List
from typing import Tuple from typing import Tuple
@ -158,7 +159,6 @@ class ArchPagingInfo:
class x86_64PagingInfo(ArchPagingInfo): class x86_64PagingInfo(ArchPagingInfo):
# constants are taken from https://www.kernel.org/doc/Documentation/x86/x86_64/mm.txt
def __init__(self): def __init__(self):
self.va_bits = 48 if self.paging_level == 4 else 51 self.va_bits = 48 if self.paging_level == 4 else 51
# https://blog.zolutal.io/understanding-paging/ # https://blog.zolutal.io/understanding-paging/
@ -254,6 +254,7 @@ class x86_64PagingInfo(ArchPagingInfo):
@pwndbg.lib.cache.cache_until("stop") @pwndbg.lib.cache.cache_until("stop")
def markers(self) -> Tuple[Tuple[str, int], ...]: def markers(self) -> Tuple[Tuple[str, int], ...]:
# https://www.kernel.org/doc/Documentation/x86/x86_64/mm.txt
return ( return (
(self.USERLAND, 0), (self.USERLAND, 0),
(None, 0x8000000000000000), (None, 0x8000000000000000),
@ -261,10 +262,6 @@ class x86_64PagingInfo(ArchPagingInfo):
(self.PHYSMAP, self.physmap), (self.PHYSMAP, self.physmap),
(self.VMALLOC, self.vmalloc), (self.VMALLOC, self.vmalloc),
(self.VMEMMAP, self.vmemmap), (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), ("cpu entry", 0xFFFFFE0000000000),
(self.ESPSTACK, 0xFFFFFF0000000000), (self.ESPSTACK, 0xFFFFFF0000000000),
("EFI", 0xFFFFFFEF00000000), ("EFI", 0xFFFFFFEF00000000),
@ -301,16 +298,18 @@ class x86_64PagingInfo(ArchPagingInfo):
page = pages[i] page = pages[i]
if page.objfile != self.KERNELLAND: if page.objfile != self.KERNELLAND:
break break
if page.start == kbase:
continue
# the first executable page after kernel text is the start of bpf/loadable driver
if has_loadable_driver or page.execute:
page.objfile = self.KERNELDRIVER
has_loadable_driver = True
continue
if not page.execute: if not page.execute:
if page.write: if page.write:
page.objfile = self.KERNELBSS page.objfile = self.KERNELBSS
else: else:
page.objfile = self.KERNELRO 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: if pwndbg.aglib.regs[pwndbg.aglib.regs.stack] in page:
page.objfile = "kernel [stack]" page.objfile = "kernel [stack]"
@ -478,27 +477,40 @@ class Aarch64PagingInfo(ArchPagingInfo):
# fallback # fallback
return 100 << 21 # 100M return 100 << 21 # 100M
@property
@pwndbg.lib.cache.cache_until("objfile")
def page_shift_heuristic(self) -> int:
sym = pwndbg.aglib.symbol.lookup_symbol_addr("copy_page_to_iter")
if sym is not None:
pattern = re.compile(r"mov.*(0x1000|0x10000|0x4000)")
for inst in pwndbg.aglib.nearpc.nearpc(int(sym), lines=50):
if (result := pattern.search(inst)) is not None:
return int(math.log2(int(result.group(1), 16)))
return 12 # default
@property @property
@pwndbg.lib.cache.cache_until("stop") @pwndbg.lib.cache.cache_until("stop")
def page_shift(self) -> int: def page_shift(self) -> int:
if self.tcr_el1["TG1"] == 0b01: match self.tcr_el1["TG1"]:
return 14 case 0b01:
elif self.tcr_el1["TG1"] == 0b10: return 14
return 12 case 0b10:
elif self.tcr_el1["TG1"] == 0b11: return 12
return 16 case 0b11:
raise NotImplementedError() return 16
return self.page_shift_heuristic
@property @property
@pwndbg.lib.cache.cache_until("stop") @pwndbg.lib.cache.cache_until("stop")
def page_shift_user(self) -> int: def page_shift_user(self) -> int:
if self.tcr_el1["TG0"] == 0b00: match self.tcr_el1["TG0"]:
return 12 case 0b00:
elif self.tcr_el1["TG0"] == 0b01: return 12
return 16 case 0b01:
elif self.tcr_el1["TG0"] == 0b10: return 16
return 14 case 0b10:
raise NotImplementedError() return 14
return self.page_shift_heuristic
@property @property
@pwndbg.lib.cache.cache_until("forever") @pwndbg.lib.cache.cache_until("forever")

Loading…
Cancel
Save