| Trees | Indices | Help |
|
|---|
|
|
1 # Rekall Memory Forensics
2 # Copyright (C) 2012
3 # Copyright 2013 Google Inc. All Rights Reserved.
4 #
5 # Authors:
6 # Michael Cohen <scudette@gmail.com> based on code by
7 # {npetroni,awalters}@4tphi.net (Nick Petroni and AAron Walters)
8 #
9 # This program is free software; you can redistribute it and/or modify
10 # it under the terms of the GNU General Public License as published by
11 # the Free Software Foundation; either version 2 of the License, or (at
12 # your option) any later version.
13 #
14 # This program is distributed in the hope that it will be useful, but
15 # WITHOUT ANY WARRANTY; without even the implied warranty of
16 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 # General Public License for more details.
18 #
19 # You should have received a copy of the GNU General Public License
20 # along with this program; if not, write to the Free Software
21 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #
23
24 """An Address Space for processing crash dump files."""
25
26 from rekall import addrspace
27 from rekall.plugins.overlays.windows import crashdump
28
29 # pylint: disable=protected-access
30
31
33 """ This Address Space supports windows Crash Dump format """
34 order = 30
35
36 PAGE_SIZE = 0x1000
37
38 # Participate in Address Space voting.
39 __image = True
40
42 super(WindowsCrashDumpSpace32, self).__init__(**kwargs)
43
44 self.as_assert(self.base != None, "No base address space provided")
45
46 self.offset = 0
47 self.fname = ''
48
49 # Check the file for sanity.
50 self.check_file()
51
52 file_offset = self.header.obj_size
53
54 for run in self.header.PhysicalMemoryBlockBuffer.Run:
55 self.add_run(int(run.BasePage) * self.PAGE_SIZE,
56 file_offset,
57 int(run.PageCount) * self.PAGE_SIZE)
58
59 file_offset += run.PageCount * self.PAGE_SIZE
60
61 self.session.SetCache(
62 "dtb", int(self.header.DirectoryTableBase))
63
65 """Checks the base file handle for sanity."""
66
67 self.as_assert(self.base,
68 "Must stack on another address space")
69
70 # Must start with the magic PAGEDUMP
71 self.as_assert((self.base.read(0, 8) == 'PAGEDUMP'),
72 "Header signature invalid")
73
74 self.profile = crashdump.CrashDump32Profile(
75 session=self.session)
76
77 self.header = self.profile.Object(
78 "_DMP_HEADER", offset=self.offset, vm=self.base)
79
80 if self.header.DumpType != "Full Dump":
81 # Here we rely on the WindowsCrashBMP AS to run before us. Therefore
82 # we fail hard if this is not a valid legacy crash format.
83 raise IOError("This is not a full memory crash dump. "
84 "Kernel crash dumps are not supported.")
85
86
88 """This AS supports windows Crash Dump format."""
89 order = 30
90
91 # Participate in Address Space voting.
92 __image = True
93
95 """Check specifically for 64 bit crash dumps."""
96
97 # Must start with the magic PAGEDU64
98 self.as_assert((self.base.read(0, 8) == 'PAGEDU64'),
99 "Header signature invalid")
100
101 self.profile = crashdump.CrashDump64Profile(
102 session=self.session)
103
104 self.as_assert(self.profile.has_type("_DMP_HEADER64"),
105 "_DMP_HEADER64 not available in profile")
106 self.header = self.profile.Object("_DMP_HEADER64",
107 offset=self.offset, vm=self.base)
108
109 # The following error is fatal - abort the voting mechanism.
110
111 # Unfortunately Volatility does not set this field correctly, so we do
112 # not make it a fatal error. It can lead to problems if we try to parse
113 # other crash dump formats, (Especially Win8 ones - see below) so we
114 # might consider making this a fatal error in future.
115 if self.header.DumpType != "Full Dump":
116 self.session.logging.warning(
117 "This is not a full memory crash dump. Kernel crash dumps are "
118 "not supported.")
119
120 # Catch this error early or we will hog all memory trying to parse a
121 # huge number of Runs. On Windows 8 we have observed the DumpType to be
122 # == 5 and these fields are padded with "PAGE" (i.e. 0x45474150).
123 if self.header.PhysicalMemoryBlockBuffer.NumberOfRuns > 100:
124 raise RuntimeError(
125 "This crashdump file format is not supported. Rekall does not "
126 "currently support crashdumps using the Win8 format.")
127
128
130 """This Address Space supports the new windows Crash Dump format.
131
132 This format first appeared in Windows 8 x64 versions. We reversed this
133 format by examining the Crash dump file from a Windows 8 system.
134
135 Alternative implementations:
136 Volatility 2.4: crashbmp.py (not working at time of writing.).
137 """
138 # Must try this before the old Crashdump format.
139 order = 25
140
141 PAGE_SIZE = 0x1000
142
143 # Participate in Address Space voting.
144 __image = True
145
147 super(WindowsCrashBMP, self).__init__(**kwargs)
148
149 self.as_assert(self.base, "Must stack on another address space")
150
151 # Must start with the magic PAGEDU64
152 self.as_assert((self.base.read(0, 8) == 'PAGEDU64'),
153 "Header signature invalid")
154
155 self.profile = crashdump.CrashDump64Profile(
156 session=self.session)
157
158 self.header = self.profile.Object("_DMP_HEADER64", vm=self.base)
159 self.as_assert(
160 self.header.DumpType == "BMP Dump", "Only BMP dumps supported.")
161
162 self.bmp_header = self.header.BMPHeader
163 PAGE_SIZE = 0x1000
164
165 # First run [Physical Offset, File Offset, Run length]
166 first_page = self.bmp_header.FirstPage.v()
167 last_run = [0, first_page, 0]
168
169 for pfn, present in enumerate(self._generate_bitmap()):
170 if present:
171 if pfn * PAGE_SIZE == last_run[0] + last_run[2]:
172 last_run[2] += PAGE_SIZE
173
174 else:
175 # Dump the last run only if it has non zero length.
176 if last_run[2] > 0:
177 self.add_run(*last_run)
178
179 # The next run starts here.
180 last_run = [
181 pfn * PAGE_SIZE, last_run[1] + last_run[2], PAGE_SIZE]
182
183 # Flush the last run if needed.
184 if last_run[2] > 0:
185 self.add_run(*last_run)
186
187 # Set the DTB from the crash dump header.
188 self.session.SetCache("dtb", self.header.DirectoryTableBase.v(),
189 volatile=False)
190
191
193 """Generate Present/Not Present for each page in the dump."""
194 # The bitmap is an array of 32 bit integers. Each bit in each int
195 # represents a single memory page.
196 for value in self.bmp_header.Bitmap:
197 # This is kind of lame but in python it is way faster than bit
198 # manipulations.
199 for bit in reversed("{0:032b}".format((value.v()))):
200 yield bit == "1"
201
| Trees | Indices | Help |
|
|---|
| Generated by Epydoc 3.0.1 on Mon Oct 9 03:29:43 2017 | http://epydoc.sourceforge.net |