Package rekall :: Package plugins :: Package tools :: Module live_windows
[frames] | no frames]

Source Code for Module rekall.plugins.tools.live_windows

  1  #!/usr/bin/env python2 
  2   
  3  # Rekall Memory Forensics 
  4  # Copyright 2015 Google Inc. All Rights Reserved. 
  5  # 
  6  # Author: Michael Cohen scudette@google.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   
 23  __author__ = "Michael Cohen <scudette@google.com>" 
 24   
 25  """A plugin to install relevant kernel modules to enable live analysis. 
 26   
 27  The intention is to allow the user to launch: 
 28   
 29  rekall live 
 30   
 31  and have Rekall install the right kernel module and connect to the driver on all 
 32  supported operating systems. 
 33  """ 
 34  import os 
 35  import platform 
 36  import re 
 37  import win32service 
 38   
 39  from rekall import session 
 40  from rekall import resources 
 41  from rekall import plugin 
 42  from rekall import obj 
 43  from rekall.plugins.addrspaces import win32 
 44   
 45   
46 -class Live(plugin.TypedProfileCommand, 47 plugin.ProfileCommand):
48 """Launch a Rekall shell for live analysis on the current system.""" 49 50 name = "live" 51 52 PROFILE_REQUIRED = False 53 54 __args = [ 55 dict(name="mode", default="Memory", type="Choices", 56 choices=session.LIVE_MODES, 57 help="Mode for live analysis."), 58 59 dict(name="driver", 60 help="Driver file to load"), 61 62 dict(name="device", default=r"\\.\pmem", 63 help="Device name to use"), 64 65 dict(name="service_name", default=r"pmem", 66 help="Service name to use") 67 ] 68 69 table_header = [ 70 dict(name="Message") 71 ] 72
73 - def __init__(self, *args, **kw):
74 super(Live, self).__init__(*args, **kw) 75 # It is OK for non privileged sessions to use the default drivers. 76 if not self.session.privileged and self.plugin_args.driver: 77 raise plugin.PluginError( 78 "Installing arbitrary drivers is only available for " 79 "interactive or privileged sessions.") 80 81 # Did we start the service? If so we need to clean up. 82 self.we_started_service = False 83 self.hScm = None 84 self.hSvc = None
85 86 exception_format_regex = re.compile(r": \((\d+),")
87 - def parse_exception(self, e):
88 """Yes! seriously there is no way to get at the real error code.""" 89 # We often see code like if "Access Denied" in str(e):... but 90 # this is unreliable since the message will be different when 91 # different language packs are used. The best way is to 92 # compare the numeric error code, but this is not exported. In 93 # our testing e.errno is not being set properly by pywin32. 94 m = self.exception_format_regex.search(str(e)) 95 if m: 96 return int(m.group(1))
97
98 - def load_driver(self):
99 """Load the driver if possible.""" 100 # Check the driver is somewhere accessible. 101 if self.plugin_args.driver is None: 102 # Valid values 103 # http://superuser.com/questions/305901/possible-values-of-processor-architecture 104 machine = platform.machine() 105 if machine == "AMD64": 106 driver = "winpmem_x64.sys" 107 elif machine == "x86": 108 driver = "winpmem_x86.sys" 109 else: 110 raise plugin.PluginError("Unsupported architecture") 111 112 self.plugin_args.driver = resources.get_resource( 113 "WinPmem/%s" % driver) 114 115 # Try the local directory 116 if self.plugin_args.driver is None: 117 self.plugin_args.driver = os.path.join( 118 os.getcwd(), "WinPmem", driver) 119 120 self.session.logging.debug("Loading driver from %s", 121 self.plugin_args.driver) 122 123 if not os.access(self.plugin_args.driver, os.R_OK): 124 raise plugin.PluginError( 125 "Driver file %s is not accessible." % self.plugin_args.driver) 126 127 self.hScm = win32service.OpenSCManager( 128 None, None, win32service.SC_MANAGER_CREATE_SERVICE) 129 130 # First uninstall the driver 131 self.remove_service(also_close_as=False) 132 133 try: 134 self.hSvc = win32service.CreateService( 135 self.hScm, self.plugin_args.service_name, 136 self.plugin_args.service_name, 137 win32service.SERVICE_ALL_ACCESS, 138 win32service.SERVICE_KERNEL_DRIVER, 139 win32service.SERVICE_DEMAND_START, 140 win32service.SERVICE_ERROR_IGNORE, 141 self.plugin_args.driver, 142 None, 0, None, None, None) 143 144 self.session.logging.debug("Created service %s", 145 self.plugin_args.service_name) 146 # Remember to cleanup afterwards. 147 self.we_started_service = True 148 149 except win32service.error as e: 150 # Service is already there, try to open it instead. 151 self.hSvc = win32service.OpenService( 152 self.hScm, self.plugin_args.service_name, 153 win32service.SERVICE_ALL_ACCESS) 154 155 # Make sure the service is stopped. 156 try: 157 win32service.ControlService( 158 self.hSvc, win32service.SERVICE_CONTROL_STOP) 159 except win32service.error: 160 pass 161 162 try: 163 win32service.StartService(self.hSvc, []) 164 except win32service.error, e: 165 self.session.logging.debug("%s: will try to continue", e) 166 167 try: 168 return win32.WinPmemAddressSpace( 169 session=self.session, filename=self.plugin_args.device) 170 except IOError as e: 171 raise plugin.PluginError(*e.args)
172
173 - def live(self):
174 if self.plugin_args.mode == "Memory": 175 phys_as = obj.NoneObject("Unable to access physical memory") 176 try: 177 phys_as = win32.WinPmemAddressSpace( 178 session=self.session, filename=self.plugin_args.device) 179 self.session.logging.debug("Using PMEM driver at %s", 180 self.plugin_args.device) 181 except IOError as e: 182 self.session.logging.debug("%s", e) 183 errno = self.parse_exception(e) 184 if errno == 5: # Access Denied. 185 self.session.logging.error( 186 "%s. Are you running as Administrator?" % e) 187 188 elif errno == 2: # File not found 189 try: 190 phys_as = self.load_driver() 191 except plugin.PluginError: 192 self.session.logging.error( 193 "Unable to load driver: %s." % e) 194 195 else: 196 self.session.logging.error( 197 "Unable to access physical memory: %s." % e) 198 199 self.session.physical_address_space = phys_as 200 201 with self.session: 202 self.session.SetParameter("live_mode", self.plugin_args.mode) 203 self.session.SetParameter("session_name", "Live (%s)" % 204 self.plugin_args.mode)
205
206 - def remove_service(self, also_close_as=True):
207 self.session.logging.debug("Removing service %s", 208 self.plugin_args.service_name) 209 210 # Make sure the handle is closed. 211 if also_close_as: 212 self.session.physical_address_space.close() 213 214 # Stop the service if it's running. 215 if not self.hSvc: 216 try: 217 self.hSvc = win32service.OpenService( 218 self.hScm, self.plugin_args.service_name, 219 win32service.SERVICE_ALL_ACCESS) 220 except win32service.error: 221 self.session.logging.debug("%s service does not exist.", 222 self.plugin_args.service_name) 223 224 if self.hSvc: 225 self.session.logging.debug("Stopping service: %s", 226 self.plugin_args.service_name) 227 try: 228 win32service.ControlService( 229 self.hSvc, win32service.SERVICE_CONTROL_STOP) 230 except win32service.error as e: 231 self.session.logging.debug("Error stopping service: %s", e) 232 233 self.session.logging.debug("Deleting service: %s", 234 self.plugin_args.service_name) 235 try: 236 win32service.DeleteService(self.hSvc) 237 except win32service.error as e: 238 self.session.logging.debug("Error deleting service: %s", e) 239 240 win32service.CloseServiceHandle(self.hSvc)
241
242 - def close(self):
243 if self.we_started_service: 244 self.remove_service()
245
246 - def __enter__(self):
247 self.live() 248 return self
249
250 - def __exit__(self, exc_type, exc_value, trace):
251 self.close()
252
253 - def collect(self):
254 yield ("Launching live memory analysis\n",) 255 try: 256 self.live() 257 258 renderer = self.session.GetRenderer() 259 260 # Launch the shell. 261 shell = self.session.plugins.shell() 262 shell.render(renderer) 263 finally: 264 self.close()
265