Package rekall :: Package plugins :: Package addrspaces :: Module crash
[frames] | no frames]

Source Code for Module rekall.plugins.addrspaces.crash

  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   
32 -class WindowsCrashDumpSpace32(addrspace.RunBasedAddressSpace):
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
41 - def __init__(self, **kwargs):
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
64 - def check_file(self):
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
87 -class WindowsCrashDumpSpace64(WindowsCrashDumpSpace32):
88 """This AS supports windows Crash Dump format.""" 89 order = 30 90 91 # Participate in Address Space voting. 92 __image = True 93
94 - def check_file(self):
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
129 -class WindowsCrashBMP(addrspace.RunBasedAddressSpace):
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
146 - def __init__(self, **kwargs):
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
192 - def _generate_bitmap(self):
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