Trees | Indices | Help |
|
---|
|
1 # Rekall Memory Forensics 2 # Copyright (C) 2012 Michael Cohen 3 # Copyright 2013 Google Inc. All Rights Reserved. 4 # 5 # Authors: 6 # Michael Cohen <scudette@gmail.com> 7 # 8 # This program is free software; you can redistribute it and/or modify 9 # it under the terms of the GNU General Public License as published by 10 # the Free Software Foundation; either version 2 of the License, or (at 11 # your option) any later version. 12 # 13 # This program is distributed in the hope that it will be useful, but 14 # WITHOUT ANY WARRANTY; without even the implied warranty of 15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 # General Public License for more details. 17 # 18 # You should have received a copy of the GNU General Public License 19 # along with this program; if not, write to the Free Software 20 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 # 22 """This is a windows specific address space.""" 23 import os 24 import struct 25 import weakref 26 27 import pywintypes 28 import win32file 29 30 from rekall import addrspace 31 from rekall.plugins.addrspaces import standard 32 33 34 PMEM_MODE_IOSPACE = 0 35 PMEM_MODE_PHYSICAL = 1 36 PMEM_MODE_PTE = 2 37 PMEM_MODE_PTE_PCI = 3 38 3941 return (DeviceType << 16) | (Access << 14) | (Function << 2) | Method42 43 44 # IOCTLS for interacting with the driver. 45 INFO_IOCTRL = CTL_CODE(0x22, 0x103, 0, 3) 46 CTRL_IOCTRL = CTL_CODE(0x22, 0x101, 0, 3) 47 48 PAGE_SHIFT = 12 49 5052 """A simple wrapper that makes a win32 file handle look like an AS.""" 53 5782 8359 try: 60 win32file.SetFilePointer(self.fhandle, offset, 0) 61 _, data = win32file.ReadFile(self.fhandle, length) 62 except Exception: 63 return addrspace.ZEROER.GetZeros(length) 64 65 return data6668 win32file.SetFilePointer(self.fhandle, offset, 0) 69 # The WinPmem driver returns bytes_written == 0 always. This is probably 70 # a bug in its write routine, so we ignore it here. If the operation was 71 # successful we assume all bytes were written. 72 err, _bytes_written = win32file.WriteFile(self.fhandle, data) 73 if err == 0: 74 return len(data) 75 return 07678 return self.size7981 win32file.CloseHandle(self.fhandle)86 """ This is a direct file AS for use in windows. 87 88 In windows, in order to open raw devices we need to use the win32 apis. This 89 address space allows us to open the raw device as exported by e.g. the 90 winpmem driver. 91 """ 92 93 CHUNK_SIZE = 0x1000 94118 11996 try: 97 fhandle = self.fhandle = win32file.CreateFile( 98 path, 99 win32file.GENERIC_READ, 100 win32file.FILE_SHARE_READ | win32file.FILE_SHARE_WRITE, 101 None, 102 win32file.OPEN_EXISTING, 103 win32file.FILE_ATTRIBUTE_NORMAL, 104 None) 105 106 self._closer = weakref.ref( 107 self, lambda x: win32file.CloseHandle(fhandle)) 108 109 self.write_enabled = False 110 return fhandle 111 112 except pywintypes.error as e: 113 raise IOError("Unable to open %s: %s" % (path, e))114121 __name = "win32file" 122 123 # We should be the AS of last resort but in front of the non win32 version. 124 order = standard.FileAddressSpace.order - 5 125 __image = True 126151 152128 self.as_assert(base == None, 'Must be first Address Space') 129 super(Win32FileAddressSpace, self).__init__(**kwargs) 130 131 path = filename or self.session.GetParameter("filename") 132 133 self.as_assert(path, "Filename must be specified in session (e.g. " 134 "session.SetParameter('filename', 'MyFile.raw').") 135 136 self.fname = path 137 138 # The file is just a regular file, we open for reading. 139 fhandle = self._OpenFileForRead(path) 140 141 # If we can not get the file size it means this is not a regular file - 142 # maybe a device. 143 self.fhandle_as = Win32FileWrapper(fhandle) 144 try: 145 file_size = win32file.GetFileSize(fhandle) 146 self.add_run(0, 0, file_size, self.fhandle_as) 147 except pywintypes.error: 148 # This may be a device, we just read the whole space. 149 self.add_run(0, 0, 2**63, self.fhandle_as) 150 self.volatile = True154 """An address space specifically designed for communicating with WinPmem.""" 155 156 __name = "winpmem" 157 __image = True 158 159 # This is a live address space. 160 volatile = True 161 162 # We must be in front of the regular file based AS. 163 order = Win32FileAddressSpace.order - 5 164 165 # This AS can map files into itself. 166 __can_map_files = True 167308169 self.as_assert(base == None, 'Must be first Address Space') 170 path = filename or session.GetParameter("filename") 171 self.as_assert(path.startswith("\\\\"), 172 "Filename does not look like a device.") 173 174 super(WinPmemAddressSpace, self).__init__( 175 filename=filename, session=session, **kwargs) 176 177 try: 178 # First open for write in case the driver is in write mode. 179 fhandle = self._OpenFileForWrite(path) 180 except IOError: 181 fhandle = self._OpenFileForRead(path) 182 183 self.fhandle_as = Win32FileWrapper(fhandle) 184 185 try: 186 self.ParseMemoryRuns(fhandle) 187 except Exception: 188 raise addrspace.ASAssertionError( 189 "This is not a WinPmem based driver.") 190 191 # Key: lower cased filename, value: offset where it is mapped. 192 self.mapped_files = {} 193 self.filesystems = {}194196 try: 197 fhandle = self.fhandle = win32file.CreateFile( 198 path, 199 win32file.GENERIC_READ | win32file.GENERIC_WRITE, 200 win32file.FILE_SHARE_READ | win32file.FILE_SHARE_WRITE, 201 None, 202 win32file.OPEN_EXISTING, 203 win32file.FILE_ATTRIBUTE_NORMAL, 204 None) 205 self.write_enabled = True 206 self._closer = weakref.ref( 207 self, lambda x: win32file.CloseHandle(fhandle)) 208 209 return fhandle 210 211 except pywintypes.error as e: 212 raise IOError("Unable to open %s: %s" % (path, e))213 214 FIELDS = (["CR3", "NtBuildNumber", "KernBase", "KDBG"] + 215 ["KPCR%02d" % i for i in xrange(32)] + 216 ["PfnDataBase", "PsLoadedModuleList", "PsActiveProcessHead"] + 217 ["Padding%s" % i for i in xrange(0xff)] + 218 ["NumberOfRuns"]) 219221 # Set acquisition mode. If the driver does not support this mode it will 222 # just fall back to the default. 223 win32file.DeviceIoControl( 224 fhandle, CTRL_IOCTRL, 225 struct.pack("I", PMEM_MODE_PTE), 4, None) 226 227 result = win32file.DeviceIoControl( 228 fhandle, INFO_IOCTRL, "", 102400, None) 229 230 fmt_string = "Q" * len(self.FIELDS) 231 self.memory_parameters = dict(zip(self.FIELDS, struct.unpack_from( 232 fmt_string, result))) 233 234 offset = struct.calcsize(fmt_string) 235 for x in xrange(self.memory_parameters["NumberOfRuns"]): 236 start, length = struct.unpack_from("QQ", result, x * 16 + offset) 237 self.add_run(start, start, length, self.fhandle_as)238240 dtb = self.memory_parameters["CR3"] 241 session.SetCache("dtb", int(dtb), volatile=False) 242 243 # Get the kernel base directly from the winpmem driver if that is 244 # available. 245 kernel_base = self.memory_parameters["KernBase"] 246 if kernel_base > 0: 247 self.session.SetCache("kernel_base", kernel_base, volatile=False)248250 # Parsing the NTFS can be expensive so we only do it when the user 251 # specifically wanted to be thorough. 252 if self.session.GetParameter("performance") != "thorough": 253 return 254 255 drive, base_filename = os.path.splitdrive(filename) 256 if not drive: 257 return 258 259 try: 260 ntfs_session = self.filesystems[drive] 261 except KeyError: 262 ntfs_session = self.filesystems[drive] = self.session.add_session( 263 filename=r"\\.\%s" % drive, verbose=True, autodetect=[], 264 profile="ntfs") 265 266 # Stat the MFT inode (MFT 2). 267 mft_stat = ntfs_session.plugins.istat(2) 268 269 # Lookup the mft entry by filename. 270 mft_entry = mft_stat.ntfs.MFTEntryByName(base_filename) 271 272 # Open the $DATA stream 273 return mft_entry.open_file()274276 """Return an address space for filename.""" 277 try: 278 # Try to read the file with OS APIs. 279 file_as = Win32FileAddressSpace(filename=filename, 280 session=self.session) 281 return file_as 282 except IOError: 283 try: 284 # Try to read the file with raw access. 285 file_as = self._map_raw_filename(filename) 286 return file_as 287 except IOError: 288 # Cant read this file - no mapping available. 289 return290292 # Normalize filename for case insenstive comparisons. 293 filename = filename.lower() 294 mapped_offset = self.mapped_files.get(filename) 295 if mapped_offset is None: 296 file_as = self.get_file_address_space(filename) 297 if not file_as: 298 return 299 300 # Add a guard page and align. 301 mapped_offset = self.mapped_files[filename] = ( 302 (length or self.end()) + 0x10000) & 0xFFFFFFFFFFFFF000 303 304 self.add_run(mapped_offset, 0, file_as.end(), file_as) 305 306 if mapped_offset is not None: 307 return mapped_offset + file_offset
Trees | Indices | Help |
|
---|
Generated by Epydoc 3.0.1 on Mon Oct 9 03:29:38 2017 | http://epydoc.sourceforge.net |