# Volatility # Copyright (C) 2007-2013 Volatility Foundation # # This file is part of Volatility. # # Volatility is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License Version 2 as # published by the Free Software Foundation. You may not use, modify or # distribute this program under any other version of the GNU General # Public License. # # Volatility is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Volatility. If not, see . # """ @author: Andrew Case @license: GNU General Public License 2.0 @contact: atcuno@gmail.com @organization: """ import volatility.obj as obj import volatility.plugins.linux.common as linux_common import volatility.plugins.linux.pslist as linux_pslist class linux_kernel_opened_files(linux_common.AbstractLinuxCommand): """Lists files that are opened from within the kernel""" def _walk_node_hash(self, node): last_node = None cnt = 0 hash_offset = self.addr_space.profile.get_obj_offset("dentry", "d_hash") while node.is_valid() and node != last_node: if cnt > 0: yield node, cnt dentry = obj.Object("dentry", offset = node.v() - hash_offset, vm = self.addr_space) cnt = cnt + 1 last_node = node node = dentry.d_hash.next def _walk_node_node(self, node): last_node = None cnt = 0 while node.is_valid() and node != last_node: if cnt > 0: yield node, cnt cnt = cnt + 1 last_node = node node = node.next def _walk_node(self, node): last_node = None yield node, 0 for node, cnt in self._walk_node_node(node): yield node, cnt for node, cnt in self._walk_node_hash(node): yield node, cnt def _gather_dcache(self): d_hash_shift = obj.Object("unsigned int", offset =self.addr_space.profile.get_symbol("d_hash_shift"), vm = self.addr_space) loop_max = 1 << d_hash_shift d_htable_ptr = obj.Object("Pointer", offset = self.addr_space.profile.get_symbol("dentry_hashtable"), vm = self.addr_space) arr = obj.Object(theType = "Array", targetType = "hlist_bl_head", offset = d_htable_ptr, vm = self.addr_space, count = loop_max) hash_offset = self.addr_space.profile.get_obj_offset("dentry", "d_hash") dents = {} for list_head in arr: if not list_head.first.is_valid(): continue node = obj.Object("hlist_bl_node", offset = list_head.first & ~1, vm = self.addr_space) for node, cnt in self._walk_node(node): dents[node.v() - hash_offset] = 0 return dents def _compare_filps(self): dcache = self._gather_dcache() tasks = linux_pslist.linux_pslist(self._config).calculate() for task in tasks: for filp, i in task.lsof(): val = filp.dentry.v() if not val in dcache: yield val procs = linux_pslist.linux_pslist(self._config).calculate() for proc in procs: for vma in proc.get_proc_maps(): if vma.vm_file: val = vma.vm_file.dentry.v() if not val in dcache: yield val def calculate(self): linux_common.set_plugin_members(self) for dentry_offset in self._compare_filps(): dentry = obj.Object("dentry", offset = dentry_offset, vm = self.addr_space) if dentry.d_count > 0 and dentry.d_inode.is_reg() and dentry.d_flags == 128: yield dentry def render_text(self, outfd, data): self.table_header(outfd, [("Offset (V)", "[addrpad]"), ("Partial File Path", "")]) for dentry in data: self.table_row(outfd, dentry.obj_offset, dentry.get_partial_path())