Package rekall :: Package plugins :: Package linux :: Module check_fops
[frames] | no frames]

Source Code for Module rekall.plugins.linux.check_fops

  1  # Rekall Memory Forensics 
  2  # Copyright (C) 2007-2013 Volatility Foundation 
  3  # Copyright 2013 Google Inc. All Rights Reserved. 
  4  # 
  5  # This file is part of Rekall Memory Forensics. 
  6  # 
  7  # Rekall Memory Forensics is free software; you can redistribute it and/or 
  8  # modify it under the terms of the GNU General Public License Version 2 as 
  9  # published by the Free Software Foundation.  You may not use, modify or 
 10  # distribute this program under any other version of the GNU General Public 
 11  # License. 
 12  # 
 13  # Rekall Memory Forensics is distributed in the hope that it will be useful, 
 14  # but WITHOUT ANY WARRANTY; without even the implied warranty of 
 15  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 16  # GNU General Public License for more details. 
 17  # 
 18  # You should have received a copy of the GNU General Public License along with 
 19  # Rekall Memory Forensics.  If not, see <http://www.gnu.org/licenses/>. 
 20  # 
 21   
 22  """ 
 23  @author:       Michael Cohen based on code by Andrew Case 
 24  @license:      GNU General Public License 2.0 
 25  @contact:      scudette@gmail.com 
 26  """ 
 27  import itertools 
 28  import posixpath 
 29   
 30  from rekall import testlib 
 31  from rekall.plugins.linux import common 
 32   
 33   
34 -class CheckProcFops(common.LinuxPlugin):
35 """Checks the proc filesystem for hooked f_ops.""" 36 __name = "check_proc_fops" 37 38 __args = [ 39 dict(name="all", type="Boolean", 40 help="Specify to see all the fops, even if they " 41 "are known."), 42 ] 43 44 table_header = [ 45 dict(name="dir_entry", style="address"), 46 dict(name="path", width=50), 47 dict(name="member", width=20), 48 dict(name="address", style="address"), 49 dict(name="module") 50 ] 51
52 - def __init__(self, *args, **kwargs):
53 super(CheckProcFops, self).__init__(*args, **kwargs) 54 self.module_plugin = self.session.plugins.lsmod(session=self.session)
55
56 - def _check_members(self, struct, members):
57 """Yields struct members and their containing module.""" 58 for member in members: 59 ptr = struct.m(member) 60 if not ptr: 61 continue 62 63 # This is really a function pointer. 64 func = ptr.dereference_as(target="Function", 65 target_args=dict(name=member)) 66 67 yield member, func
68
69 - def _walk_proc(self, current, seen, path=""):
70 """Recursively traverse the proc filesystem yielding proc_dir_entry. 71 72 Yields: 73 tuples of proc_dir_entry, full_path to this proc entry. 74 """ 75 # Prevent infinite recursion here. 76 if current in seen: 77 return 78 seen.add(current) 79 80 yield current, posixpath.join(path, current.Name) 81 82 # Yield our peers. 83 for proc_dir_entry in current.walk_list("next"): 84 for x in self._walk_proc(proc_dir_entry, seen, path): 85 yield x 86 87 # Now also yield the subdirs: 88 if current.subdir: 89 for x in self._walk_proc( 90 current.subdir, seen, 91 posixpath.join(path, unicode(current.Name))): 92 yield x
93
94 - def check_proc_fop(self):
95 """Check the proc mount point.""" 96 f_op_members = sorted(self.profile.file_operations().members.keys()) 97 proc_mnt = self.profile.get_constant_object( 98 "proc_mnt", 99 target="Pointer", 100 target_args=dict( 101 target="vfsmount" 102 ), 103 vm=self.kernel_address_space) 104 105 root = proc_mnt.mnt_root 106 for member, func in self._check_members( 107 root.d_inode.i_fop, f_op_members): 108 yield (proc_mnt, "proc_mnt: root", member, func) 109 110 111 # only check the root directory 112 for dentry in root.d_subdirs.list_of_type("dentry", "d_u"): 113 name = dentry.d_name.name.deref() 114 for member, func in self._check_members( 115 dentry.d_inode.i_fop, f_op_members): 116 yield dentry, name, member, func
117
118 - def check_fops(self):
119 """Check the file ops for all the open file handles.""" 120 f_op_members = sorted(self.profile.file_operations().members.keys()) 121 proc_root = self.profile.get_constant_object( 122 "proc_root", 123 target="proc_dir_entry", 124 vm=self.kernel_address_space) 125 126 seen = set() 127 for proc_dir_entry, full_path in self._walk_proc(proc_root, seen): 128 for member, func in self._check_members( 129 proc_dir_entry.proc_fops, f_op_members): 130 yield proc_dir_entry, full_path, member, func
131
132 - def collect(self):
133 for proc_dir_entry, path, member, func in itertools.chain( 134 self.check_proc_fop(), self.check_fops()): 135 location = ", ".join( 136 self.session.address_resolver.format_address( 137 func.obj_offset)) 138 139 # Point out suspicious constants. 140 highlight = None if location else "important" 141 142 if highlight or self.plugin_args.all: 143 yield dict(dir_entry=proc_dir_entry, 144 path=path, member=member, address=func, 145 module=location, highlight=highlight) 146 147 self.session.report_progress( 148 "Checking proc f_ops for %(path)s", path=path)
149 150
151 -class TestCheckProcFops(testlib.SimpleTestCase):
152 PARAMETERS = dict( 153 commandline="check_proc_fops --all" 154 )
155 156 157
158 -class CheckTaskFops(CheckProcFops, common.LinProcessFilter):
159 """Check open files in tasks for f_ops modifications.""" 160 __name = "check_task_fops" 161 162 table_header = [ 163 dict(name="task", width=30), 164 dict(name="member", width=30), 165 dict(name="address", style="address"), 166 dict(name="module") 167 ] 168
169 - def check_fops(self):
170 """Check the file ops for all the open file handles.""" 171 f_op_members = sorted(self.profile.file_operations().members.keys()) 172 173 # Use the lsof plugin to get all the open files in each task we care 174 # about. 175 lsof = self.session.plugins.lsof(session=self.session) 176 177 for task in self.filter_processes(): 178 for file_struct, _ in lsof.get_open_files(task): 179 for member, func in self._check_members( 180 file_struct.f_op, f_op_members): 181 yield task, member, func
182
183 - def collect(self):
184 for task, member, func in self.check_fops(): 185 location = ", ".join( 186 self.session.address_resolver.format_address( 187 func.obj_offset)) 188 189 highlight = None if location else "important" 190 191 if highlight or self.plugin_args.all: 192 yield dict(task=task, member=member, address=func, 193 module=location, highlight=highlight) 194 195 self.session.report_progress( 196 "Checking task f_ops for %(comm)s (%(pid)s)", 197 comm=task.comm, pid=task.pid)
198 199
200 -class TestCheckTaskFops(testlib.SimpleTestCase):
201 PARAMETERS = dict( 202 commandline="check_task_fops --proc_regex %(proc_name)s --all", 203 proc_name="bash" 204 )
205