Package rekall :: Package plugins :: Package windows :: Package registry :: Module printkey
[frames] | no frames]

Source Code for Module rekall.plugins.windows.registry.printkey

  1  # Rekall Memory Forensics 
  2  # Copyright (C) 2012 Michael Cohen <scudette@gmail.com> 
  3  # Copyright (c) 2008 Brendan Dolan-Gavitt <bdolangavitt@wesleyan.edu> 
  4  # Copyright 2013 Google Inc. All Rights Reserved. 
  5  # 
  6  # This program is free software; you can redistribute it and/or modify 
  7  # it under the terms of the GNU General Public License as published by 
  8  # the Free Software Foundation; either version 2 of the License, or (at 
  9  # your option) any later version. 
 10  # 
 11  # This program is distributed in the hope that it will be useful, but 
 12  # WITHOUT ANY WARRANTY; without even the implied warranty of 
 13  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 
 14  # General Public License for more details. 
 15  # 
 16  # You should have received a copy of the GNU General Public License 
 17  # along with this program; if not, write to the Free Software 
 18  # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 
 19  # 
 20   
 21  """ 
 22  @author:       Michael Cohen <scudette@gmail.com> 
 23  @author:       AAron Walters and Brendan Dolan-Gavitt 
 24  @license:      GNU General Public License 2.0 or later 
 25  @contact:      awalters@volatilesystems.com,bdolangavitt@wesleyan.edu 
 26  @organization: Volatile Systems 
 27  """ 
 28  import re 
 29   
 30  from rekall import addrspace 
 31  from rekall.plugins import core 
 32  from rekall.plugins.windows.registry import registry 
 33  from rekall.plugins.overlays import basic 
 34  from rekall_lib import utils 
