1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 import re
35
36 from rekall import scan
37 from rekall.plugins import core
38 from rekall.plugins.addrspaces import intel
39 from rekall.plugins.common import pfn
40 from rekall.plugins.windows import address_resolver
41 from rekall.plugins.windows import common
42 from rekall.plugins.windows import pagefile
43 from rekall_lib import utils
44
45
46 -class VAD(common.WinProcessFilter):
47 """Concise dump of the VAD.
48
49 Similar to windbg's !vad.
50 """
51
52 __name = "vad"
53
54 __args = [
55 dict(name="regex", type="RegEx",
56 help="A regular expression to filter VAD filenames."),
57
58 dict(name="offset", type="IntParser",
59 help="Only print the vad corresponding to this offset.")
60 ]
61
62 table_header = [
63 dict(name='_EPROCESS', type="_EPROCESS", hidden=True),
64 dict(name="divider", type="Divider"),
65 dict(name='VAD', style="address"),
66 dict(name='lev', width=3, align="r"),
67 dict(name='start', style="address"),
68 dict(name='end', style="address"),
69 dict(name='com', width=6, align="r"),
70 dict(name='type', width=7),
71 dict(name='exe', width=6),
72 dict(name='protect', width=20),
73 dict(name='filename')
74 ]
75
79
81 return dict(
82 _EPROCESS=self.session.profile._EPROCESS(),
83 divider=self.session.profile._EPROCESS(),
84 VAD=self.session.profile._MMVAD(),
85 lev=int,
86 start=self.session.profile.Pointer(),
87 end=self.session.profile.Pointer(),
88 com=int,
89 type=str,
90 exe=str,
91 protect=self.session.profile.Enumeration(),
92 filename=str)
93
98
100 resolver = self.GetVadsForProcess(task)
101 if resolver:
102 _, _, data = resolver.get_containing_range(addr)
103 return data
104
106 result = utils.RangedCollection()
107 self.session.report_progress(
108 " Enumerating VADs in %s (%s)", task.name, task.pid)
109
110 for vad in task.RealVadRoot.traverse():
111 result.insert(vad.Start, vad.End, (self._get_filename(vad), vad))
112
113 return result
114
116 try:
117 resolver = self._cache[task]
118 except KeyError:
119
120
121
122
123 self._cache[task] = None
124 resolver = self._cache[task] = self._make_cache(task)
125
126 return resolver
127
129 filename = ""
130 try:
131 file_obj = vad.ControlArea.FilePointer
132 if file_obj:
133 filename = file_obj.FileName or "Pagefile-backed section"
134 except AttributeError:
135 pass
136
137 return unicode(filename)
138
140 task_as = task.get_process_address_space()
141 result = []
142 for vad in vad_root.traverse():
143
144 if self.plugin_args.regex and not re.search(
145 self.plugin_args.regex, self._get_filename(vad)):
146 continue
147
148 if (self.plugin_args.offset is not None and
149 not vad.Start <= self.plugin_args.offset <= vad.End):
150 continue
151
152 exe = ""
153 if "EXECUTE" in str(vad.u.VadFlags.ProtectionEnum):
154 exe = "Exe"
155
156 result.append(dict(
157 VAD=vad,
158 lev=vad.obj_context.get('depth', 0),
159
160
161 start=self.profile.Pointer(value=vad.Start, vm=task_as),
162 end=self.profile.Pointer(value=vad.End, vm=task_as),
163 com=vad.CommitCharge if vad.CommitCharge < 0x7fffffff else -1,
164 type="Private" if vad.u.VadFlags.PrivateMemory > 0 else "Mapped",
165 exe=exe,
166 protect=vad.u.VadFlags.ProtectionEnum,
167 filename=self._get_filename(vad)))
168
169
170 result.sort(key=lambda x: x["start"].v())
171 return result
172
174 for task in self.filter_processes():
175 yield dict(_EPROCESS=task, divider=task)
176
177 for row in self.collect_vadroot(task.RealVadRoot, task):
178 row["_EPROCESS"] = task
179 yield row
180
181
182 -class VADMap(pfn.VADMapMixin, common.WinProcessFilter):
183 """Inspect each page in the VAD and report its status.
184
185 This allows us to see the address translation status of each page in the
186 VAD.
187 """
188
238
253
263
264
265 -class VADDump(core.DirectoryDumperMixin, VAD):
266 """Dumps out the vad sections to a file"""
267
268 __name = "vaddump"
269
270 @classmethod
271 - def args(cls, parser):
276
278 self.max_size = kwargs.pop("max_size", 100*1024*1024)
279 super(VADDump, self).__init__(*args, **kwargs)
280
282 for task in self.filter_processes():
283 renderer.section("{0:6} ({1:2})".format(
284 task.name, task.UniqueProcessId))
285
286 renderer.table_header([
287 ("Start", "start", "[addrpad]"),
288 ("End", "end", "[addrpad]"),
289 ("Length", "length", "[addr]"),
290 ("Filename", "filename", "60s"),
291 ("Comment", "comment", "")])
292
293
294 task_space = task.get_process_address_space()
295
296 name = task.ImageFileName
297 offset = task_space.vtop(task.obj_offset)
298 if offset is None:
299 renderer.format(
300 "Process does not have a valid address space.\n")
301 continue
302
303 with self.session.plugins.cc() as cc:
304 cc.SwitchProcessContext(task)
305
306 for vad in task.RealVadRoot.traverse():
307
308 start = vad.Start
309 end = vad.End
310
311 filename = "{0}.{1:x}.{2:08x}-{3:08x}.dmp".format(
312 name, offset, start, end)
313
314 with renderer.open(directory=self.dump_dir,
315 filename=filename,
316 mode='wb') as fd:
317
318 if end - start > self.max_size:
319 renderer.table_row(start, end, end-start,
320 "Skipped - Region too large")
321 continue
322
323 self.session.report_progress("Dumping %s" % filename)
324
325 self.CopyToFile(task_space, start, end + 1, fd)
326 renderer.table_row(
327 start, end, end-start, filename,
328 self._get_filename(vad))
329
332 """A scanner over all memory regions of a process."""
333
334 - def __init__(self, task=None, process_profile=None, **kwargs):
335 """Scan the process address space through the Vads.
336
337 Args:
338 task: The _EPROCESS object for this task.
339
340 process_profile: The specialized profile for this process. In practice
341 this is always different from task.obj_profile (which belongs to the
342 kernel). If not provided we default to the kernel profile.
343 """
344 self.task = task
345 super(VadScanner, self).__init__(
346 profile=process_profile or task.obj_profile,
347 address_space=task.get_process_address_space(),
348 **kwargs)
349
350 - def scan(self, offset=0, maxlen=None):
357