Trees | Indices | Help |
|
---|
|
1 # Rekall Memory Forensics 2 # Copyright 2014 Google Inc. All Rights Reserved. 3 # 4 # This program is free software; you can redistribute it and/or modify 5 # it under the terms of the GNU General Public License as published by 6 # the Free Software Foundation; either version 2 of the License, or (at 7 # your option) any later version. 8 # 9 # This program is distributed in the hope that it will be useful, but 10 # WITHOUT ANY WARRANTY; without even the implied warranty of 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 # General Public License for more details. 13 # 14 # You should have received a copy of the GNU General Public License 15 # along with this program; if not, write to the Free Software 16 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 # 18 19 """The module implements the windows specific address resolution plugin.""" 20 21 __author__ = "Michael Cohen <scudette@gmail.com>" 22 import re 23 24 from rekall import addrspace 25 from rekall import config 26 from rekall import obj 27 from rekall import plugin 28 from rekall import testlib 29 from rekall.plugins.common import address_resolver 30 from rekall.plugins.windows import common 31 from rekall.plugins.overlays.windows import pe_vtypes 32 from rekall_lib import utils 33 34 35 config.DeclareOption( 36 "autodetect_build_local_tracked", 37 group="Autodetection Overrides", 38 default=["nt", "win32k", "tcpip", "ntdll"], 39 type="ArrayStringParser", 40 help="When autodetect_build_local is set to 'basic' we fetch these " 41 "modules directly from the symbol server.")42 43 44 # In windows there are two types of mapped PE files - kernel modules and Dlls. 45 46 -class PEModule(address_resolver.Module):47 """Windows overlays PE files in memory.""" 48 49 _profile = None 5020652 """Get the module guid from the session cache. 53 54 This allows the user to override the GUID detection with their own. 55 """ 56 return self.session.GetParameter("%s_profile" % self.name)5759 """Guess the guid for the PE file.""" 60 # Try to load the file from the physical address space. 61 if self.session.physical_address_space.metadata("can_map_files"): 62 phys_as = self.session.physical_address_space 63 if self.filename: 64 image_offset = phys_as.get_mapped_offset(self.filename, 0) 65 if image_offset: 66 try: 67 file_as = addrspace.RunBasedAddressSpace( 68 base=phys_as, session=self.session) 69 70 file_as.add_run(0, image_offset, 2**63) 71 72 pe_file_as = pe_vtypes.PEFileAddressSpace( 73 base=file_as, session=self.session) 74 75 pe_helper = pe_vtypes.PE( 76 address_space=pe_file_as, 77 image_base=pe_file_as.image_base, 78 session=self.session) 79 80 return pe_helper.RSDS.GUID_AGE 81 except IOError: 82 pass8385 # Overlay on the virtual AS. 86 pe_helper = pe_vtypes.PE( 87 address_space=self.session.GetParameter("default_address_space"), 88 image_base=self.start, session=self.session) 89 90 return pe_helper.RSDS.GUID_AGE9193 index = self.session.LoadProfile("%s/index" % self.name) 94 for profile_name, _ in index.LookupIndex(self.start): 95 return profile_name9698 """Try to figure out the profile name for this module. 99 100 We have a number of methods as we need to call these in the most 101 appropriate order. 102 """ 103 # Firt check the session - this allows the user to specify the profile 104 # directly by storing e.g. win32_profile in the session. 105 profile = self.detect_profile_from_session() 106 if profile: 107 return profile 108 109 # We might have the original file, e.g. in the AFF4 image. 110 guid = (self.detect_guid_from_mapped_file() or 111 112 # Maybe we can just read the RSDS value from the mapped pe 113 # header. 114 self.detect_guid_pe_header()) 115 116 if guid: 117 return "%s/GUID/%s" % (self.name, guid) 118 119 # Finally try to apply the index if available. 120 return self.detect_profile_from_index()121123 """Fetch and build a local profile from the symbol server.""" 124 if profile_name is None: 125 profile_name = self.detect_profile_name() 126 127 mode = self.session.GetParameter("autodetect_build_local") 128 if force or mode == "full" or ( 129 mode == "basic" and 130 self.name in self.session.GetParameter( 131 "autodetect_build_local_tracked")): 132 build_local_profile = self.session.plugins.build_local_profile() 133 try: 134 self.session.logging.debug("Will build local profile %s", 135 profile_name) 136 build_local_profile.fetch_and_parse(profile_name) 137 return self.session.LoadProfile(profile_name, use_cache=False) 138 except IOError: 139 pass 140 141 return obj.NoneObject()142144 """Create a dummy profile from PE exports.""" 145 # Building from export table is slow and might not be needed if the user 146 # wants speed. 147 if self.session.GetParameter("performance") == "fast": 148 return obj.NoneObject() 149 150 self.session.logging.debug("Building profile from PE Exports for %s", 151 self.name) 152 result = obj.Profile.classes["BasicPEProfile"]( 153 name=self.name, 154 session=self.session) 155 156 result.image_base = self.start 157 158 peinfo = self.session.plugins.peinfo( 159 image_base=self.start, address_space=self.session.GetParameter( 160 "default_address_space")) 161 162 constants = {} 163 if "Export" in self.session.GetParameter("name_resolution_strategies"): 164 for _, func, name, _ in peinfo.pe_helper.ExportDirectory(): 165 self.session.report_progress("Merging export table: %s", name) 166 func_offset = func.v() 167 if not result.get_constant_by_address(func_offset): 168 constants[str(name or "")] = func_offset - self.start 169 170 result.add_constants(constants_are_addresses=True, constants=constants) 171 return result172174 self._profile = None175 176 @utils.safe_property 182184 profile_name = self.detect_profile_name() 185 if profile_name: 186 self._profile = ( 187 self.session.LoadProfile(profile_name) or 188 self.build_local_profile(profile_name, force=force)) 189 190 if not self._profile: 191 # Profile is not available, should we build it? 192 self._profile = self.build_profile_from_exports() 193 194 if not self._profile: 195 return obj.NoneObject("Unable to detect GUID") 196 197 self._profile.image_base = self.start 198 return self._profile199 200 @profile.setter202 """Allow the profile for this module to be overridden.""" 203 self._profile = value 204 if value: 205 self._profile.image_base = self.start209 """A Module corresponding to a VAD entry.""" 210 filename = None 211231 244213 name = "vad_%#x" % vad.Start 214 try: 215 # The filename of the _MMVAD 216 self.file_obj = vad.ControlArea.FilePointer 217 if self.file_obj.v(): 218 self.filename = self.file_obj.file_name_with_drive() 219 name = WindowsAddressResolver.NormalizeModuleName(self.filename) 220 except AttributeError: 221 # Anonymous module has no name but can be enumerated via 222 # address_resolver.modules(). 223 self.file_obj = self.filename = None 224 225 self.vad = vad 226 super(VadModule, self).__init__( 227 name=name, 228 start=vad.Start, 229 end=vad.End, 230 session=session)245 246 -class WindowsAddressResolver(address_resolver.AddressResolverMixin, 247 common.WindowsCommandPlugin):248 """A windows specific address resolver plugin.""" 249 250 @classmethod336252 parser.add_argument( 253 "download_profile", default=False, 254 help="Try to download the profile for this module from the " 255 "symbol server.")256258 super(WindowsAddressResolver, self).__init__(**kwargs) 259 self.download_profile = download_profile260262 if self.download_profile: 263 self.session.address_resolver.GetModuleByName( 264 self.download_profile).load_profile(force=True)265 266 @staticmethod268 result = unicode(module_name) 269 result = re.split(r"[/\\]", result)[-1] 270 271 # Drop the file extension. 272 result = result.split(".")[0] 273 274 # The kernel is treated specially - just like windbg. 275 if result in ["ntoskrnl", "ntkrnlpa", "ntkrnlmp"]: 276 result = u"nt" 277 278 return result.lower()279281 """Add module names to the tracked list.""" 282 already_tracked = self.session.GetParameter( 283 'autodetect_build_local_tracked') or [] 284 285 needed = set(modules) 286 if not needed.issubset(already_tracked): 287 needed.update(already_tracked) 288 with self.session as session: 289 session.SetParameter("autodetect_build_local_tracked", needed) 290 for module_name in modules: 291 module_obj = self.GetModuleByName(module_name) 292 if module_obj: 293 # Clear the module's profile. This will force it to 294 # reload a new profile. 295 module_obj.profile = None296 297299 """Initialize the address resolver. 300 301 In windows we populate the virtual address space map from kernel modules 302 and VAD mapped files (dlls). 303 """ 304 if self._initialized: 305 return 306 307 try: 308 # First populate with kernel modules. 309 for ldr_entry in self.session.plugins.modules().lsmod(): 310 self.AddModule( 311 KernelModule(ldr_module=ldr_entry, session=self.session)) 312 313 # Windows 10 does not have the kernel in the modules list. 314 if not self._modules_by_name.get("nt"): 315 start = obj.Pointer.integer_to_address( 316 self.session.GetParameter("kernel_base")) 317 pe = pe_vtypes.PE(image_base=start, session=self.session) 318 end = start + pe.nt_header.OptionalHeader.SizeOfImage 319 self.AddModule( 320 PEModule( 321 session=self.session, 322 name="nt", 323 start=start, 324 end=end, 325 profile=self.session.profile) 326 ) 327 328 # Now use the vad. 329 process_context = self.session.GetParameter("process_context") 330 if process_context != None: 331 for vad in process_context.RealVadRoot.traverse(): 332 self.AddModule(VadModule(vad=vad, session=self.session)) 333 334 finally: 335 self._initialized = True337 338 -class PECommandPlugin(plugin.KernelASMixin, plugin.PhysicalASMixin, 339 plugin.TypedProfileCommand, 340 plugin.ProfileCommand):341 """A command that is active when inspecting a PE file.""" 342 __abstract = True 343 344 @classmethod349 353357 """A simple address resolver for PE files.""" 358444360 super(PEAddressResolver, self).__init__(*args, **kwargs) 361 self.image_base = self.kernel_address_space.image_base 362 self.pe_helper = pe_vtypes.PE( 363 address_space=self.session.kernel_address_space, 364 image_base=self.image_base, 365 session=self.session)366 367 @staticmethod369 result = unicode(module_name) 370 result = re.split(r"[/\\]", result)[-1] 371 372 # The kernel is treated specially - just like windbg. 373 if result in ["ntoskrnl.pdb", "ntkrnlpa.pdb", "ntkrnlmp.pdb"]: 374 result = u"nt" 375 376 return result377379 capture = super(PEAddressResolver, self)._ParseAddress(name) 380 if capture["module"] != "header" and not capture["symbol"]: 381 capture["symbol"] = capture["module"] 382 capture["module"] = "header" 383 384 return capture385387 if self._initialized: 388 return 389 390 symbols = {} 391 self.pe_profile = None 392 393 # Get a usable profile. 394 if "Symbol" in self.session.GetParameter("name_resolution_strategies"): 395 # Load the profile for this binary. 396 self.pe_profile = self.session.LoadProfile("%s/GUID/%s" % ( 397 self.NormalizeModuleName(self.pe_helper.RSDS.Filename), 398 self.pe_helper.RSDS.GUID_AGE)) 399 400 if self.pe_profile == None: 401 self.pe_profile = pe_vtypes.BasicPEProfile(session=self.session) 402 403 if "Export" in self.session.GetParameter("name_resolution_strategies"): 404 # Extract all exported symbols into the profile's symbol table. 405 for _, func, name, _ in self.pe_helper.ExportDirectory(): 406 func_address = func.v() 407 name = utils.SmartUnicode(name) 408 symbols[name] = func_address - self.image_base 409 410 self.pe_profile.image_base = self.image_base 411 self.pe_profile.add_constants(constants_are_addresses=True, 412 constants=symbols) 413 414 # A section for the header. 415 self.AddModule( 416 PESectionModule(start=self.image_base, 417 end=self.image_base+0x1000, 418 name="pe", 419 profile=self.pe_profile, 420 session=self.session)) 421 422 # Find the highest address covered in this executable image. 423 for _, name, virtual_address, length in self.pe_helper.Sections(): 424 if length > 0: 425 virtual_address += self.image_base 426 self.AddModule( 427 PESectionModule(start=virtual_address, 428 end=virtual_address + length, 429 name=self.NormalizeModuleName(name), 430 profile=self.pe_profile, 431 session=self.session)) 432 433 self._initialized = True434436 if "!" not in pattern: 437 pattern = "pe!" + pattern 438 return super(PEAddressResolver, self).search_symbol(pattern)439441 self._EnsureInitialized() 442 return "<%s: %s@%#x>" % (self.__class__.__name__, self.pe_profile.name, 443 self.image_base)447 PLUGIN = "address_resolver"448
Trees | Indices | Help |
|
---|
Generated by Epydoc 3.0.1 on Mon Oct 9 03:29:41 2017 | http://epydoc.sourceforge.net |