35 36 37 -class PrintKey(registry.RegistryPlugin):
38 """Print a registry key, and its subkeys and values""" 39 __name = "printkey" 40 41 @classmethod
42 - def args(cls, parser):
43 """Declare the command line args we need.""" 44 super(PrintKey, cls).args(parser) 45 46 parser.add_argument("-k", "--key", default="", 47 help="Registry key to print.") 48 49 parser.add_argument("-r", "--recursive", default=False, 50 type="Boolean", 51 help='If set print the entire subtree.')
52 53
54 - def __init__(self, key="", recursive=False, **kwargs):
55 """Print all keys and values contained by a registry key. 56 57 Args: 58 key: The key name to list. If not provided we list the root key in the 59 hive. 60 61 recursive: If set print the entire subtree. 62 """ 63 super(PrintKey, self).__init__(**kwargs) 64 self.key = key 65 self.recursive = recursive
66
67 - def _list_keys(self, key=None):
68 yield key 69 70 if self.recursive: 71 for subkey in key.subkeys(): 72 for subkey in self._list_keys(subkey): 73 yield subkey
74
75 - def list_keys(self):
76 """Return the keys that match.""" 77 seen = set() 78 for hive_offset in self.hive_offsets: 79 reg = registry.RegistryHive( 80 profile=self.profile, session=self.session, 81 kernel_address_space=self.kernel_address_space, 82 hive_offset=hive_offset) 83 84 key = reg.open_key(self.key) 85 for subkey in self._list_keys(key): 86 if subkey in seen: 87 break 88 89 seen.add(subkey) 90 91 yield reg, subkey
92
93 - def voltext(self, key):
94 """Returns a string representing (S)table or (V)olatile keys.""" 95 return "(V)" if key.obj_offset & 0x80000000 else "(S)"
96
97 - def render(self, renderer):
98 renderer.format("Legend: (S) = Stable (V) = Volatile\n\n") 99 for reg, key in self.list_keys(): 100 self.session.report_progress( 101 "Printing %s", lambda key=key: key.Path) 102 103 if key: 104 renderer.format("----------------------------\n") 105 renderer.format("Registry: {0}\n", reg.Name) 106 renderer.format("Key name: {0} {1} @ {2:addrpad}\n", key.Name, 107 self.voltext(key), key.obj_vm.vtop(int(key))) 108 109 renderer.format("Last updated: {0}\n", key.LastWriteTime) 110 renderer.format("\n") 111 renderer.format("Subkeys:\n") 112 113 for subkey in key.subkeys(): 114 if not subkey.Name: 115 renderer.format( 116 " Unknown subkey: {0}\n", subkey.Name.reason) 117 else: 118 renderer.format(u" {1} {0}\n", 119 subkey.Name, self.voltext(subkey)) 120 121 renderer.format("\n") 122 renderer.format("Values:\n") 123 for value in key.values(): 124 renderer.format("{0:addrpad} ", value.obj_vm.vtop(value)) 125 if value.Type == 'REG_BINARY': 126 data = value.DecodedData 127 if isinstance(data, basestring): 128 renderer.format( 129 u"{0:width=13} {1:width=15} : {2}\n", 130 value.Type, value.Name, self.voltext(value)) 131 utils.WriteHexdump(renderer, value.DecodedData) 132 else: 133 renderer.format( 134 u"{0:width=13} {1:width=15} : {2} {3}\n", 135 value.Type, value.Name, self.voltext(value), 136 utils.SmartUnicode(value.DecodedData).strip())
137
138 139 -class RegDump(core.DirectoryDumperMixin, registry.RegistryPlugin):
140 """Dump all registry hives from memory into a dump directory.""" 141 142 __name = 'regdump' 143
144 - def dump_hive(self, hive_offset=None, reg=None, fd=None):
145 """Write the hive into the fd. 146 147 Args: 148 hive_offset: The virtual offset where the hive is located. 149 reg: Optionally an instance of registry.Registry helper. If provided 150 hive_offset is ignored. 151 fd: The file like object we write to. 152 """ 153 if reg is None: 154 reg = registry.RegistryHive( 155 profile=self.profile, 156 kernel_address_space=self.kernel_address_space, 157 hive_offset=hive_offset) 158 159 count = 0 160 for data in reg.address_space.save(): 161 fd.write(data) 162 count += len(data) 163 self.session.report_progress( 164 "Dumping {0}Mb".format(count/1024/1024))
165
166 - def render(self, renderer):
167 # Get all the offsets if needed. 168 for hive_offset in self.hive_offsets: 169 reg = registry.RegistryHive( 170 profile=self.profile, session=self.session, 171 kernel_address_space=self.kernel_address_space, 172 hive_offset=hive_offset) 173 174 # Make up a filename for it, should be similar to the hive name. 175 filename = reg.Name.rsplit("\\", 1).pop() 176 177 # Sanitize it. 178 filename = re.sub(r"[^a-zA-Z0-9_\-@ ]", "_", filename) 179 180 # Make up the path. 181 renderer.section() 182 renderer.format("Dumping {0} into \"{1}\"\n", reg.Name, filename) 183 184 with renderer.open(directory=self.dump_dir, 185 filename=filename, 186 mode="wb") as fd: 187 self.dump_hive(reg=reg, fd=fd) 188 renderer.format("Dumped {0} bytes\n", fd.tell())
189
190 191 192 -class HiveDump(registry.RegistryPlugin):
193 """Prints out a hive""" 194 195 __name = "hivedump" 196
197 - def _key_iterator(self, key, seen):
198 yield key 199 200 if key in seen: 201 return 202 203 seen.add(key) 204 205 for subkey in key.subkeys(): 206 for subsubkey in self._key_iterator(subkey, seen): 207 yield subsubkey
208
209 - def render(self, renderer):
210 seen = set() 211 212 for hive_offset in self.hive_offsets: 213 reg = registry.RegistryHive( 214 hive_offset=hive_offset, session=self.session, 215 kernel_address_space=self.kernel_address_space, 216 profile=self.profile) 217 218 renderer.section() 219 renderer.format("Hive {0}\n\n", reg.Name) 220 221 renderer.table_header([("Last Written", "timestamp", "<24"), 222 ("Key", "key", "")]) 223 224 for key in self._key_iterator(reg.root, seen): 225 renderer.table_row(key.LastWriteTime, key.Path)
226 227 228 # Special types to parse the SAM data structures. 229 sam_vtypes = { 230 "UNICODE_STRING": [12, { 231 "offset": [0, ["unsigned int"]], 232 "len": [4, ["unsigned int"]], 233 "Value": lambda x: x.obj_profile.UnicodeString( 234 offset=x.offset+0xCC, 235 length=x.len, vm=x.obj_vm), 236 237 }], 238 239 "Hash": [12, { 240 "offset": [0, ["unsigned int"]], 241 "len": [4, ["unsigned int"]], 242 "Value": lambda x: x.obj_vm.read( 243 x.offset+0xCC, x.len).encode("hex"), 244 245 }], 246 247 "V": [None, { 248 "Type": [4, ["Enumeration", dict( 249 choices={ 250 0xBC: "Default Admin User", 251 0xd4: "Custom Limited Acct", 252 0xb0: "Default Guest Acct" 253 }, 254 target="unsigned int" 255 )]], 256 "UserName": [12, ['UNICODE_STRING']], 257 "FullName": [24, ['UNICODE_STRING']], 258 "Comment": [36, ['UNICODE_STRING']], 259 "LanHash": [156, ['Hash']], 260 "NTHash": [168, ['Hash']], 261 }], 262 263 "F": [None, { 264 "LastLoginTime": [8, ['WinFileTime']], 265 "PwdResetDate": [24, ["WinFileTime"]], 266 "AccountExpiration": [32, ["WinFileTime"]], 267 "PasswordFailedTime": [40, ["WinFileTime"]], 268 "LoginCount": [66, ["unsigned short int"]], 269 "FailedLoginCount": [64, ["unsigned short int"]], 270 "Rid": [48, ["unsigned int"]], 271 "Flags": [56, ["Flags", dict( 272 maskmap=utils.Invert({ 273 0x0001: "Account Disabled", 274 0x0002: "Home directory required", 275 0x0004: "Password not required", 276 0x0008: "Temporary duplicate account", 277 0x0010: "Normal user account", 278 0x0020: "MNS logon user account", 279 0x0040: "Interdomain trust account", 280 0x0080: "Workstation trust account", 281 0x0100: "Server trust account", 282 0x0200: "Password does not expire", 283 0x0400: "Account auto locked" 284 }), 285 target="unsigned short int" 286 )]], 287 }], 288 }
289 290 291 292 -class SAMProfile(basic.Profile32Bits, basic.BasicClasses):
293 """A profile to parse the SAM.""" 294 295 @classmethod
296 - def Initialize(cls, profile):
300
301 302 -class Users(registry.RegistryPlugin):
303 """Enumerate all users of this system. 304 305 Ref: 306 samparse.pl from RegRipper. 307 308 # copyright 2012 Quantum Analytics Research, LLC 309 # Author: H. Carvey, keydet89@yahoo.com 310 """ 311 name = "users" 312
313 - def GenerateUsers(self):
314 """Generates User RID keys, V and F structs for all users.""" 315 sam_profile = SAMProfile(session=self.session) 316 317 for hive_offset in self.hive_offsets: 318 reg = registry.RegistryHive( 319 hive_offset=hive_offset, session=self.session, 320 kernel_address_space=self.kernel_address_space, 321 profile=self.profile) 322 323 users = reg.open_key("SAM/Domains/Account/Users") 324 for user_rid in users.subkeys(): 325 # The V value holds the information we are after. 326 v_data = user_rid.open_value("V") 327 if not v_data: 328 continue 329 330 v = sam_profile.V(vm=addrspace.BufferAddressSpace( 331 data=v_data.DecodedData, session=self.session)) 332 333 f_data = user_rid.open_value("F") 334 f = sam_profile.F(vm=addrspace.BufferAddressSpace( 335 data=f_data.DecodedData, session=self.session)) 336 337 yield user_rid, v, f
338
339 - def render(self, renderer):
340 for user_rid, v, f in self.GenerateUsers(): 341 renderer.section() 342 renderer.format("Key {0} \n\n", user_rid.Path) 343 renderer.table_header( 344 columns=[("", "property", "20"), 345 ("", "value", "")], 346 suppress_headers=True) 347 348 for field in v.members: 349 try: 350 renderer.table_row(field, getattr(v, field).Value) 351 except AttributeError: 352 renderer.table_row(field, getattr(v, field)) 353 354 for field in f.members: 355 renderer.table_row(field, getattr(f, field))
356
357 358 -class Services(registry.RegistryPlugin):
359 """Enumerate all services.""" 360 name = "services" 361 362 # http://msdn.microsoft.com/en-us/library/windows/desktop/ms682450(v=vs.85).aspx 363 # CreateService function. 364 SERVICE_TYPE = { 365 0x00000004: 'SERVICE_ADAPTER', 366 0x00000002: 'SERVICE_FILE_SYSTEM_DRIVER', 367 0x00000001: 'SERVICE_KERNEL_DRIVER', 368 0x00000008: 'SERVICE_RECOGNIZER_DRIVER', 369 0x00000010: 'SERVICE_WIN32_OWN_PROCESS', 370 0x00000020: 'SERVICE_WIN32_SHARE_PROCESS' 371 } 372 373 START_TYPE = { 374 0x00000002: 'SERVICE_AUTO_START', 375 0x00000000: 'SERVICE_BOOT_START', 376 0x00000003: 'SERVICE_DEMAND_START', 377 0x00000004: 'SERVICE_DISABLED', 378 0x00000001: 'SERVICE_SYSTEM_START' 379 } 380 381 ERROR_CONTROL = { 382 0x00000003: 'SERVICE_ERROR_CRITICAL', 383 0x00000000: 'SERVICE_ERROR_IGNORE', 384 0x00000001: 'SERVICE_ERROR_NORMAL', 385 0x00000002: 'SERVICE_ERROR_SEVERE' 386 } 387
388 - def GenerateServices(self):
389 for hive_offset in self.hive_offsets: 390 reg = registry.RegistryHive( 391 profile=self.profile, session=self.session, 392 kernel_address_space=self.kernel_address_space, 393 hive_offset=hive_offset) 394 395 for service in reg.CurrentControlSet().open_subkey( 396 "Services").subkeys(): 397 yield service
398
399 - def render(self, renderer):
400 for service in self.GenerateServices(): 401 renderer.section(service.Name.v()) 402 renderer.table_header([("Key", "key", "20"), 403 ("Value", "value", "[wrap:60]")], 404 suppress_headers=True) 405 406 for value in service.values(): 407 k = value.Name.v() 408 v = value.DecodedData 409 if value.Type == "REG_BINARY": 410 continue 411 412 if isinstance(v, list): 413 v = ",".join([x for x in v if x]) 414 415 if k == "Type": 416 v = self.SERVICE_TYPE.get(v, v) 417 418 if k == "Start": 419 v = self.START_TYPE.get(v, v) 420 421 if k == "ErrorControl": 422 v = self.ERROR_CONTROL.get(v, v) 423 424 renderer.table_row(k, v)
425