Package winappdbg :: Module registry
[hide private]
[frames] | no frames]

Source Code for Module winappdbg.registry

  1  #!~/.wine/drive_c/Python25/python.exe 
  2  # -*- coding: utf-8 -*- 
  3   
  4  # Copyright (c) 2009-2014, Mario Vilas 
  5  # All rights reserved. 
  6  # 
  7  # Redistribution and use in source and binary forms, with or without 
  8  # modification, are permitted provided that the following conditions are met: 
  9  # 
 10  #     * Redistributions of source code must retain the above copyright notice, 
 11  #       this list of conditions and the following disclaimer. 
 12  #     * Redistributions in binary form must reproduce the above copyright 
 13  #       notice,this list of conditions and the following disclaimer in the 
 14  #       documentation and/or other materials provided with the distribution. 
 15  #     * Neither the name of the copyright holder nor the names of its 
 16  #       contributors may be used to endorse or promote products derived from 
 17  #       this software without specific prior written permission. 
 18  # 
 19  # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
 20  # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
 21  # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
 22  # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
 23  # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
 24  # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
 25  # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
 26  # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
 27  # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
 28  # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
 29  # POSSIBILITY OF SUCH DAMAGE. 
 30   
 31  """ 
 32  Registry access. 
 33   
 34  @group Instrumentation: 
 35      Registry, RegistryKey 
 36  """ 
 37   
 38  from __future__ import with_statement 
 39   
 40  __revision__ = "$Id: registry.py 1299 2013-12-20 09:30:55Z qvasimodo $" 
 41   
 42  __all__ = ['Registry'] 
 43   
 44  import win32 
 45  import collections 
 46  import warnings 
