1 """Rekall plugins for displaying processes in live triaging."""
2
3 import psutil
4 from efilter.protocols import structured
5
6 from rekall_lib import utils
7
8 from rekall.plugins import core
9 from rekall.plugins.response import common
10 from rekall.plugins.overlays import basic
11
12 from rekall.plugins import yarascanner
16 """An object to represent a live process.
17
18 This is the live equivalent of _EPROCESS.
19 """
20 __slots__ = ("_proc", "_obj_profile", "session",
21 "start_time", "obj_offset", "pid")
22
23 obj_offset = 0
24
39
40 @utils.safe_property
42
43
44 if self._obj_profile is None:
45 self._obj_profile = common.IRProfile(
46 session=self.session, proc=self)
47
48 return self._obj_profile
49
52
54 try:
55 result = getattr(self._proc, field_name)
56 if callable(result):
57 result = result()
58
59 return result
60 except psutil.Error:
61
62 if field_name == "environ":
63 return {}
64
65 return None
66 except AttributeError:
67 return None
68
78
80 return "<Live Process pid=%s>" % self.pid
81
84
86 try:
87 return self._proc.as_dict()
88 except Exception:
89
90 return {}
91
92
93 psutil_fields = ['cmdline', 'connections', 'cpu_affinity',
94 'cpu_percent', 'cpu_times', 'create_time',
95 'cwd', 'environ', 'exe', 'gids', 'io_counters',
96 'ionice', 'memory_full_info', 'memory_info',
97 'memory_info_ex', 'memory_maps', 'memory_percent',
98 'name', 'nice', 'num_ctx_switches', 'num_fds',
99 'num_threads', 'open_files', 'pid', 'ppid',
100 'status', 'terminal', 'threads', 'uids', 'username',
101 'num_handles']
102
103
104 properties = dict(__slots__=())
105 for field in psutil_fields:
106 properties[field] = property(
107 lambda self, field=field: self._get_field(field))
108
109 LiveProcess = type("LiveProcess", (_LiveProcess, ), properties)
110
111
112 structured.IStructured.implement(
113 for_type=LiveProcess,
114 implementations={
115 structured.resolve: lambda d, m: getattr(d, m, None),
116 structured.getmembers_runtime: lambda d: set(psutil_fields + d.keys()),
117 }
118 )
122 """A live process filter using the system APIs."""
123
124 __abstract = True
125
126 __args = [
127 dict(name="pids", positional=True, type="ArrayIntParser", default=[],
128 help="One or more pids of processes to select."),
129
130 dict(name="proc_regex", default=None, type="RegEx",
131 help="A regex to select a process by name."),
132 ]
133
134 @utils.safe_property
137
152
158
160 """A plugin which lists all open files."""
161 name = "lsof"
162
163 table_header = [
164 dict(name="divider", type="Divider"),
165 dict(name="proc", hidden=True),
166 dict(name="file", hidden=True),
167 dict(name="name", width=30),
168 dict(name="pid", width=6, align="r"),
169 dict(name="user", width=8),
170 dict(name="fd", width=4),
171 dict(name="mode", width=4),
172 dict(name="offset", width=12),
173 dict(name="node", width=8),
174 dict(name="path"),
175 ]
176
190
194 """A live pslist plugin using the APIs."""
195
196 name = "pslist"
197
198 table_header = [
199 dict(name="proc", hidden=True),
200 dict(name="Name", width=30),
201 dict(name="pid", width=6, align="r"),
202 dict(name="ppid", width=6, align="r"),
203 dict(name="Thds", width=6, align="r"),
204 dict(name="Hnds", width=8, align="r"),
205 dict(name="wow64", width=6),
206 dict(name="start", width=24),
207 dict(name="binary"),
208 ]
209
212
214 """Determine if the proc is Wow64."""
215
216 return (proc.environ.get("PROCESSOR_ARCHITECTURE") == 'x86' and
217 proc.environ.get("PROCESSOR_ARCHITEW6432") == 'AMD64')
218
219 - def _row(self, proc):
229
233
234
235 -class APISetProcessContext(core.SetProcessContextMixin,
236 APIProcessFilter):
237 """A cc plugin for setting process context to live mode."""
238 name = "cc"
239
242 """Scanner for scanning processes using the ReadProcessMemory() API."""
243
244 __abstract = True
245
266
269 """Yara scan process memory using the ReadProcessMemory() API."""
270 name = "yarascan"
271