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

Source Code for Module rekall.plugins.addrspaces.pmem

  1  # Rekall Memory Forensics 
  2  # 
  3  # Copyright 2015 Google Inc. All Rights Reserved. 
  4  # 
  5  # This program is free software; you can redistribute it and/or modify 
  6  # it under the terms of the GNU General Public License as published by 
  7  # the Free Software Foundation; either version 2 of the License, or (at 
  8  # your option) any later version. 
  9  # 
 10  # This program is distributed in the hope that it will be useful, but 
 11  # WITHOUT ANY WARRANTY; without even the implied warranty of 
 12  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 
 13  # General Public License for more details. 
 14  # 
 15  # You should have received a copy of the GNU General Public License 
 16  # along with this program; if not, write to the Free Software 
 17  # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 
 18  # 
 19   
 20  """Address spaces specific to pmem live here.""" 
 21  __author__ = "Adam Sindelar <adamsh@google.com>" 
 22   
 23  from os import path 
 24   
 25  from rekall import addrspace 
 26  from rekall import yaml_utils 
 27  from rekall.plugins.addrspaces import standard 
 28   
 29   
30 -class _StreamWrapper(object):
31 - def __init__(self, stream):
32 self.stream = stream
33
34 - def read(self, offset, length):
35 self.stream.seek(offset) 36 return self.stream.read(length)
37
38 - def write(self, offset, length):
39 self.stream.seek(offset) 40 return self.stream.write(length)
41 42
43 -class MacPmemAddressSpace(addrspace.RunBasedAddressSpace):
44 """Implements an address space to overlay the new MacPmem device.""" 45 46 name = "MacPmem" 47 order = standard.FileAddressSpace.order - 2 48 __image = True 49 volatile = True 50 fd = None 51 fname = None 52 _writable = True 53
54 - def _ensure_fd_writable(self):
55 """Reopen the device if necessary. 56 57 /dev/pmem is open read-only by default. This reopens it if writes are 58 requested. 59 """ 60 if self.session.GetParameter("writable_physical_memory"): 61 expected_mode = "r+" 62 else: 63 raise RuntimeError( 64 "writable_physical_memory is not set in the Session.") 65 66 if self.fd.mode != expected_mode: 67 self.fd.close() 68 self.fd = open(self.fname, expected_mode)
69
70 - def __init__(self, base=None, filename=None, **kwargs):
71 super(MacPmemAddressSpace, self).__init__(**kwargs) 72 73 self.as_assert(base == None, 74 "Must be mapped directly over a raw device.") 75 self.fname = filename or (self.session and self.session.GetParameter( 76 "filename")) 77 78 self.as_assert(self.fname, "Filename must be specified.") 79 80 # Open as read-only even if writes are supported and allowed, because 81 # permissions may be set up such that opening for writing would be 82 # disallowed. 83 try: 84 self.fd = open(self.fname, "r") 85 except (OSError, IOError): 86 raise addrspace.ASAssertionError( 87 "Filename does not exist or can not be opened.") 88 89 self.fname_info = "%s_info" % self.fname 90 self.as_assert(path.exists(self.fname_info), 91 "MacPmem would declare a YML device at %s" % 92 self.fname_info) 93 94 self._load_yml(self.fname_info)
95
96 - def _get_readable_runs(self, records):
97 """Yields all the runs that are safe to read. 98 99 This just trusts the EFI bootmap at the moment. 100 """ 101 for record in records: 102 if record["type"] == "efi_range": 103 if efi_type_readable(record["efi_type"]): 104 yield (record["start"], record["start"], record["length"], 105 _StreamWrapper(self.fd))
106
107 - def ConfigureSession(self, session_obj):
108 session_obj.SetCache("dtb", self.pmem_metadata["meta"]["dtb_off"], 109 volatile=False) 110 session_obj.SetCache("vm_kernel_slide", 111 self.pmem_metadata["meta"]["kaslr_slide"], 112 volatile=False)
113
114 - def _load_yml(self, yml_path):
115 with open(yml_path) as fp: 116 data = self.pmem_metadata = yaml_utils.decode(fp.read()) 117 118 for run in self._get_readable_runs(data["records"]): 119 self.add_run(*run)
120
121 - def close(self):
122 self.fd.close()
123 124 125 # See http://wiki.phoenix.com/wiki/index.php/EFI_MEMORY_TYPE for list of 126 # segment types that become conventional memory after ExitBootServices() 127 # is sent to EFI. 128 EFI_SEGMENTS_SAFETY = { 129 "EfiReservedMemoryType": "", 130 "EfiLoaderCode": "rw", # General use. 131 "EfiLoaderData": "rw", # General use. 132 "EfiBootServicesCode": "rw", # General use. 133 "EfiBootServicesData": "rw", # General use. 134 "EfiRuntimeServicesCode": "r", # Memory to be preserved. 135 "EfiRuntimeServicesData": "r", # Memory to be preserved. 136 "EfiConventionalMemory": "r", # General use. 137 "EfiUnusableMemory": "", # (Hardware) errors - don't use. 138 "EfiACPIReclaimMemory": "rw", # General use after ACPI enabled. 139 "EfiACPIMemoryNVS": "r", # Memory to be preserved. 140 "EfiMemoryMappedIO": "", # ACPI tables. 141 "EfiMemoryMappedIOPortSpace": "", # ACPI tables. 142 "EfiPalCode": "r", # OS-dependent. Largely read-only. 143 "EfiMaxMemoryType": "rw", # No idea (adamsh). Looks like general use? 144 } 145 146
147 -def efi_type_readable(efi_type):
148 return "r" in EFI_SEGMENTS_SAFETY[str(efi_type)]
149