From c1e425217bf8ea0e4b62a56ddaff5db29d87b4f0 Mon Sep 17 00:00:00 2001 From: Mike Auty Date: Thu, 5 Jan 2023 10:20:19 +0000 Subject: [PATCH] Initial canonical helper addition The intel 64-bit 4-page paging mechanism allows for 48-bit virtual addresses. They introduced a convention that the higher bits must be set a particular way to avoid operating system developers abusing those bits and creating problems that would be difficult to resolve in the future. Volatility requires that addresses for mapping or translation fit within the available bounds of the virtual address space. This unfortunately means that addresses that have the protections against abuse in place can may live outside this range. This provides two function (canonicalize and decanonicalize) which will either set the appropriate sign extension or remove it. The decanonicalize function will return an adress outside of the address range if the original value was not canonical. --- volatility3/framework/layers/intel.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/volatility3/framework/layers/intel.py b/volatility3/framework/layers/intel.py index dce207fd5..ecfb6bf11 100644 --- a/volatility3/framework/layers/intel.py +++ b/volatility3/framework/layers/intel.py @@ -56,6 +56,11 @@ class Intel(linear.LinearlyMappedLayer): ) self._entry_size = struct.calcsize(self._entry_format) self._entry_number = self.page_size // self._entry_size + self._canonical_prefix = self._mask( + (1 << self._bits_per_register) - 1, + self._bits_per_register, + self._maxvirtaddr, + ) # These can vary depending on the type of space self._index_shift = int( @@ -106,6 +111,23 @@ class Intel(linear.LinearlyMappedLayer): """Returns whether a particular page is valid based on its entry.""" return bool(entry & 1) + def canonicalize(self, addr: int) -> int: + """Canonicalizes an address by performing an appropiate sign extension on the higher addresses""" + if self._bits_per_register <= self._maxvirtaddr: + return addr & self.address_mask + elif addr < (1 << self._maxvirtaddr - 1): + return addr + return self._mask(addr, self._maxvirtaddr, 0) + self._canonical_prefix + + def decanonicalize(self, addr: int) -> int: + """Removes canonicalization to ensure an adress fits within the correct range if it has been canonicalized + + This will produce an address outside the range if the canonicalization is incorrect + """ + if addr < (1 << self._maxvirtaddr - 1): + return addr + return addr ^ self._canonical_prefix + def _translate(self, offset: int) -> Tuple[int, int, str]: """Translates a specific offset based on paging tables.