From 3d51b4a41a7110670826557ea82f3bd0ecf55e5c Mon Sep 17 00:00:00 2001 From: Eve Date: Fri, 24 Mar 2023 15:08:59 +0000 Subject: [PATCH 1/9] Add basic support for linux maple tree struct --- .../framework/symbols/linux/__init__.py | 2 + .../symbols/linux/extensions/__init__.py | 142 ++++++++++++++++++ 2 files changed, 144 insertions(+) diff --git a/volatility3/framework/symbols/linux/__init__.py b/volatility3/framework/symbols/linux/__init__.py index ce07167e5..7a22241a5 100644 --- a/volatility3/framework/symbols/linux/__init__.py +++ b/volatility3/framework/symbols/linux/__init__.py @@ -50,6 +50,8 @@ class LinuxKernelIntermedSymbols(intermed.IntermediateSymbolTable): self.optional_set_type_class("bt_sock", extensions.bt_sock) self.optional_set_type_class("xdp_sock", extensions.xdp_sock) + # Only found in 6.1+ kernels + self.optional_set_type_class("maple_tree", extensions.maple_tree) class LinuxUtilities(interfaces.configuration.VersionableInterface): """Class with multiple useful linux functions.""" diff --git a/volatility3/framework/symbols/linux/extensions/__init__.py b/volatility3/framework/symbols/linux/extensions/__init__.py index 5ab8f1aa0..72173f471 100644 --- a/volatility3/framework/symbols/linux/extensions/__init__.py +++ b/volatility3/framework/symbols/linux/extensions/__init__.py @@ -294,11 +294,128 @@ class fs_struct(objects.StructType): raise AttributeError("Unable to find the root mount") +class maple_tree(objects.StructType): + # include/linux/maple_tree.h + # Mask for Maple Tree Flags + MT_FLAGS_HEIGHT_MASK = 0x7C + MT_FLAGS_HEIGHT_OFFSET = 0x02 + + # Shift and mask to extract information from maple tree node pointers + MAPLE_NODE_TYPE_SHIFT = 0x03 + MAPLE_NODE_TYPE_MASK = 0x0F + MAPLE_NODE_POINTER_MASK = 0xFF + + # types of Maple Tree Nodes + MAPLE_DENSE = 0 + MAPLE_LEAF_64 = 1 + MAPLE_RANGE_64 = 2 + MAPLE_ARANGE_64 = 3 + + def get_slot_iter(self): + """Parse the Maple Tree and return every non zero slot.""" + maple_tree_offset, _, _ = self._parse_maple_tree_entry(self.vol.offset) + maple_tree_depth = ( + self.ma_flags & self.MT_FLAGS_HEIGHT_MASK + ) >> self.MT_FLAGS_HEIGHT_OFFSET + yield from self._parse_maple_tree_node( + self.ma_root, maple_tree_offset, maple_tree_depth + ) + + def _parse_maple_tree_node( + self, maple_tree_entry, parent, maple_tree_depth, seen=set(), depth=1 + ): + """Recursively parse Maple Tree Nodes and yield all non empty slots""" + + # protect against unlikely loop + if maple_tree_entry in seen: + vollog.warning( + f"The mte {hex(maple_tree_entry)} has all ready been seen, no further results will be produced for this node." + ) + return + else: + seen.add(maple_tree_entry) + if maple_tree_depth < depth: + vollog.warning( + f"The depth for the maple tree at {hex(self.vol.offset)} is {maple_tree_depth}, however when parsing the nodes " + f"a depth of {depth} was reached. This is unexpected and may lead to incorrect results." + ) + # parse the mte to extract the pointer value, node type, and leaf status + pointer, node_type, is_leaf = self._parse_maple_tree_entry(maple_tree_entry) + + # create a pointer object for the node parent mte (note this will include flags in the low bits) + symbol_table_name = self.get_symbol_table_name() + node_parent_mte = self._context.object( + symbol_table_name + constants.BANG + "pointer", + layer_name=self.vol.layer_name, + offset=pointer, + ) + + # extract the actual pointer to the parent of this node + node_parent_pointer, _, _ = self._parse_maple_tree_entry(node_parent_mte) + + # verify that the node_parent_pointer correctly points to the parent + assert node_parent_pointer == parent + + # create a node object + node = self._context.object( + symbol_table_name + constants.BANG + "maple_node", + layer_name=self.vol.layer_name, + offset=pointer, + ) + + # parse the slots based on the node type + if node_type == self.MAPLE_DENSE: + assert is_leaf == True + for slot in node.alloc.slot: + if (slot & ~(self.MAPLE_NODE_TYPE_MASK)) != 0: + yield slot + elif node_type == self.MAPLE_LEAF_64: + assert is_leaf == True + for slot in node.mr64.slot: + if (slot & ~(self.MAPLE_NODE_TYPE_MASK)) != 0: + yield slot + elif node_type == self.MAPLE_RANGE_64: + assert is_leaf == False + for slot in node.mr64.slot: + if (slot & ~(self.MAPLE_NODE_TYPE_MASK)) != 0: + yield from self._parse_maple_tree_node( + slot, pointer, maple_tree_depth, seen, depth + 1 + ) + elif node_type == self.MAPLE_ARANGE_64: + assert is_leaf == False + for slot in node.ma64.slot: + if (slot & ~(self.MAPLE_NODE_TYPE_MASK)) != 0: + yield from self._parse_maple_tree_node( + slot, pointer, maple_tree_depth, seen, depth + 1 + ) + else: + # unkown maple node type + raise AttributeError( + f"Unkown Maple Tree node type {node_type} at offset {hex(pointer)}." + ) + + def _parse_maple_tree_entry(self, maple_tree_entry): + """Parse a Maple Tree Entry and return the pointer, node type, if the node is a leaf, if the node is the root""" + # Extract the node type + node_type = ( + maple_tree_entry >> self.MAPLE_NODE_TYPE_SHIFT + ) & self.MAPLE_NODE_TYPE_MASK + + # Determine if it's a leaf node or not + is_leaf = node_type < self.MAPLE_RANGE_64 + + # Clear the lower bits to get the true pointer value + pointer = maple_tree_entry & ~(self.MAPLE_NODE_POINTER_MASK) + + return pointer, node_type, is_leaf class mm_struct(objects.StructType): def get_mmap_iter(self) -> Iterable[interfaces.objects.ObjectInterface]: """Returns an iterator for the mmap list member of an mm_struct.""" + if not self.has_member('mmap'): + raise AttributeError("get_mmap_iter called on mm_struct where no mmap member exists.") + if not self.mmap: return @@ -312,7 +429,32 @@ class mm_struct(objects.StructType): seen.add(link.vol.offset) link = link.vm_next + def get_maple_tree_iter(self) -> Iterable[interfaces.objects.ObjectInterface]: + """Returns an iterator for the mm_mt member of an mm_struct.""" + + if not self.has_member('mm_mt'): + raise AttributeError("get_maple_tree_iter called on mm_struct where no mm_mt member exists.") + symbol_table_name = self.get_symbol_table_name() + for vma_pointer in self.mm_mt.get_slot_iter(): + # convert pointer to vm_area_struct and yield + vma = self._context.object( + symbol_table_name + constants.BANG + "vm_area_struct", + layer_name=self.vol.layer_name, + offset=vma_pointer + ) + yield vma + + def get_vma_iter(self) -> Iterable[interfaces.objects.ObjectInterface]: + """Returns an iterator for the VMAs in an mm_struct. Automatically choosing the mmap or mm_mt as required.""" + + if self.has_member('mmap'): + yield from self.get_mmap_iter() + elif self.has_member('mm_mt'): + yield from self.get_maple_tree_iter() + else: + raise AttributeError("Unable to find mmap or mm_mt in mm_struct") + class super_block(objects.StructType): # include/linux/kdev_t.h MINORBITS = 20 From 5207cfcb93cf7f8955b5a499ac13a46ba962da78 Mon Sep 17 00:00:00 2001 From: Eve Date: Fri, 24 Mar 2023 15:10:34 +0000 Subject: [PATCH 2/9] Modify linux plugins to support both mmap and mm_mt --- volatility3/framework/plugins/linux/elfs.py | 2 +- volatility3/framework/plugins/linux/malfind.py | 2 +- volatility3/framework/plugins/linux/proc.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/volatility3/framework/plugins/linux/elfs.py b/volatility3/framework/plugins/linux/elfs.py index 822a69dd6..2ff5eb591 100644 --- a/volatility3/framework/plugins/linux/elfs.py +++ b/volatility3/framework/plugins/linux/elfs.py @@ -48,7 +48,7 @@ class Elfs(plugins.PluginInterface): name = utility.array_to_string(task.comm) - for vma in task.mm.get_mmap_iter(): + for vma in task.mm.get_vma_iter(): hdr = proc_layer.read(vma.vm_start, 4, pad=True) if not ( hdr[0] == 0x7F diff --git a/volatility3/framework/plugins/linux/malfind.py b/volatility3/framework/plugins/linux/malfind.py index 18237b80c..1fd005de8 100644 --- a/volatility3/framework/plugins/linux/malfind.py +++ b/volatility3/framework/plugins/linux/malfind.py @@ -46,7 +46,7 @@ class Malfind(interfaces.plugins.PluginInterface): proc_layer = self.context.layers[proc_layer_name] - for vma in task.mm.get_mmap_iter(): + for vma in task.mm.get_vma_iter(): if vma.is_suspicious() and vma.get_name(self.context, task) != "[vdso]": data = proc_layer.read(vma.vm_start, 64, pad=True) yield vma, data diff --git a/volatility3/framework/plugins/linux/proc.py b/volatility3/framework/plugins/linux/proc.py index 9d8af482e..8979f6f63 100644 --- a/volatility3/framework/plugins/linux/proc.py +++ b/volatility3/framework/plugins/linux/proc.py @@ -44,7 +44,7 @@ class Maps(plugins.PluginInterface): name = utility.array_to_string(task.comm) - for vma in task.mm.get_mmap_iter(): + for vma in task.mm.get_vma_iter(): flags = vma.get_protection() page_offset = vma.get_page_offset() major = 0 From 89e477a068092cad50acfaa0fd965097ae5da8c7 Mon Sep 17 00:00:00 2001 From: Eve Date: Fri, 24 Mar 2023 20:07:32 +0000 Subject: [PATCH 3/9] Remove _parse_maple_tree_entry function and make parsing easier to read --- .../symbols/linux/extensions/__init__.py | 25 ++++++------------- 1 file changed, 7 insertions(+), 18 deletions(-) diff --git a/volatility3/framework/symbols/linux/extensions/__init__.py b/volatility3/framework/symbols/linux/extensions/__init__.py index 72173f471..9375a288b 100644 --- a/volatility3/framework/symbols/linux/extensions/__init__.py +++ b/volatility3/framework/symbols/linux/extensions/__init__.py @@ -313,7 +313,7 @@ class maple_tree(objects.StructType): def get_slot_iter(self): """Parse the Maple Tree and return every non zero slot.""" - maple_tree_offset, _, _ = self._parse_maple_tree_entry(self.vol.offset) + maple_tree_offset = self.vol.offset & ~(self.MAPLE_NODE_POINTER_MASK) maple_tree_depth = ( self.ma_flags & self.MT_FLAGS_HEIGHT_MASK ) >> self.MT_FLAGS_HEIGHT_OFFSET @@ -340,7 +340,11 @@ class maple_tree(objects.StructType): f"a depth of {depth} was reached. This is unexpected and may lead to incorrect results." ) # parse the mte to extract the pointer value, node type, and leaf status - pointer, node_type, is_leaf = self._parse_maple_tree_entry(maple_tree_entry) + pointer = maple_tree_entry & ~(self.MAPLE_NODE_POINTER_MASK) + node_type = ( + maple_tree_entry >> self.MAPLE_NODE_TYPE_SHIFT + ) & self.MAPLE_NODE_TYPE_MASK + is_leaf = node_type < self.MAPLE_RANGE_64 # create a pointer object for the node parent mte (note this will include flags in the low bits) symbol_table_name = self.get_symbol_table_name() @@ -351,7 +355,7 @@ class maple_tree(objects.StructType): ) # extract the actual pointer to the parent of this node - node_parent_pointer, _, _ = self._parse_maple_tree_entry(node_parent_mte) + node_parent_pointer = node_parent_mte & ~(self.MAPLE_NODE_POINTER_MASK) # verify that the node_parent_pointer correctly points to the parent assert node_parent_pointer == parent @@ -394,21 +398,6 @@ class maple_tree(objects.StructType): f"Unkown Maple Tree node type {node_type} at offset {hex(pointer)}." ) - def _parse_maple_tree_entry(self, maple_tree_entry): - """Parse a Maple Tree Entry and return the pointer, node type, if the node is a leaf, if the node is the root""" - # Extract the node type - node_type = ( - maple_tree_entry >> self.MAPLE_NODE_TYPE_SHIFT - ) & self.MAPLE_NODE_TYPE_MASK - - # Determine if it's a leaf node or not - is_leaf = node_type < self.MAPLE_RANGE_64 - - # Clear the lower bits to get the true pointer value - pointer = maple_tree_entry & ~(self.MAPLE_NODE_POINTER_MASK) - - return pointer, node_type, is_leaf - class mm_struct(objects.StructType): def get_mmap_iter(self) -> Iterable[interfaces.objects.ObjectInterface]: """Returns an iterator for the mmap list member of an mm_struct.""" From 089234671c70b746c91c25ac2980a6a4f35607b0 Mon Sep 17 00:00:00 2001 From: Eve Date: Mon, 27 Mar 2023 06:29:30 +0100 Subject: [PATCH 4/9] Remove checks for leaf node in linux maple tree parsing, node type is enough. --- volatility3/framework/symbols/linux/extensions/__init__.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/volatility3/framework/symbols/linux/extensions/__init__.py b/volatility3/framework/symbols/linux/extensions/__init__.py index 9375a288b..a8bf1b6aa 100644 --- a/volatility3/framework/symbols/linux/extensions/__init__.py +++ b/volatility3/framework/symbols/linux/extensions/__init__.py @@ -344,7 +344,6 @@ class maple_tree(objects.StructType): node_type = ( maple_tree_entry >> self.MAPLE_NODE_TYPE_SHIFT ) & self.MAPLE_NODE_TYPE_MASK - is_leaf = node_type < self.MAPLE_RANGE_64 # create a pointer object for the node parent mte (note this will include flags in the low bits) symbol_table_name = self.get_symbol_table_name() @@ -369,24 +368,20 @@ class maple_tree(objects.StructType): # parse the slots based on the node type if node_type == self.MAPLE_DENSE: - assert is_leaf == True for slot in node.alloc.slot: if (slot & ~(self.MAPLE_NODE_TYPE_MASK)) != 0: yield slot elif node_type == self.MAPLE_LEAF_64: - assert is_leaf == True for slot in node.mr64.slot: if (slot & ~(self.MAPLE_NODE_TYPE_MASK)) != 0: yield slot elif node_type == self.MAPLE_RANGE_64: - assert is_leaf == False for slot in node.mr64.slot: if (slot & ~(self.MAPLE_NODE_TYPE_MASK)) != 0: yield from self._parse_maple_tree_node( slot, pointer, maple_tree_depth, seen, depth + 1 ) elif node_type == self.MAPLE_ARANGE_64: - assert is_leaf == False for slot in node.ma64.slot: if (slot & ~(self.MAPLE_NODE_TYPE_MASK)) != 0: yield from self._parse_maple_tree_node( From 859482445907fd9c2ae579d37e0a898b10857690 Mon Sep 17 00:00:00 2001 From: Eve Date: Tue, 9 May 2023 06:47:07 +0100 Subject: [PATCH 5/9] Linux: Ensure that objects made when parsing maple tree use the native_layer_name --- volatility3/framework/symbols/linux/extensions/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/volatility3/framework/symbols/linux/extensions/__init__.py b/volatility3/framework/symbols/linux/extensions/__init__.py index a8bf1b6aa..931003b60 100644 --- a/volatility3/framework/symbols/linux/extensions/__init__.py +++ b/volatility3/framework/symbols/linux/extensions/__init__.py @@ -349,7 +349,7 @@ class maple_tree(objects.StructType): symbol_table_name = self.get_symbol_table_name() node_parent_mte = self._context.object( symbol_table_name + constants.BANG + "pointer", - layer_name=self.vol.layer_name, + layer_name=self.vol.native_layer_name, offset=pointer, ) @@ -424,7 +424,7 @@ class mm_struct(objects.StructType): # convert pointer to vm_area_struct and yield vma = self._context.object( symbol_table_name + constants.BANG + "vm_area_struct", - layer_name=self.vol.layer_name, + layer_name=self.vol.native_layer_name, offset=vma_pointer ) yield vma From a2906ad270b3ec09dd38db3bc1d24b58de0c7054 Mon Sep 17 00:00:00 2001 From: Eve Date: Tue, 9 May 2023 07:07:39 +0100 Subject: [PATCH 6/9] Linux: Update comments and var names for maple tree depth warnings --- .../symbols/linux/extensions/__init__.py | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/volatility3/framework/symbols/linux/extensions/__init__.py b/volatility3/framework/symbols/linux/extensions/__init__.py index 931003b60..67a4cd2d0 100644 --- a/volatility3/framework/symbols/linux/extensions/__init__.py +++ b/volatility3/framework/symbols/linux/extensions/__init__.py @@ -314,15 +314,15 @@ class maple_tree(objects.StructType): def get_slot_iter(self): """Parse the Maple Tree and return every non zero slot.""" maple_tree_offset = self.vol.offset & ~(self.MAPLE_NODE_POINTER_MASK) - maple_tree_depth = ( + expected_maple_tree_depth = ( self.ma_flags & self.MT_FLAGS_HEIGHT_MASK ) >> self.MT_FLAGS_HEIGHT_OFFSET yield from self._parse_maple_tree_node( - self.ma_root, maple_tree_offset, maple_tree_depth + self.ma_root, maple_tree_offset, expected_maple_tree_depth ) def _parse_maple_tree_node( - self, maple_tree_entry, parent, maple_tree_depth, seen=set(), depth=1 + self, maple_tree_entry, parent, expected_maple_tree_depth, seen=set(), current_depth=1 ): """Recursively parse Maple Tree Nodes and yield all non empty slots""" @@ -334,11 +334,16 @@ class maple_tree(objects.StructType): return else: seen.add(maple_tree_entry) - if maple_tree_depth < depth: + + # check if we have exceeded the expected depth of this maple tree. + # e.g. when current_depth is larger than expected_maple_tree_depth there may be an issue. + # it is normal that expected_maple_tree_depth is equal to current_depth. + if expected_maple_tree_depth < current_depth: vollog.warning( - f"The depth for the maple tree at {hex(self.vol.offset)} is {maple_tree_depth}, however when parsing the nodes " - f"a depth of {depth} was reached. This is unexpected and may lead to incorrect results." + f"The depth for the maple tree at {hex(self.vol.offset)} is {expected_maple_tree_depth}, however when parsing the nodes " + f"a depth of {current_depth} was reached. This is unexpected and may lead to incorrect results." ) + # parse the mte to extract the pointer value, node type, and leaf status pointer = maple_tree_entry & ~(self.MAPLE_NODE_POINTER_MASK) node_type = ( @@ -379,13 +384,13 @@ class maple_tree(objects.StructType): for slot in node.mr64.slot: if (slot & ~(self.MAPLE_NODE_TYPE_MASK)) != 0: yield from self._parse_maple_tree_node( - slot, pointer, maple_tree_depth, seen, depth + 1 + slot, pointer, expected_maple_tree_depth, seen, current_depth + 1 ) elif node_type == self.MAPLE_ARANGE_64: for slot in node.ma64.slot: if (slot & ~(self.MAPLE_NODE_TYPE_MASK)) != 0: yield from self._parse_maple_tree_node( - slot, pointer, maple_tree_depth, seen, depth + 1 + slot, pointer, expected_maple_tree_depth, seen, current_depth + 1 ) else: # unkown maple node type From 7f9afccf6f44fb69cd1039ab478854317bad5d5b Mon Sep 17 00:00:00 2001 From: Eve Date: Wed, 10 May 2023 08:49:46 +0100 Subject: [PATCH 7/9] Linux: apply black formating to maple tree parsing --- .../symbols/linux/extensions/__init__.py | 46 +++++++++++++------ 1 file changed, 33 insertions(+), 13 deletions(-) diff --git a/volatility3/framework/symbols/linux/extensions/__init__.py b/volatility3/framework/symbols/linux/extensions/__init__.py index 67a4cd2d0..7398a9ecd 100644 --- a/volatility3/framework/symbols/linux/extensions/__init__.py +++ b/volatility3/framework/symbols/linux/extensions/__init__.py @@ -294,6 +294,7 @@ class fs_struct(objects.StructType): raise AttributeError("Unable to find the root mount") + class maple_tree(objects.StructType): # include/linux/maple_tree.h # Mask for Maple Tree Flags @@ -322,7 +323,12 @@ class maple_tree(objects.StructType): ) def _parse_maple_tree_node( - self, maple_tree_entry, parent, expected_maple_tree_depth, seen=set(), current_depth=1 + self, + maple_tree_entry, + parent, + expected_maple_tree_depth, + seen=set(), + current_depth=1, ): """Recursively parse Maple Tree Nodes and yield all non empty slots""" @@ -384,13 +390,21 @@ class maple_tree(objects.StructType): for slot in node.mr64.slot: if (slot & ~(self.MAPLE_NODE_TYPE_MASK)) != 0: yield from self._parse_maple_tree_node( - slot, pointer, expected_maple_tree_depth, seen, current_depth + 1 + slot, + pointer, + expected_maple_tree_depth, + seen, + current_depth + 1, ) elif node_type == self.MAPLE_ARANGE_64: for slot in node.ma64.slot: if (slot & ~(self.MAPLE_NODE_TYPE_MASK)) != 0: yield from self._parse_maple_tree_node( - slot, pointer, expected_maple_tree_depth, seen, current_depth + 1 + slot, + pointer, + expected_maple_tree_depth, + seen, + current_depth + 1, ) else: # unkown maple node type @@ -398,13 +412,16 @@ class maple_tree(objects.StructType): f"Unkown Maple Tree node type {node_type} at offset {hex(pointer)}." ) + class mm_struct(objects.StructType): def get_mmap_iter(self) -> Iterable[interfaces.objects.ObjectInterface]: """Returns an iterator for the mmap list member of an mm_struct.""" - if not self.has_member('mmap'): - raise AttributeError("get_mmap_iter called on mm_struct where no mmap member exists.") - + if not self.has_member("mmap"): + raise AttributeError( + "get_mmap_iter called on mm_struct where no mmap member exists." + ) + if not self.mmap: return @@ -420,9 +437,11 @@ class mm_struct(objects.StructType): def get_maple_tree_iter(self) -> Iterable[interfaces.objects.ObjectInterface]: """Returns an iterator for the mm_mt member of an mm_struct.""" - - if not self.has_member('mm_mt'): - raise AttributeError("get_maple_tree_iter called on mm_struct where no mm_mt member exists.") + + if not self.has_member("mm_mt"): + raise AttributeError( + "get_maple_tree_iter called on mm_struct where no mm_mt member exists." + ) symbol_table_name = self.get_symbol_table_name() for vma_pointer in self.mm_mt.get_slot_iter(): @@ -430,20 +449,21 @@ class mm_struct(objects.StructType): vma = self._context.object( symbol_table_name + constants.BANG + "vm_area_struct", layer_name=self.vol.native_layer_name, - offset=vma_pointer + offset=vma_pointer, ) yield vma def get_vma_iter(self) -> Iterable[interfaces.objects.ObjectInterface]: """Returns an iterator for the VMAs in an mm_struct. Automatically choosing the mmap or mm_mt as required.""" - if self.has_member('mmap'): + if self.has_member("mmap"): yield from self.get_mmap_iter() - elif self.has_member('mm_mt'): + elif self.has_member("mm_mt"): yield from self.get_maple_tree_iter() else: raise AttributeError("Unable to find mmap or mm_mt in mm_struct") - + + class super_block(objects.StructType): # include/linux/kdev_t.h MINORBITS = 20 From 834372a6f89dc4c49c0a2fb563c1dd1cea1392ae Mon Sep 17 00:00:00 2001 From: Eve Date: Wed, 10 May 2023 09:12:03 +0100 Subject: [PATCH 8/9] Linux: apply black v23.3.0 formating to volatility3/framework/symbols/linux/extensions/__init__.py --- .../symbols/linux/extensions/__init__.py | 53 ------------------- 1 file changed, 53 deletions(-) diff --git a/volatility3/framework/symbols/linux/extensions/__init__.py b/volatility3/framework/symbols/linux/extensions/__init__.py index 7398a9ecd..eecb200f9 100644 --- a/volatility3/framework/symbols/linux/extensions/__init__.py +++ b/volatility3/framework/symbols/linux/extensions/__init__.py @@ -34,10 +34,8 @@ class module(generic.GenericIntelProcess): def get_init_size(self): if self.has_member("init_layout"): return self.init_layout.size - elif self.has_member("init_size"): return self.init_size - raise AttributeError( "module -> get_init_size: Unable to determine .init section size of module" ) @@ -45,10 +43,8 @@ class module(generic.GenericIntelProcess): def get_core_size(self): if self.has_member("core_layout"): return self.core_layout.size - elif self.has_member("core_size"): return self.core_size - raise AttributeError( "module -> get_core_size: Unable to determine core size of module" ) @@ -58,7 +54,6 @@ class module(generic.GenericIntelProcess): return self.core_layout.base elif self.has_member("module_core"): return self.module_core - raise AttributeError("module -> get_module_core: Unable to get module core") def get_module_init(self): @@ -66,7 +61,6 @@ class module(generic.GenericIntelProcess): return self.init_layout.base elif self.has_member("module_init"): return self.module_init - raise AttributeError("module -> get_module_core: Unable to get module init") def get_name(self): @@ -88,7 +82,6 @@ class module(generic.GenericIntelProcess): idx = 0 while arr[idx]: idx = idx + 1 - return idx def get_sections(self): @@ -97,7 +90,6 @@ class module(generic.GenericIntelProcess): num_sects = self.sect_attrs.nsections else: num_sects = self._get_sect_count(self.sect_attrs.grp) - arr = self._context.object( self.get_symbol_table().name + constants.BANG + "array", layer_name=self.vol.layer_name, @@ -116,7 +108,6 @@ class module(generic.GenericIntelProcess): prefix = "Elf64_" else: prefix = "Elf32_" - elf_table_name = intermed.IntermediateSymbolTable.create( self.context, self.config_path, @@ -155,7 +146,6 @@ class module(generic.GenericIntelProcess): return self.kallsyms.symtab elif self.has_member("symtab"): return self.symtab - raise AttributeError("module -> symtab: Unable to get symtab") @property @@ -164,7 +154,6 @@ class module(generic.GenericIntelProcess): return int(self.kallsyms.num_symtab) elif self.has_member("num_symtab"): return int(self.num_symtab) - raise AttributeError( "module -> num_symtab: Unable to determine number of symbols" ) @@ -177,7 +166,6 @@ class module(generic.GenericIntelProcess): # Older kernels elif self.has_member("strtab"): return self.strtab - raise AttributeError("module -> strtab: Unable to get strtab") @@ -195,19 +183,15 @@ class task_struct(generic.GenericIntelProcess): pgd = self.mm.pgd except exceptions.InvalidAddressException: return None - if not isinstance(parent_layer, linear.LinearlyMappedLayer): raise TypeError( "Parent layer is not a translation layer, unable to construct process layer" ) - dtb, layer_name = parent_layer.translate(pgd) if not dtb: return None - if preferred_name is None: preferred_name = self.vol.layer_name + f"_Process{self.pid}" - # Add the constructed layer and return the name return self._add_process_layer( self._context, dtb, config_prefix, preferred_name @@ -229,7 +213,6 @@ class task_struct(generic.GenericIntelProcess): vollog.info( f"adding vma: {start:x} {self.mm.brk:x} | {end:x} {self.mm.start_brk:x}" ) - yield (start, end - start) @property @@ -282,7 +265,6 @@ class fs_struct(objects.StructType): return self.root elif self.root.has_member("dentry"): return self.root.dentry - raise AttributeError("Unable to find the root dentry") def get_root_mnt(self): @@ -291,7 +273,6 @@ class fs_struct(objects.StructType): return self.rootmnt elif self.root.has_member("mnt"): return self.root.mnt - raise AttributeError("Unable to find the root mount") @@ -340,7 +321,6 @@ class maple_tree(objects.StructType): return else: seen.add(maple_tree_entry) - # check if we have exceeded the expected depth of this maple tree. # e.g. when current_depth is larger than expected_maple_tree_depth there may be an issue. # it is normal that expected_maple_tree_depth is equal to current_depth. @@ -349,7 +329,6 @@ class maple_tree(objects.StructType): f"The depth for the maple tree at {hex(self.vol.offset)} is {expected_maple_tree_depth}, however when parsing the nodes " f"a depth of {current_depth} was reached. This is unexpected and may lead to incorrect results." ) - # parse the mte to extract the pointer value, node type, and leaf status pointer = maple_tree_entry & ~(self.MAPLE_NODE_POINTER_MASK) node_type = ( @@ -421,10 +400,8 @@ class mm_struct(objects.StructType): raise AttributeError( "get_mmap_iter called on mm_struct where no mmap member exists." ) - if not self.mmap: return - yield self.mmap seen = {self.mmap.vol.offset} @@ -442,7 +419,6 @@ class mm_struct(objects.StructType): raise AttributeError( "get_maple_tree_iter called on mm_struct where no mm_mt member exists." ) - symbol_table_name = self.get_symbol_table_name() for vma_pointer in self.mm_mt.get_slot_iter(): # convert pointer to vm_area_struct and yield @@ -569,7 +545,6 @@ class vm_area_struct(objects.StructType): retval = retval + char else: retval = retval + "-" - return retval # only parse the rwx bits @@ -583,7 +558,6 @@ class vm_area_struct(objects.StructType): def get_page_offset(self) -> int: if self.vm_file == 0: return 0 - return self.vm_pgoff << constants.linux.PAGE_SHIFT def get_name(self, context, task): @@ -600,7 +574,6 @@ class vm_area_struct(objects.StructType): fname = "[vdso]" else: fname = "Anonymous Mapping" - return fname # used by malfind @@ -611,10 +584,8 @@ class vm_area_struct(objects.StructType): if flags_str == "rwx": ret = True - elif flags_str == "r-x" and self.vm_file.dereference().vol.offset == 0: ret = True - return ret @@ -624,12 +595,10 @@ class qstr(objects.StructType): str_length = self.len + 1 # Maximum length should include null terminator else: str_length = 255 - try: ret = objects.utility.pointer_to_string(self.name, str_length) except (exceptions.InvalidAddressException, ValueError): ret = "" - return ret @@ -660,7 +629,6 @@ class dentry(objects.StructType): """ if self.vol.offset == old_dentry: return True - return self.d_ancestor(old_dentry) def d_ancestor(self, ancestor_dentry): @@ -678,10 +646,8 @@ class dentry(objects.StructType): ): if current_dentry.d_parent == ancestor_dentry.vol.offset: return current_dentry - dentry_seen.add(current_dentry.vol.offset) current_dentry = current_dentry.d_parent - return None @@ -738,12 +704,10 @@ class list_head(objects.StructType, collections.abc.Iterable): link = getattr(self, direction).dereference() except exceptions.InvalidAddressException: return - if not sentinel: yield self._context.object( symbol_type, layer, offset=self.vol.offset - relative_offset ) - seen = {self.vol.offset} while link.vol.offset not in seen: obj = self._context.object( @@ -869,7 +833,6 @@ class mount(objects.StructType): peer = current_mnt.get_peer_under_root(self.mnt_ns, root) if peer and peer.vol.offset != 0: return peer.mnt_group_id - mnt_seen.add(current_mnt.vol.offset) current_mnt = current_mnt.mnt_master return 0 @@ -885,12 +848,10 @@ class mount(objects.StructType): current_mnt.mnt.mnt_root, root ): return current_mnt - mnt_seen.add(current_mnt.vol.offset) current_mnt = current_mnt.next_peer() if current_mnt.vol.offset == self.vol.offset: break - return None def is_path_reachable(self, current_dentry, root): @@ -907,7 +868,6 @@ class mount(objects.StructType): current_dentry = current_mnt.mnt_mountpoint mnt_seen.add(current_mnt.vol.offset) current_mnt = current_mnt.mnt_parent - return current_mnt.mnt.vol.offset == root.mnt and current_dentry.is_subdir( root.dentry ) @@ -968,7 +928,6 @@ class kobject(objects.StructType): ret = refcnt.counter else: ret = refcnt.refs.counter - return ret @@ -987,7 +946,6 @@ class mnt_namespace(objects.StructType): if not self._context.symbol_space.has_type(mnt_type): # Old kernels ~ 2.6 mnt_type = table_name + constants.BANG + "vfsmount" - for mount in self.list.to_list(mnt_type, "mnt_list"): yield mount @@ -1012,7 +970,6 @@ class socket(objects.StructType): ) if not module_names: raise ValueError(f"No module using the symbol table {symbol_table}") - kernel_module_name = module_names[0] kernel = self._context.modules[kernel_module_name] return kernel @@ -1022,7 +979,6 @@ class socket(objects.StructType): kernel = self._get_vol_kernel() except ValueError: return 0 - socket_alloc = linux.LinuxUtilities.container_of( self.vol.offset, "socket_alloc", "socket", kernel ) @@ -1048,7 +1004,6 @@ class sock(objects.StructType): def get_inode(self): if not self.sk_socket: return 0 - return self.sk_socket.get_inode() def get_protocol(self): @@ -1058,7 +1013,6 @@ class sock(objects.StructType): # Return the generic socket state if self.has_member("sk"): return self.sk.sk_socket.get_state() - return self.sk_socket.get_state() @@ -1066,7 +1020,6 @@ class unix_sock(objects.StructType): def get_name(self): if not self.addr: return - sockaddr_un = self.addr.name.cast("sockaddr_un") saddr = str(utility.array_to_string(sockaddr_un.sun_path)) return saddr @@ -1102,7 +1055,6 @@ class inet_sock(objects.StructType): protocol = IP_PROTOCOLS.get(self.sk.sk_protocol) if self.get_family() == "AF_INET6": protocol = IPV6_PROTOCOLS.get(self.sk.sk_protocol, protocol) - return protocol def get_state(self): @@ -1133,7 +1085,6 @@ class inet_sock(objects.StructType): dport_le = sk_common.skc_dport else: return - return socket_module.htons(dport_le) def get_src_addr(self): @@ -1152,7 +1103,6 @@ class inet_sock(objects.StructType): saddr = self.pinet6.saddr else: return - parent_layer = self._context.layers[self.vol.layer_name] try: addr_bytes = parent_layer.read(saddr.vol.offset, addr_size) @@ -1161,7 +1111,6 @@ class inet_sock(objects.StructType): f"Unable to read socket src address from {saddr.vol.offset:#x}" ) return - return socket_module.inet_ntop(family, addr_bytes) def get_dst_addr(self): @@ -1183,7 +1132,6 @@ class inet_sock(objects.StructType): addr_size = 16 else: return - parent_layer = self._context.layers[self.vol.layer_name] try: addr_bytes = parent_layer.read(daddr.vol.offset, addr_size) @@ -1192,7 +1140,6 @@ class inet_sock(objects.StructType): f"Unable to read socket dst address from {daddr.vol.offset:#x}" ) return - return socket_module.inet_ntop(family, addr_bytes) From b3c348820f341ea43a5bb215a5841349f46fb16c Mon Sep 17 00:00:00 2001 From: Eve Date: Wed, 10 May 2023 09:18:05 +0100 Subject: [PATCH 9/9] Linux: apply black v23.3.0 formating to volatility3/framework/symbols/linux/__init__.py --- volatility3/framework/symbols/linux/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/volatility3/framework/symbols/linux/__init__.py b/volatility3/framework/symbols/linux/__init__.py index 7a22241a5..c012f9cc7 100644 --- a/volatility3/framework/symbols/linux/__init__.py +++ b/volatility3/framework/symbols/linux/__init__.py @@ -53,6 +53,7 @@ class LinuxKernelIntermedSymbols(intermed.IntermediateSymbolTable): # Only found in 6.1+ kernels self.optional_set_type_class("maple_tree", extensions.maple_tree) + class LinuxUtilities(interfaces.configuration.VersionableInterface): """Class with multiple useful linux functions."""