1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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
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
55
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
64 func = ptr.dereference_as(target="Function",
65 target_args=dict(name=member))
66
67 yield member, func
68
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
76 if current in seen:
77 return
78 seen.add(current)
79
80 yield current, posixpath.join(path, current.Name)
81
82
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
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
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
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
131
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
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
155
156
157
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
170 """Check the file ops for all the open file handles."""
171 f_op_members = sorted(self.profile.file_operations().members.keys())
172
173
174
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
198
199
201 PARAMETERS = dict(
202 commandline="check_task_fops --proc_regex %(proc_name)s --all",
203 proc_name="bash"
204 )
205