1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 """This module adds support for incident response to Rekall."""
24
25 __author__ = "Michael Cohen <scudette@google.com>"
26 import platform
27 import os
28 import stat
29
30 import arrow
31
32 from efilter.protocols import associative
33 from efilter.protocols import structured
34
35 from rekall import addrspace
36 from rekall import obj
37 from rekall import plugin
38
39 from rekall_lib import registry
40 from rekall_lib import utils
41
42
43 IRProcessAddressSpace = None
44 IRProfile = None
60
63 """A class representing the profile for IR (live) analysis."""
64
65
66 METADATA = dict(live=True, type="API",
67 os=platform.system())
68
71 """Specification of a file path."""
72
73 __slots__ = ("name", "filesystem", "path_sep")
74
75 default_path_sep = "\\" if platform.system() == "Windows" else "/"
76
77 - def __init__(self, filename, filesystem=u"API", path_sep=None):
94
95 @property
100
101 @property
107
110
112 """Get a path suitable to be used with os APIs."""
113 result = os.path.sep.join(self.components())
114
115
116 if os.path.sep == "/":
117 result = "/" + result
118
119 return result
120
123
124 - def join(self, components):
134
135 - def add(self, component):
141
142
143 -class User(utils.SlottedObject):
144 """A class to represent a user."""
145
146 __slots__ = ("session", "uid", "username", "homedir", "shell")
147
148 @classmethod
149 @registry.memoize
151 result = cls()
152
153
154 try:
155 import pwd
156
157 record = pwd.getpwuid(uid)
158 result.uid = uid
159 result.username = record.pw_name
160 result.homedir = record.pw_dir
161 result.shell = record.pw_shell
162 except (KeyError, ImportError):
163 pass
164
165 return result
166
169
171 if self.username:
172 return u"%s (%s)" % (self.username, self.uid)
173 elif self.uid is not None:
174 return unicode(self.uid)
175
176 return ""
177
178
179 -class Group(utils.SlottedObject):
180 """A class to represent a user."""
181
182 __slots__ = ("session", "gid", "group_name")
183
184 @classmethod
185 @registry.memoize
187 result = cls()
188
189
190 try:
191 import grp
192
193 record = grp.getgrgid(gid)
194 result.gid = gid
195 result.group_name = record.gr_name
196 except (KeyError, ImportError):
197 pass
198
199 return result
200
203
205 if self.group_name:
206 return u"%s (%s)" % (self.group_name, self.gid)
207
208 elif self.gid is not None:
209 return unicode(self.gid)
210
211 return ""
212
294
297
298 """An object to represent permissions."""
299 __metaclass__ = registry.UniqueObjectIdMetaclass
300
301
302 _filemode_table = (
303 ((stat.S_IFLNK, "l"),
304 (stat.S_IFREG, "-"),
305 (stat.S_IFBLK, "b"),
306 (stat.S_IFDIR, "d"),
307 (stat.S_IFCHR, "c"),
308 (stat.S_IFIFO, "p")),
309
310 ((stat.S_IRUSR, "r"),),
311 ((stat.S_IWUSR, "w"),),
312 ((stat.S_IXUSR|stat.S_ISUID, "s"),
313 (stat.S_ISUID, "S"),
314 (stat.S_IXUSR, "x")),
315
316 ((stat.S_IRGRP, "r"),),
317 ((stat.S_IWGRP, "w"),),
318 ((stat.S_IXGRP|stat.S_ISGID, "s"),
319 (stat.S_ISGID, "S"),
320 (stat.S_IXGRP, "x")),
321
322 ((stat.S_IROTH, "r"),),
323 ((stat.S_IWOTH, "w"),),
324 ((stat.S_IXOTH|stat.S_ISVTX, "t"),
325 (stat.S_ISVTX, "T"),
326 (stat.S_IXOTH, "x"))
327 )
328
330 self.value = int(value)
331
333 """Convert a file's mode to a string of the form '-rwxrwxrwx'."""
334 perm = []
335 for table in self._filemode_table:
336 for bit, char in table:
337 if mode & bit == bit:
338 perm.append(char)
339 break
340 else:
341 perm.append("-")
342 return "".join(perm)
343
346
349
352
354 return stat.S_ISDIR(self.value)
355
357 return stat.S_ISLNK(self.value)
358
362 """A base class for all IR plugins.
363
364 IR Plugins are only active when the session is live.
365 """
366
367 __abstract = True
368
369 PROFILE_REQUIRED = False
370 mode = "mode_live"
371
375 """A base class for all API access plugins.
376
377 These plugins are only active when we are in pure API mode (e.g. API
378 pslist).
379 """
380
381 __abstract = True
382
383 PROFILE_REQUIRED = False
384 mode = "mode_live_api"
385
386
387 FILE_SPEC_DISPATCHER = dict(API=FileInformation)
391 """Return the correct FileInformation class from the filename.
392
393 Currently we only support OS API accessible files, but in the future we will
394 also support NTFS files.
395 """
396
397 filespec = FileSpec(filename)
398
399 handler = FILE_SPEC_DISPATCHER.get(filespec.filesystem)
400 if handler:
401 try:
402 return handler.from_stat(filespec, session=session)
403 except (IOError, OSError):
404
405 return obj.NoneObject("Cant open %s", filespec)
406
407 raise RuntimeError("Unsupported file spec type %s" %
408 filespec.filesystem)
409
410
411
412 associative.IAssociative.implement(
413 for_type=FileInformation,
414 implementations={
415 associative.select: getattr,
416 associative.reflect_runtime_key: structured.reflect_runtime_member,
417 associative.getkeys_runtime: structured.getmembers_runtime
418 }
419 )
420
421 associative.IAssociative.implement(
422 for_type=FileSpec,
423 implementations={
424 associative.select: getattr,
425 associative.reflect_runtime_key: lambda c: str,
426 associative.getkeys_runtime: lambda _: ["name"]
427 }
428 )
429