Package rekall :: Package plugins :: Package windows :: Module index
[frames] | no frames]

Source Code for Module rekall.plugins.windows.index

  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  """This module implements profile indexing. 
 20   
 21  Rekall relies on accurate profiles for reliable analysis of memory artifacts. We 
 22  depend on selecting the correct profile from the profile repository, but 
 23  sometimes its hard to determine the exact profile to use. For windows, the 
 24  profile must match exactly the GUID in the driver. 
 25   
 26  However, sometimes, the GUID is unavailable or it could be manipulated. In that 
 27  case we would like to determine the profile version by applying the index. 
 28   
 29  The profile repository has an index for each kernel module stored. We can use 
 30  this index to determine the exact version of the profile very quickly - even if 
 31  the RSDS GUID is not available or incorrect. 
 32  """ 
 33   
 34  __author__ = "Michael Cohen <scudette@google.com>" 
 35   
 36  from rekall import obj 
 37  from rekall import testlib 
 38  from rekall.plugins.windows import common 
 39  from rekall.plugins.overlays import basic 
40 41 42 -class GuessGUID(common.WindowsCommandPlugin):
43 """Try to guess the exact version of a kernel module by using an index.""" 44 45 name = "guess_guid" 46 47 __args = [ 48 dict(name="module", positional=True, 49 help="The name of the module to guess."), 50 51 dict(name="minimal_match", default=1, type="IntParser", 52 help="The minimal number of comparison points to be considered. " 53 "Sometimes not all comparison points can be used since they may " 54 "not be mapped."), 55 ] 56 57 table_header = [ 58 dict(name="pid", width=20), 59 dict(name="session", width=20), 60 dict(name="profile"), 61 ] 62
63 - def ScanProfile(self):
64 """Scan for module using version_scan for RSDS scanning.""" 65 module_name = self.plugin_args.module.split(".")[0] 66 for _, guid in self.session.plugins.version_scan( 67 name_regex="^%s.pdb" % module_name).ScanVersions(): 68 yield obj.NoneObject(), "%s/GUID/%s" % (module_name, guid)
69
70 - def LookupIndex(self):
71 """Loookup the profile from an index.""" 72 try: 73 index = self.session.LoadProfile( 74 "%s/index" % self.plugin_args.module) 75 except ValueError: 76 return 77 78 cc = self.session.plugins.cc() 79 for session in self.session.plugins.sessions().session_spaces(): 80 # Switch the process context to this session so the address 81 # resolver can find the correctly mapped driver. 82 with cc: 83 cc.SwitchProcessContext(iter(session.processes()).next()) 84 85 # Get the image base of the win32k module. 86 image_base = self.session.address_resolver.get_address_by_name( 87 self.plugin_args.module) 88 89 for profile, _ in index.LookupIndex( 90 image_base, minimal_match=self.plugin_args.minimal_match): 91 yield self.session.GetParameter("process_context"), profile
92
93 - def GuessProfiles(self):
94 """Search for suitable profiles using a variety of methods.""" 95 # Usually this plugin is invoked from ParameterHooks which will take the 96 # first hit. So we try to do the fast methods first, then fall back to 97 # the slower methods. 98 for x in self.LookupIndex(): 99 yield x 100 101 # Looking up the index failed because it was not there, or the index did 102 # not contain the right profile - fall back to RSDS scanning. 103 for x in self.ScanProfile(): 104 yield x
105
106 - def collect(self):
107 for context, possibility in self.GuessProfiles(): 108 yield (context.pid, context.SessionId, possibility)
109
110 111 -class EProcessIndex(basic.ProfileLLP64):
112 """A profile index for _EPROCESS structs.""" 113 114 @classmethod
115 - def Initialize(cls, profile):
116 super(EProcessIndex, cls).Initialize(profile) 117 profile.add_types({ 118 '_KUSER_SHARED_DATA': [None, { 119 "NtMajorVersion": [620, ["unsigned long", {}]], 120 "NtMinorVersion": [624, ["unsigned long", {}]], 121 }] 122 })
123
124 - def LoadIndex(self, index):
125 self.index = index 126 127 # Consolidate all the relative offsets from the ImageFileName to the 128 # DirectoryTableBase. 129 self.filename_to_dtb = set() 130 for metadata in index.values(): 131 offsets = metadata["offsets"] 132 relative_offset = offsets["_EPROCESS.ImageFileName"] - ( 133 offsets["_EPROCESS.Pcb"] + 134 offsets["_KPROCESS.DirectoryTableBase"]) 135 136 arch = metadata.get("arch", "AMD64") 137 self.filename_to_dtb.add((relative_offset, arch))
138
139 140 -class TestGuessGUID(testlib.SortedComparison):
141 PARAMETERS = dict( 142 commandline="guess_guid win32k" 143 )
144