47 48 #============================================================================== 49 50 -class _RegistryContainer (object):
51 """ 52 Base class for L{Registry} and L{RegistryKey}. 53 """ 54 55 # Dummy object to detect empty arguments.
56 - class __EmptyArgument:
57 pass
58 __emptyArgument = __EmptyArgument() 59
60 - def __init__(self):
61 self.__default = None
62
63 - def has_key(self, name):
64 return name in self
65
66 - def get(self, name, default=__emptyArgument):
67 try: 68 return self[name] 69 except KeyError: 70 if default is RegistryKey.__emptyArgument: 71 return self.__default 72 return default
73
74 - def setdefault(self, default):
75 self.__default = default
76
77 - def __iter__(self):
78 return self.iterkeys()
79
80 #============================================================================== 81 82 -class RegistryKey (_RegistryContainer):
83 """ 84 Exposes a single Windows Registry key as a dictionary-like object. 85 86 @see: L{Registry} 87 88 @type path: str 89 @ivar path: Registry key path. 90 91 @type handle: L{win32.RegistryKeyHandle} 92 @ivar handle: Registry key handle. 93 """ 94
95 - def __init__(self, path, handle):
96 """ 97 @type path: str 98 @param path: Registry key path. 99 100 @type handle: L{win32.RegistryKeyHandle} 101 @param handle: Registry key handle. 102 """ 103 super(RegistryKey, self).__init__() 104 if path.endswith('\\'): 105 path = path[:-1] 106 self._path = path 107 self._handle = handle
108 109 @property
110 - def path(self):
111 return self._path
112 113 @property
114 - def handle(self):
115 #if not self._handle: 116 # msg = "This Registry key handle has already been closed." 117 # raise RuntimeError(msg) 118 return self._handle
119 120 #def close(self): 121 # """ 122 # Close the Registry key handle, freeing its resources. It cannot be 123 # used again after calling this method. 124 # 125 # @note: This method will be called automatically by the garbage 126 # collector, and upon exiting a "with" block. 127 # 128 # @raise RuntimeError: This Registry key handle has already been closed. 129 # """ 130 # self.handle.close() 131 # 132 #def __enter__(self): 133 # """ 134 # Compatibility with the "C{with}" Python statement. 135 # """ 136 # return self 137 # 138 #def __exit__(self, type, value, traceback): 139 # """ 140 # Compatibility with the "C{with}" Python statement. 141 # """ 142 # try: 143 # self.close() 144 # except Exception: 145 # pass 146
147 - def __contains__(self, name):
148 try: 149 win32.RegQueryValueEx(self.handle, name, False) 150 return True 151 except WindowsError, e: 152 if e.winerror == win32.ERROR_FILE_NOT_FOUND: 153 return False 154 raise
155
156 - def __getitem__(self, name):
157 try: 158 return win32.RegQueryValueEx(self.handle, name)[0] 159 except WindowsError, e: 160 if e.winerror == win32.ERROR_FILE_NOT_FOUND: 161 raise KeyError(name) 162 raise
163
164 - def __setitem__(self, name, value):
166
167 - def __delitem__(self, name):
169
170 - def iterkeys(self):
171 handle = self.handle 172 index = 0 173 while 1: 174 resp = win32.RegEnumValue(handle, index, False) 175 if resp is None: 176 break 177 yield resp[0] 178 index += 1
179
180 - def itervalues(self):
181 handle = self.handle 182 index = 0 183 while 1: 184 resp = win32.RegEnumValue(handle, index) 185 if resp is None: 186 break 187 yield resp[2] 188 index += 1
189
190 - def iteritems(self):
191 handle = self.handle 192 index = 0 193 while 1: 194 resp = win32.RegEnumValue(handle, index) 195 if resp is None: 196 break 197 yield resp[0], resp[2] 198 index += 1
199
200 - def keys(self):
201 # return list(self.iterkeys()) # that can't be optimized by psyco 202 handle = self.handle 203 keys = list() 204 index = 0 205 while 1: 206 resp = win32.RegEnumValue(handle, index, False) 207 if resp is None: 208 break 209 keys.append(resp[0]) 210 index += 1 211 return keys
212
213 - def values(self):
214 # return list(self.itervalues()) # that can't be optimized by psyco 215 handle = self.handle 216 values = list() 217 index = 0 218 while 1: 219 resp = win32.RegEnumValue(handle, index) 220 if resp is None: 221 break 222 values.append(resp[2]) 223 index += 1 224 return values
225
226 - def items(self):
227 # return list(self.iteritems()) # that can't be optimized by psyco 228 handle = self.handle 229 items = list() 230 index = 0 231 while 1: 232 resp = win32.RegEnumValue(handle, index) 233 if resp is None: 234 break 235 items.append( (resp[0], resp[2]) ) 236 index += 1 237 return items
238
239 - def get_value_type(self, name):
240 """ 241 Retrieves the low-level data type for the given value. 242 243 @type name: str 244 @param name: Registry value name. 245 246 @rtype: int 247 @return: One of the following constants: 248 - L{win32.REG_NONE} (0) 249 - L{win32.REG_SZ} (1) 250 - L{win32.REG_EXPAND_SZ} (2) 251 - L{win32.REG_BINARY} (3) 252 - L{win32.REG_DWORD} (4) 253 - L{win32.REG_DWORD_BIG_ENDIAN} (5) 254 - L{win32.REG_LINK} (6) 255 - L{win32.REG_MULTI_SZ} (7) 256 - L{win32.REG_RESOURCE_LIST} (8) 257 - L{win32.REG_FULL_RESOURCE_DESCRIPTOR} (9) 258 - L{win32.REG_RESOURCE_REQUIREMENTS_LIST} (10) 259 - L{win32.REG_QWORD} (11) 260 261 @raise KeyError: The specified value could not be found. 262 """ 263 try: 264 return win32.RegQueryValueEx(self.handle, name)[1] 265 except WindowsError, e: 266 if e.winerror == win32.ERROR_FILE_NOT_FOUND: 267 raise KeyError(name) 268 raise
269
270 - def clear(self):
271 handle = self.handle 272 while 1: 273 resp = win32.RegEnumValue(handle, 0, False) 274 if resp is None: 275 break 276 win32.RegDeleteValue(handle, resp[0])
277
278 - def __str__(self):
279 default = self[''] 280 return str(default)
281
282 - def __unicode__(self):
283 default = self[u''] 284 return unicode(default)
285
286 - def __repr__(self):
287 return '<Registry key: "%s">' % self._path
288
289 - def iterchildren(self):
290 """ 291 Iterates the subkeys for this Registry key. 292 293 @rtype: iter of L{RegistryKey} 294 @return: Iterator of subkeys. 295 """ 296 handle = self.handle 297 index = 0 298 while 1: 299 subkey = win32.RegEnumKey(handle, index) 300 if subkey is None: 301 break 302 yield self.child(subkey) 303 index += 1
304
305 - def children(self):
306 """ 307 Returns a list of subkeys for this Registry key. 308 309 @rtype: list(L{RegistryKey}) 310 @return: List of subkeys. 311 """ 312 # return list(self.iterchildren()) # that can't be optimized by psyco 313 handle = self.handle 314 result = [] 315 index = 0 316 while 1: 317 subkey = win32.RegEnumKey(handle, index) 318 if subkey is None: 319 break 320 result.append( self.child(subkey) ) 321 index += 1 322 return result
323
324 - def child(self, subkey):
325 """ 326 Retrieves a subkey for this Registry key, given its name. 327 328 @type subkey: str 329 @param subkey: Name of the subkey. 330 331 @rtype: L{RegistryKey} 332 @return: Subkey. 333 """ 334 path = self._path + '\\' + subkey 335 handle = win32.RegOpenKey(self.handle, subkey) 336 return RegistryKey(path, handle)
337
338 - def flush(self):
339 """ 340 Flushes changes immediately to disk. 341 342 This method is normally not needed, as the Registry writes changes 343 to disk by itself. This mechanism is provided to ensure the write 344 happens immediately, as opposed to whenever the OS wants to. 345 346 @warn: Calling this method too often may degrade performance. 347 """ 348 win32.RegFlushKey(self.handle)
349
350 #============================================================================== 351 352 # TODO: possibly cache the RegistryKey objects 353 # to avoid opening and closing handles many times on code sequences like this: 354 # 355 # r = Registry() 356 # r['HKLM\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Run']['Example 1'] = 'example1.exe' 357 # r['HKLM\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Run']['Example 2'] = 'example2.exe' 358 # r['HKLM\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Run']['Example 3'] = 'example3.exe' 359 360 # TODO: support for access flags? 361 # TODO: should be possible to disable the safety checks (see __delitem__) 362 363 # TODO: workaround for an API bug described by a user in MSDN 364 # 365 # http://msdn.microsoft.com/en-us/library/windows/desktop/aa379776(v=vs.85).aspx 366 # 367 # Apparently RegDeleteTree won't work remotely from Win7 to WinXP, and the only 368 # solution is to recursively call RegDeleteKey. 369 370 -class Registry (_RegistryContainer):
371 """ 372 Exposes the Windows Registry as a Python container. 373 374 @type machine: str or None 375 @ivar machine: For a remote Registry, the machine name. 376 For a local Registry, the value is C{None}. 377 """ 378 379 _hives_by_name = { 380 381 # Short names 382 'HKCR' : win32.HKEY_CLASSES_ROOT, 383 'HKCU' : win32.HKEY_CURRENT_USER, 384 'HKLM' : win32.HKEY_LOCAL_MACHINE, 385 'HKU' : win32.HKEY_USERS, 386 'HKPD' : win32.HKEY_PERFORMANCE_DATA, 387 'HKCC' : win32.HKEY_CURRENT_CONFIG, 388 389 # Long names 390 'HKEY_CLASSES_ROOT' : win32.HKEY_CLASSES_ROOT, 391 'HKEY_CURRENT_USER' : win32.HKEY_CURRENT_USER, 392 'HKEY_LOCAL_MACHINE' : win32.HKEY_LOCAL_MACHINE, 393 'HKEY_USERS' : win32.HKEY_USERS, 394 'HKEY_PERFORMANCE_DATA' : win32.HKEY_PERFORMANCE_DATA, 395 'HKEY_CURRENT_CONFIG' : win32.HKEY_CURRENT_CONFIG, 396 } 397 398 _hives_by_value = { 399 win32.HKEY_CLASSES_ROOT : 'HKEY_CLASSES_ROOT', 400 win32.HKEY_CURRENT_USER : 'HKEY_CURRENT_USER', 401 win32.HKEY_LOCAL_MACHINE : 'HKEY_LOCAL_MACHINE', 402 win32.HKEY_USERS : 'HKEY_USERS', 403 win32.HKEY_PERFORMANCE_DATA : 'HKEY_PERFORMANCE_DATA', 404 win32.HKEY_CURRENT_CONFIG : 'HKEY_CURRENT_CONFIG', 405 } 406 407 _hives = sorted(_hives_by_value.itervalues()) 408
409 - def __init__(self, machine = None):
410 """ 411 Opens a local or remote registry. 412 413 @type machine: str 414 @param machine: Optional machine name. If C{None} it opens the local 415 registry. 416 """ 417 self._machine = machine 418 self._remote_hives = {}
419 420 @property
421 - def machine(self):
422 return self._machine
423
424 - def _split_path(self, path):
425 """ 426 Splits a Registry path and returns the hive and key. 427 428 @type path: str 429 @param path: Registry path. 430 431 @rtype: tuple( int, str ) 432 @return: Tuple containing the hive handle and the subkey path. 433 The hive handle is always one of the following integer constants: 434 - L{win32.HKEY_CLASSES_ROOT} 435 - L{win32.HKEY_CURRENT_USER} 436 - L{win32.HKEY_LOCAL_MACHINE} 437 - L{win32.HKEY_USERS} 438 - L{win32.HKEY_PERFORMANCE_DATA} 439 - L{win32.HKEY_CURRENT_CONFIG} 440 """ 441 if '\\' in path: 442 p = path.find('\\') 443 hive = path[:p] 444 path = path[p+1:] 445 else: 446 hive = path 447 path = None 448 handle = self._hives_by_name[ hive.upper() ] 449 return handle, path
450
451 - def _parse_path(self, path):
452 """ 453 Parses a Registry path and returns the hive and key. 454 455 @type path: str 456 @param path: Registry path. 457 458 @rtype: tuple( int, str ) 459 @return: Tuple containing the hive handle and the subkey path. 460 For a local Registry, the hive handle is an integer. 461 For a remote Registry, the hive handle is a L{RegistryKeyHandle}. 462 """ 463 handle, path = self._split_path(path) 464 if self._machine is not None: 465 handle = self._connect_hive(handle) 466 return handle, path
467
468 - def _join_path(self, hive, subkey):
469 """ 470 Joins the hive and key to make a Registry path. 471 472 @type hive: int 473 @param hive: Registry hive handle. 474 The hive handle must be one of the following integer constants: 475 - L{win32.HKEY_CLASSES_ROOT} 476 - L{win32.HKEY_CURRENT_USER} 477 - L{win32.HKEY_LOCAL_MACHINE} 478 - L{win32.HKEY_USERS} 479 - L{win32.HKEY_PERFORMANCE_DATA} 480 - L{win32.HKEY_CURRENT_CONFIG} 481 482 @type subkey: str 483 @param subkey: Subkey path. 484 485 @rtype: str 486 @return: Registry path. 487 """ 488 path = self._hives_by_value[hive] 489 if subkey: 490 path = path + '\\' + subkey 491 return path
492
493 - def _sanitize_path(self, path):
494 """ 495 Sanitizes the given Registry path. 496 497 @type path: str 498 @param path: Registry path. 499 500 @rtype: str 501 @return: Registry path. 502 """ 503 return self._join_path( *self._split_path(path) )
504
505 - def _connect_hive(self, hive):
506 """ 507 Connect to the specified hive of a remote Registry. 508 509 @note: The connection will be cached, to close all connections and 510 erase this cache call the L{close} method. 511 512 @type hive: int 513 @param hive: Hive to connect to. 514 515 @rtype: L{win32.RegistryKeyHandle} 516 @return: Open handle to the remote Registry hive. 517 """ 518 try: 519 handle = self._remote_hives[hive] 520 except KeyError: 521 handle = win32.RegConnectRegistry(self._machine, hive) 522 self._remote_hives[hive] = handle 523 return handle
524
525 - def close(self):
526 """ 527 Closes all open connections to the remote Registry. 528 529 No exceptions are raised, even if an error occurs. 530 531 This method has no effect when opening the local Registry. 532 533 The remote Registry will still be accessible after calling this method 534 (new connections will be opened automatically on access). 535 """ 536 while self._remote_hives: 537 hive = self._remote_hives.popitem()[1] 538 try: 539 hive.close() 540 except Exception, e: 541 try: 542 msg = "Cannot close registry hive handle %s, reason: %s" 543 msg %= (hive.value, str(e)) 544 warnings.warn(msg) 545 except Exception: 546 pass
547
548 - def __enter__(self):
549 return self
550
551 - def __exit__(self, exc_type, exc_value, traceback):
552 self.close()
553
554 - def __repr__(self):
555 if self._machine: 556 return '<Remote Registry at "%s">' % self._machine 557 return '<Local Registry>'
558
559 - def __contains__(self, path):
560 hive, subpath = self._parse_path(path) 561 try: 562 with win32.RegOpenKey(hive, subpath): 563 return True 564 except WindowsError, e: 565 if e.winerror == win32.ERROR_FILE_NOT_FOUND: 566 return False 567 raise
568
569 - def __getitem__(self, path):
570 path = self._sanitize_path(path) 571 hive, subpath = self._parse_path(path) 572 try: 573 handle = win32.RegOpenKey(hive, subpath) 574 except WindowsError, e: 575 if e.winerror == win32.ERROR_FILE_NOT_FOUND: 576 raise KeyError(path) 577 raise 578 return RegistryKey(path, handle)
579
580 - def __setitem__(self, path, value):
581 do_copy = isinstance(value, RegistryKey) 582 if not do_copy and not isinstance(value, str) \ 583 and not isinstance(value, unicode): 584 if isinstance(value, object): 585 t = value.__class__.__name__ 586 else: 587 t = type(value) 588 raise TypeError("Expected string or RegistryKey, got %s" % t) 589 hive, subpath = self._parse_path(path) 590 with win32.RegCreateKey(hive, subpath) as handle: 591 if do_copy: 592 win32.RegCopyTree(value.handle, None, handle) 593 else: 594 win32.RegSetValueEx(handle, None, value)
595 596 # XXX FIXME currently not working! 597 # It's probably best to call RegDeleteKey recursively, even if slower.
598 - def __delitem__(self, path):
599 hive, subpath = self._parse_path(path) 600 if not subpath: 601 raise TypeError( 602 "Are you SURE you want to wipe out an entire hive?!" 603 " Call win32.RegDeleteTree() directly if you must...") 604 try: 605 win32.RegDeleteTree(hive, subpath) 606 except WindowsError, e: 607 if e.winerror == win32.ERROR_FILE_NOT_FOUND: 608 raise KeyError(path) 609 raise
610
611 - def create(self, path):
612 """ 613 Creates a new Registry key. 614 615 @type path: str 616 @param path: Registry key path. 617 618 @rtype: L{RegistryKey} 619 @return: The newly created Registry key. 620 """ 621 path = self._sanitize_path(path) 622 hive, subpath = self._parse_path(path) 623 handle = win32.RegCreateKey(hive, subpath) 624 return RegistryKey(path, handle)
625
626 - def subkeys(self, path):
627 """ 628 Returns a list of subkeys for the given Registry key. 629 630 @type path: str 631 @param path: Registry key path. 632 633 @rtype: list(str) 634 @return: List of subkey names. 635 """ 636 result = list() 637 hive, subpath = self._parse_path(path) 638 with win32.RegOpenKey(hive, subpath) as handle: 639 index = 0 640 while 1: 641 name = win32.RegEnumKey(handle, index) 642 if name is None: 643 break 644 result.append(name) 645 index += 1 646 return result
647
648 - def iterate(self, path):
649 """ 650 Returns a recursive iterator on the specified key and its subkeys. 651 652 @type path: str 653 @param path: Registry key path. 654 655 @rtype: iterator 656 @return: Recursive iterator that returns Registry key paths. 657 658 @raise KeyError: The specified path does not exist. 659 """ 660 if path.endswith('\\'): 661 path = path[:-1] 662 if not self.has_key(path): 663 raise KeyError(path) 664 stack = collections.deque() 665 stack.appendleft(path) 666 return self.__iterate(stack)
667
668 - def iterkeys(self):
669 """ 670 Returns an iterator that crawls the entire Windows Registry. 671 """ 672 stack = collections.deque(self._hives) 673 stack.reverse() 674 return self.__iterate(stack)
675
676 - def __iterate(self, stack):
677 while stack: 678 path = stack.popleft() 679 yield path 680 try: 681 subkeys = self.subkeys(path) 682 except WindowsError: 683 continue 684 prefix = path + '\\' 685 subkeys = [prefix + name for name in subkeys] 686 stack.extendleft(subkeys)
687