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

Source Code for Module winappdbg.util

  1  # Copyright (c) 2009-2010, Mario Vilas 
  2  # All rights reserved. 
  3  # 
  4  # Redistribution and use in source and binary forms, with or without 
  5  # modification, are permitted provided that the following conditions are met: 
  6  # 
  7  #     * Redistributions of source code must retain the above copyright notice, 
  8  #       this list of conditions and the following disclaimer. 
  9  #     * Redistributions in binary form must reproduce the above copyright 
 10  #       notice,this list of conditions and the following disclaimer in the 
 11  #       documentation and/or other materials provided with the distribution. 
 12  #     * Neither the name of the copyright holder nor the names of its 
 13  #       contributors may be used to endorse or promote products derived from 
 14  #       this software without specific prior written permission. 
 15  # 
 16  # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
 17  # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
 18  # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
 19  # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
 20  # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
 21  # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
 22  # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
 23  # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
 24  # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
 25  # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
 26  # POSSIBILITY OF SUCH DAMAGE. 
 27   
 28  """ 
 29  Miscellaneous utility classes and functions. 
 30   
 31  @group Miscellaneous: 
 32      PathOperations, 
 33      MemoryAddresses, 
 34      CustomAddressIterator, 
 35      DataAddressIterator, 
 36      ImageAddressIterator, 
 37      MappedAddressIterator, 
 38      ExecutableAddressIterator, 
 39      ReadableAddressIterator, 
 40      WriteableAddressIterator, 
 41      ExecutableAndWriteableAddressIterator, 
 42      DebugRegister, 
 43      Regenerator 
 44  """ 
 45   
 46  __revision__ = "$Id$" 
 47   
 48  __all__ = [ 
 49   
 50      # Filename and pathname manipulation 
 51      'PathOperations', 
 52   
 53      # Memory address operations 
 54      'MemoryAddresses', 
 55      'CustomAddressIterator', 
 56      'DataAddressIterator', 
 57      'ImageAddressIterator', 
 58      'MappedAddressIterator', 
 59      'ExecutableAddressIterator', 
 60      'ReadableAddressIterator', 
 61      'WriteableAddressIterator', 
 62      'ExecutableAndWriteableAddressIterator', 
 63   
 64      # Debug registers manipulation 
 65      'DebugRegister', 
 66   
 67      # Miscellaneous 
 68      'Regenerator', 
 69   
 70      ] 
 71   
 72  import os 
 73  import win32 
74 75 #============================================================================== 76 77 # See Process.generate_memory_snapshot() 78 -class Regenerator(object):
79 """ 80 Calls a generator and iterates it. When it's finished iterating, the 81 generator is called again. This allows you to iterate a generator more 82 than once (well, sort of). 83 """ 84
85 - def __init__(self, g_function, *v_args, **d_args):
86 """ 87 @type g_function: function 88 @param g_function: Function that when called returns a generator. 89 90 @type v_args: tuple 91 @param v_args: Variable arguments to pass to the generator function. 92 93 @type d_args: dict 94 @param d_args: Variable arguments to pass to the generator function. 95 """ 96 self.__g_function = g_function 97 self.__v_args = v_args 98 self.__d_args = d_args 99 self.__g_object = None
100
101 - def __iter__(self):
102 'x.__iter__() <==> iter(x)' 103 return self
104
105 - def next(self):
106 'x.next() -> the next value, or raise StopIteration' 107 if self.__g_object is None: 108 self.__g_object = self.__g_function( *self.__v_args, **self.__d_args ) 109 try: 110 return self.__g_object.next() 111 except StopIteration: 112 self.__g_object = None 113 raise
114
115 #============================================================================== 116 117 -class PathOperations (object):
118 """ 119 Static methods for filename and pathname manipulation. 120 """ 121 @classmethod
122 - def __new__(cls, *argv, **argd):
123 'Don\'t try to instance this class, it\'s just a namespace!' 124 raise NotImplementedError
125 126 @staticmethod
127 - def pathname_to_filename(pathname):
128 """ 129 @type pathname: str 130 @param pathname: Absolute path. 131 132 @rtype: str 133 @return: Relative path. 134 """ 135 return win32.PathFindFileName(pathname)
136 137 @staticmethod
138 - def filename_to_pathname(filename):
139 """ 140 @type filename: str 141 @param filename: Relative path. 142 143 @rtype: str 144 @return: Absolute path. 145 """ 146 return win32.GetFullPathName(filename)
147 148 @staticmethod
149 - def path_is_relative(path):
150 """ 151 @see: L{path_is_absolute} 152 153 @type path: str 154 @param path: Absolute or relative path. 155 156 @rtype: bool 157 @return: C{True} if the path is relative, C{False} if it's absolute. 158 """ 159 return win32.PathIsRelative(path)
160 161 @staticmethod
162 - def path_is_absolute(path):
163 """ 164 @see: L{path_is_relative} 165 166 @type path: str 167 @param path: Absolute or relative path. 168 169 @rtype: bool 170 @return: C{True} if the path is absolute, C{False} if it's relative. 171 """ 172 return not win32.PathIsRelative(path)
173 174 @staticmethod
175 - def split_extension(pathname):
176 """ 177 @type pathname: str 178 @param pathname: Absolute path. 179 180 @rtype: tuple( str, str ) 181 @return: 182 Tuple containing the file and extension components of the filename. 183 """ 184 filepart = win32.PathRemoveExtension(pathname) 185 extpart = win32.PathFindExtension(pathname) 186 return (filepart, extpart)
187 188 @staticmethod
189 - def split_filename(pathname):
190 """ 191 @type pathname: str 192 @param pathname: Absolute path. 193 194 @rtype: tuple( str, str ) 195 @return: Tuple containing the path to the file and the base filename. 196 """ 197 filepart = win32.PathFindFileName(pathname) 198 pathpart = win32.PathRemoveFileSpec(pathname) 199 return (pathpart, filepart)
200 201 @staticmethod
202 - def split_path(path):
203 """ 204 @see: L{join_path} 205 206 @type path: str 207 @param path: Absolute or relative path. 208 209 @rtype: list( str... ) 210 @return: List of path components. 211 """ 212 components = list() 213 while path: 214 next = win32.PathFindNextComponent(path) 215 if next: 216 prev = path[ : -len(next) ] 217 components.append(prev) 218 path = next 219 return components
220 221 @staticmethod
222 - def join_path(*components):
223 """ 224 @see: L{split_path} 225 226 @type components: tuple( str... ) 227 @param components: Path components. 228 229 @rtype: str 230 @return: Absolute or relative path. 231 """ 232 if components: 233 path = components[0] 234 for next in components[1:]: 235 path = win32.PathAppend(path, next) 236 else: 237 path = "" 238 return path
239 240 @staticmethod
241 - def native_to_win32_pathname(name):
242 """ 243 @type name: str 244 @param name: Native (NT) absolute pathname. 245 246 @rtype: str 247 @return: Win32 absolute pathname. 248 """ 249 # XXX TODO 250 # There are probably some native paths that 251 # won't be converted by this naive approach. 252 if name.startswith("\\"): 253 if name.startswith("\\??\\"): 254 name = name[4:] 255 elif name.startswith("\\SystemRoot\\"): 256 system_root_path = os.environ['SYSTEMROOT'] 257 if system_root_path.endswith('\\'): 258 system_root_path = system_root_path[:-1] 259 name = system_root_path + name[11:] 260 else: 261 for drive_number in xrange(ord('A'), ord('Z') + 1): 262 drive_letter = '%c:' % drive_number 263 try: 264 device_native_path = win32.QueryDosDevice(drive_letter) 265 except WindowsError, e: 266 if win32.winerror(e) in (win32.ERROR_FILE_NOT_FOUND, \ 267 win32.ERROR_PATH_NOT_FOUND): 268 continue 269 raise 270 if not device_native_path.endswith('\\'): 271 device_native_path += '\\' 272 if name.startswith(device_native_path): 273 name = drive_letter + '\\' + \ 274 name[ len(device_native_path) : ] 275 break 276 return name
277
278 #============================================================================== 279 280 -class MemoryAddresses (object):
281 """ 282 Class to manipulate memory addresses. 283 284 @type pageSize: int 285 @cvar pageSize: Page size in bytes. Defaults to 0x1000 but it's 286 automatically updated on runtime when importing the module. 287 """ 288 @classmethod
289 - def __new__(cls, *argv, **argd):
290 'Don\'t try to instance this class, it\'s just a namespace!' 291 raise NotImplementedError
292 293 # Try to get the pageSize value on runtime, 294 # ignoring exceptions on failure. 295 try: 296 try: 297 pageSize = win32.GetSystemInfo().dwPageSize 298 except WindowsError: 299 pageSize = 0x1000 300 except NameError: 301 pageSize = 0x1000 302 303 @classmethod
304 - def align_address_to_page_start(cls, address):
305 """ 306 Align the given address to the start of the page it occupies. 307 308 @type address: int 309 @param address: Memory address. 310 311 @rtype: int 312 @return: Aligned memory address. 313 """ 314 return address - ( address % cls.pageSize )
315 316 @classmethod
317 - def align_address_to_page_end(cls, address):
318 """ 319 Align the given address to the end of the page it occupies. 320 That is, to point to the start of the next page. 321 322 @type address: int 323 @param address: Memory address. 324 325 @rtype: int 326 @return: Aligned memory address. 327 """ 328 return address + cls.pageSize - ( address % cls.pageSize )
329 330 @classmethod
331 - def align_address_range(cls, begin, end):
332 """ 333 Align the given address range to the start and end of the page(s) it occupies. 334 335 @type begin: int 336 @param begin: Memory address of the beginning of the buffer. 337 338 @type end: int 339 @param end: Memory address of the end of the buffer. 340 341 @rtype: tuple( int, int ) 342 @return: Aligned memory addresses. 343 """ 344 if end > begin: 345 begin, end = end, begin 346 return ( 347 cls.align_address_to_page_start(begin), 348 cls.align_address_to_page_end(end) 349 )
350 351 @classmethod
352 - def get_buffer_size_in_pages(cls, address, size):
353 """ 354 Get the number of pages in use by the given buffer. 355 356 @type address: int 357 @param address: Aligned memory address. 358 359 @type size: int 360 @param size: Buffer size. 361 362 @rtype: int 363 @return: Buffer size in number of pages. 364 """ 365 if size < 0: 366 size = -size 367 address = address - size 368 begin, end = cls.align_address_range(address, address + size) 369 # XXX FIXME 370 # I think this rounding fails at least for address 0xFFFFFFFF size 1 371 return int(float(end - begin) / float(cls.pageSize))
372 373 @staticmethod
374 - def do_ranges_intersect(begin, end, old_begin, old_end):
375 """ 376 Determine if the two given memory address ranges intersect. 377 378 @type begin: int 379 @param begin: Start address of the first range. 380 381 @type end: int 382 @param end: End address of the first range. 383 384 @type old_begin: int 385 @param old_begin: Start address of the second range. 386 387 @type old_end: int 388 @param old_end: End address of the second range. 389 390 @rtype: bool 391 @return: C{True} if the two ranges intersect, C{False} otherwise. 392 """ 393 return (old_begin <= begin < old_end) or \ 394 (old_begin < end <= old_end) or \ 395 (begin <= old_begin < end) or \ 396 (begin < old_end <= end)
397
398 #============================================================================== 399 400 -def CustomAddressIterator(memory_map, condition):
401 """ 402 Generator function that iterates through a memory map, filtering memory 403 region blocks by any given condition. 404 405 @type memory_map: list( L{win32.MemoryBasicInformation} ) 406 @param memory_map: List of memory region information objects. 407 Returned by L{Process.get_memory_map}. 408 409 @type condition: function 410 @param condition: Callback function that returns C{True} if the memory 411 block should be returned, or C{False} if it should be filtered. 412 413 @rtype: generator of L{win32.MemoryBasicInformation} 414 @return: Generator object to iterate memory blocks. 415 """ 416 for mbi in memory_map: 417 if condition(mbi): 418 address = mbi.BaseAddress 419 max_addr = address + mbi.RegionSize 420 while address < max_addr: 421 yield address 422 address = address + 1
423
424 -def DataAddressIterator(memory_map):
425 """ 426 Generator function that iterates through a memory map, returning only those 427 memory blocks that contain data. 428 429 @type memory_map: list( L{win32.MemoryBasicInformation} ) 430 @param memory_map: List of memory region information objects. 431 Returned by L{Process.get_memory_map}. 432 433 @rtype: generator of L{win32.MemoryBasicInformation} 434 @return: Generator object to iterate memory blocks. 435 """ 436 return CustomAddressIterator(memory_map, 437 win32.MemoryBasicInformation.has_content)
438
439 -def ImageAddressIterator(memory_map):
440 """ 441 Generator function that iterates through a memory map, returning only those 442 memory blocks that belong to executable images. 443 444 @type memory_map: list( L{win32.MemoryBasicInformation} ) 445 @param memory_map: List of memory region information objects. 446 Returned by L{Process.get_memory_map}. 447 448 @rtype: generator of L{win32.MemoryBasicInformation} 449 @return: Generator object to iterate memory blocks. 450 """ 451 return CustomAddressIterator(memory_map, 452 win32.MemoryBasicInformation.is_image)
453
454 -def MappedAddressIterator(memory_map):
455 """ 456 Generator function that iterates through a memory map, returning only those 457 memory blocks that belong to memory mapped files. 458 459 @type memory_map: list( L{win32.MemoryBasicInformation} ) 460 @param memory_map: List of memory region information objects. 461 Returned by L{Process.get_memory_map}. 462 463 @rtype: generator of L{win32.MemoryBasicInformation} 464 @return: Generator object to iterate memory blocks. 465 """ 466 return CustomAddressIterator(memory_map, 467 win32.MemoryBasicInformation.is_mapped)
468
469 -def ReadableAddressIterator(memory_map):
470 """ 471 Generator function that iterates through a memory map, returning only those 472 memory blocks that are readable. 473 474 @type memory_map: list( L{win32.MemoryBasicInformation} ) 475 @param memory_map: List of memory region information objects. 476 Returned by L{Process.get_memory_map}. 477 478 @rtype: generator of L{win32.MemoryBasicInformation} 479 @return: Generator object to iterate memory blocks. 480 """ 481 return CustomAddressIterator(memory_map, 482 win32.MemoryBasicInformation.is_readable)
483
484 -def WriteableAddressIterator(memory_map):
485 """ 486 Generator function that iterates through a memory map, returning only those 487 memory blocks that are writeable. 488 489 @note: Writeable memory is always readable too. 490 491 @type memory_map: list( L{win32.MemoryBasicInformation} ) 492 @param memory_map: List of memory region information objects. 493 Returned by L{Process.get_memory_map}. 494 495 @rtype: generator of L{win32.MemoryBasicInformation} 496 @return: Generator object to iterate memory blocks. 497 """ 498 return CustomAddressIterator(memory_map, 499 win32.MemoryBasicInformation.is_writeable)
500
501 -def ExecutableAddressIterator(memory_map):
502 """ 503 Generator function that iterates through a memory map, returning only those 504 memory blocks that are executable. 505 506 @note: Executable memory is always readable too. 507 508 @type memory_map: list( L{win32.MemoryBasicInformation} ) 509 @param memory_map: List of memory region information objects. 510 Returned by L{Process.get_memory_map}. 511 512 @rtype: generator of L{win32.MemoryBasicInformation} 513 @return: Generator object to iterate memory blocks. 514 """ 515 return CustomAddressIterator(memory_map, 516 win32.MemoryBasicInformation.is_executable)
517
518 -def ExecutableAndWriteableAddressIterator(memory_map):
519 """ 520 Generator function that iterates through a memory map, returning only those 521 memory blocks that are executable and writeable. 522 523 @note: The presence of such pages make memory corruption vulnerabilities 524 much easier to exploit. 525 526 @type memory_map: list( L{win32.MemoryBasicInformation} ) 527 @param memory_map: List of memory region information objects. 528 Returned by L{Process.get_memory_map}. 529 530 @rtype: generator of L{win32.MemoryBasicInformation} 531 @return: Generator object to iterate memory blocks. 532 """ 533 return CustomAddressIterator(memory_map, 534 win32.MemoryBasicInformation.is_executable_and_writeable)
535
536 #============================================================================== 537 538 -class DebugRegister (object):
539 """ 540 Class to manipulate debug registers. 541 Used by L{HardwareBreakpoint}. 542 543 @group Trigger flags used by HardwareBreakpoint: 544 BREAK_ON_EXECUTION, BREAK_ON_WRITE, BREAK_ON_ACCESS, BREAK_ON_IO_ACCESS 545 @group Size flags used by HardwareBreakpoint: 546 WATCH_BYTE, WATCH_WORD, WATCH_DWORD, WATCH_QWORD 547 @group Bitwise masks for Dr7: 548 enableMask, disableMask, triggerMask, watchMask, clearMask, 549 generalDetectMask 550 @group Bitwise masks for Dr6: 551 hitMask, hitMaskAll, debugAccessMask, singleStepMask, taskSwitchMask, 552 clearDr6Mask, clearHitMask 553 @group Debug control MSR definitions: 554 DebugCtlMSR, LastBranchRecord, BranchTrapFlag, PinControl, 555 LastBranchToIP, LastBranchFromIP, 556 LastExceptionToIP, LastExceptionFromIP 557 558 @type BREAK_ON_EXECUTION: int 559 @cvar BREAK_ON_EXECUTION: Break on execution. 560 561 @type BREAK_ON_WRITE: int 562 @cvar BREAK_ON_WRITE: Break on write. 563 564 @type BREAK_ON_ACCESS: int 565 @cvar BREAK_ON_ACCESS: Break on read or write. 566 567 @type BREAK_ON_IO_ACCESS: int 568 @cvar BREAK_ON_IO_ACCESS: Break on I/O port access. 569 570 @type WATCH_BYTE: int 571 @cvar WATCH_BYTE: Watch a byte. 572 573 @type WATCH_WORD: int 574 @cvar WATCH_WORD: Watch a word. 575 576 @type WATCH_DWORD: int 577 @cvar WATCH_DWORD: Watch a double word. 578 579 @type WATCH_QWORD: int 580 @cvar WATCH_QWORD: Watch one quad word. 581 582 @type enableMask: 4-tuple of integers 583 @cvar enableMask: 584 Enable bit on C{Dr7} for each slot. 585 Works as a bitwise-OR mask. 586 587 @type disableMask: 4-tuple of integers 588 @cvar disableMask: 589 Mask of the enable bit on C{Dr7} for each slot. 590 Works as a bitwise-AND mask. 591 592 @type triggerMask: 4-tuple of 2-tuples of integers 593 @cvar triggerMask: 594 Trigger bits on C{Dr7} for each trigger flag value. 595 Each 2-tuple has the bitwise-OR mask and the bitwise-AND mask. 596 597 @type watchMask: 4-tuple of 2-tuples of integers 598 @cvar watchMask: 599 Watch bits on C{Dr7} for each watch flag value. 600 Each 2-tuple has the bitwise-OR mask and the bitwise-AND mask. 601 602 @type clearMask: 4-tuple of integers 603 @cvar clearMask: 604 Mask of all important bits on C{Dr7} for each slot. 605 Works as a bitwise-AND mask. 606 607 @type generalDetectMask: integer 608 @cvar generalDetectMask: 609 General detect mode bit. It enables the processor to notify the 610 debugger when the debugee is trying to access one of the debug 611 registers. 612 613 @type hitMask: 4-tuple of integers 614 @cvar hitMask: 615 Hit bit on C{Dr6} for each slot. 616 Works as a bitwise-AND mask. 617 618 @type hitMaskAll: integer 619 @cvar hitMaskAll: 620 Bitmask for all hit bits in C{Dr6}. Useful to know if at least one 621 hardware breakpoint was hit, or to clear the hit bits only. 622 623 @type clearHitMask: integer 624 @cvar clearHitMask: 625 Bitmask to clear all the hit bits in C{Dr6}. 626 627 @type debugAccessMask: integer 628 @cvar debugAccessMask: 629 The debugee tried to access a debug register. Needs bit 630 L{generalDetectMask} enabled in C{Dr7}. 631 632 @type singleStepMask: integer 633 @cvar singleStepMask: 634 A single step exception was raised. Needs the trap flag enabled. 635 636 @type taskSwitchMask: integer 637 @cvar taskSwitchMask: 638 A task switch has occurred. Needs the TSS T-bit set to 1. 639 640 @type clearDr6Mask: integer 641 @cvar clearDr6Mask: 642 Bitmask to clear all meaningful bits in C{Dr6}. 643 """ 644 @classmethod
645 - def __new__(cls, *argv, **argd):
646 'Don\'t try to instance this class, it\'s just a namespace!' 647 raise NotImplementedError
648 649 BREAK_ON_EXECUTION = 0 650 BREAK_ON_WRITE = 1 651 BREAK_ON_ACCESS = 3 652 BREAK_ON_IO_ACCESS = 2 653 654 WATCH_BYTE = 0 655 WATCH_WORD = 1 656 WATCH_DWORD = 3 657 WATCH_QWORD = 2 658 659 registerMask = win32.SIZE_T(-1).value 660 661 #------------------------------------------------------------------------------ 662 663 # http://en.wikipedia.org/wiki/Debug_register 664 665 # DR7 - Debug control 666 # 667 # The low-order eight bits of DR7 (0,2,4,6 and 1,3,5,7) selectively enable 668 # the four address breakpoint conditions. There are two levels of enabling: 669 # the local (0,2,4,6) and global (1,3,5,7) levels. The local enable bits 670 # are automatically reset by the processor at every task switch to avoid 671 # unwanted breakpoint conditions in the new task. The global enable bits 672 # are not reset by a task switch; therefore, they can be used for 673 # conditions that are global to all tasks. 674 # 675 # Bits 16-17 (DR0), 20-21 (DR1), 24-25 (DR2), 28-29 (DR3), define when 676 # breakpoints trigger. Each breakpoint has a two-bit entry that specifies 677 # whether they break on execution (00b), data write (01b), data read or 678 # write (11b). 10b is defined to mean break on IO read or write but no 679 # hardware supports it. Bits 18-19 (DR0), 22-23 (DR1), 26-27 (DR2), 30-31 680 # (DR3), define how large area of memory is watched by breakpoints. Again 681 # each breakpoint has a two-bit entry that specifies whether they watch 682 # one (00b), two (01b), eight (10b) or four (11b) bytes. 683 684 # This could easily be calculated on runtime in only one method, 685 # but it's faster to have it precalculated like this. 686 687 # Dr7 |= enableMask[register] 688 enableMask = ( 689 1 << 0, # Dr0 (bit 0) 690 1 << 2, # Dr1 (bit 2) 691 1 << 4, # Dr2 (bit 4) 692 1 << 6, # Dr3 (bit 6) 693 ) 694 695 # Dr7 &= disableMask[register] 696 disableMask = tuple( [registerMask ^ x for x in enableMask] ) 697 del x 698 699 # orMask, andMask = triggerMask[register][trigger] 700 # Dr7 = (Dr7 & andMask) | orMask # to set 701 # Dr7 = Dr7 & andMask # to remove 702 triggerMask = ( 703 # Dr0 (bits 16-17) 704 ( 705 ((0 << 16), (3 << 16) ^ registerMask), # execute 706 ((1 << 16), (3 << 16) ^ registerMask), # write 707 ((2 << 16), (3 << 16) ^ registerMask), # io read 708 ((3 << 16), (3 << 16) ^ registerMask), # access 709 ), 710 # Dr1 (bits 20-21) 711 ( 712 ((0 << 20), (3 << 20) ^ registerMask), # execute 713 ((1 << 20), (3 << 20) ^ registerMask), # write 714 ((2 << 20), (3 << 20) ^ registerMask), # io read 715 ((3 << 20), (3 << 20) ^ registerMask), # access 716 ), 717 # Dr2 (bits 24-25) 718 ( 719 ((0 << 24), (3 << 24) ^ registerMask), # execute 720 ((1 << 24), (3 << 24) ^ registerMask), # write 721 ((2 << 24), (3 << 24) ^ registerMask), # io read 722 ((3 << 24), (3 << 24) ^ registerMask), # access 723 ), 724 # Dr3 (bits 28-29) 725 ( 726 ((0 << 28), (3 << 28) ^ registerMask), # execute 727 ((1 << 28), (3 << 28) ^ registerMask), # write 728 ((2 << 28), (3 << 28) ^ registerMask), # io read 729 ((3 << 28), (3 << 28) ^ registerMask), # access 730 ), 731 ) 732 733 # orMask, andMask = watchMask[register][watch] 734 # Dr7 = (Dr7 & andMask) | orMask # to set 735 # Dr7 = Dr7 & andMask # to remove 736 watchMask = ( 737 # Dr0 (bits 18-19) 738 ( 739 ((0 << 18), (3 << 18) ^ registerMask), # byte 740 ((1 << 18), (3 << 18) ^ registerMask), # word 741 ((2 << 18), (3 << 18) ^ registerMask), # qword 742 ((3 << 18), (3 << 18) ^ registerMask), # dword 743 ), 744 # Dr1 (bits 22-23) 745 ( 746 ((0 << 23), (3 << 23) ^ registerMask), # byte 747 ((1 << 23), (3 << 23) ^ registerMask), # word 748 ((2 << 23), (3 << 23) ^ registerMask), # qword 749 ((3 << 23), (3 << 23) ^ registerMask), # dword 750 ), 751 # Dr2 (bits 26-27) 752 ( 753 ((0 << 26), (3 << 26) ^ registerMask), # byte 754 ((1 << 26), (3 << 26) ^ registerMask), # word 755 ((2 << 26), (3 << 26) ^ registerMask), # qword 756 ((3 << 26), (3 << 26) ^ registerMask), # dword 757 ), 758 # Dr3 (bits 30-31) 759 ( 760 ((0 << 30), (3 << 31) ^ registerMask), # byte 761 ((1 << 30), (3 << 31) ^ registerMask), # word 762 ((2 << 30), (3 << 31) ^ registerMask), # qword 763 ((3 << 30), (3 << 31) ^ registerMask), # dword 764 ), 765 ) 766 767 # Dr7 = Dr7 & clearMask[register] 768 clearMask = ( 769 registerMask ^ ( (1 << 0) + (3 << 16) + (3 << 18) ), # Dr0 770 registerMask ^ ( (1 << 2) + (3 << 20) + (3 << 22) ), # Dr1 771 registerMask ^ ( (1 << 4) + (3 << 24) + (3 << 26) ), # Dr2 772 registerMask ^ ( (1 << 6) + (3 << 28) + (3 << 30) ), # Dr3 773 ) 774 775 # Dr7 = Dr7 | generalDetectMask 776 generalDetectMask = (1 << 13) 777 778 # DR6 - Debug status 779 # 780 # The debug status register permits the debugger to determine which debug 781 # conditions have occurred. When the processor detects an enabled debug 782 # exception, it sets the low-order bits of this register (0,1,2,3) before 783 # entering the debug exception handler. 784 # 785 # Note that the bits of DR6 are never cleared by the processor. To avoid 786 # any confusion in identifying the next debug exception, the debug handler 787 # should move zeros to DR6 immediately before returning. 788 789 # bool(Dr6 & hitMask[register]) 790 hitMask = ( 791 (1 << 0), # Dr0 792 (1 << 1), # Dr1 793 (1 << 2), # Dr2 794 (1 << 3), # Dr3 795 ) 796 797 # bool(Dr6 & anyHitMask) 798 hitMaskAll = hitMask[0] | hitMask[1] | hitMask[2] | hitMask[3] 799 800 # Dr6 = Dr6 & clearHitMask 801 clearHitMask = registerMask ^ hitMaskAll 802 803 # bool(Dr6 & debugAccessMask) 804 debugAccessMask = (1 << 13) 805 806 # bool(Dr6 & singleStepMask) 807 singleStepMask = (1 << 14) 808 809 # bool(Dr6 & taskSwitchMask) 810 taskSwitchMask = (1 << 15) 811 812 # Dr6 = Dr6 & clearDr6Mask 813 clearDr6Mask = registerMask ^ (hitMaskAll | \ 814 debugAccessMask | singleStepMask | taskSwitchMask) 815 816 #------------------------------------------------------------------------------ 817 818 # (from the AMD64 manuals) 819 820 # The fields within the DebugCtlMSR register are: 821 # 822 # Last-Branch Record (LBR) - Bit 0, read/write. Software sets this bit to 1 823 # to cause the processor to record the source and target addresses of the 824 # last control transfer taken before a debug exception occurs. The recorded 825 # control transfers include branch instructions, interrupts, and exceptions. 826 # 827 # Branch Single Step (BTF) - Bit 1, read/write. Software uses this bit to 828 # change the behavior of the rFLAGS.TF bit. When this bit is cleared to 0, 829 # the rFLAGS.TF bit controls instruction single stepping, (normal behavior). 830 # When this bit is set to 1, the rFLAGS.TF bit controls single stepping on 831 # control transfers. The single-stepped control transfers include branch 832 # instructions, interrupts, and exceptions. Control-transfer single stepping 833 # requires both BTF=1 and rFLAGS.TF=1. 834 # 835 # Performance-Monitoring/Breakpoint Pin-Control (PBi) - Bits 5-2, read/write. 836 # Software uses these bits to control the type of information reported by 837 # the four external performance-monitoring/breakpoint pins on the processor. 838 # When a PBi bit is cleared to 0, the corresponding external pin (BPi) 839 # reports performance-monitor information. When a PBi bit is set to 1, the 840 # corresponding external pin (BPi) reports breakpoint information. 841 # 842 # All remaining bits in the DebugCtlMSR register are reserved. 843 844 # Software can enable control-transfer single stepping by setting 845 # DebugCtlMSR.BTF to 1 and rFLAGS.TF to 1. The processor automatically 846 # disables control-transfer single stepping when a debug exception (#DB) 847 # occurs by clearing DebugCtlMSR.BTF to 0. rFLAGS.TF is also cleared when a 848 # #DB exception occurs. Before exiting the debug-exception handler, software 849 # must set both DebugCtlMSR.BTF and rFLAGS.TF to 1 to restart single 850 # stepping. 851 852 DebugCtlMSR = 0x1D9 853 LastBranchRecord = (1 << 0) 854 BranchTrapFlag = (1 << 1) 855 PinControl = ( 856 (1 << 2), # PB1 857 (1 << 3), # PB2 858 (1 << 4), # PB3 859 (1 << 5), # PB4 860 ) 861 862 # Control-transfer recording MSRs: LastBranchToIP, LastBranchFromIP, 863 # LastExceptionToIP, and LastExceptionFromIP. These registers are loaded 864 # automatically by the processor when the DebugCtlMSR.LBR bit is set to 1. 865 # These MSRs are read-only. 866 867 # The processor automatically disables control-transfer recording when a 868 # debug exception (#DB) occurs by clearing DebugCtlMSR.LBR to 0. The 869 # contents of the control-transfer recording MSRs are not altered by the 870 # processor when the #DB occurs. Before exiting the debug-exception handler, 871 # software can set DebugCtlMSR.LBR to 1 to re-enable the recording mechanism. 872 873 LastBranchToIP = 0x1DC 874 LastBranchFromIP = 0x1DB 875 LastExceptionToIP = 0x1DE 876 LastExceptionFromIP = 0x1DD 877 878 #------------------------------------------------------------------------------ 879 880 @classmethod
881 - def clear_bp(cls, ctx, register):
882 """ 883 Clears a hardware breakpoint. 884 885 @see: find_slot, set_bp 886 887 @type ctx: dict( str S{->} int ) 888 @param ctx: Thread context dictionary. 889 890 @type register: int 891 @param register: Slot (debug register) for hardware breakpoint. 892 """ 893 ctx['Dr7'] &= cls.clearMask[register] 894 ctx['Dr%d' % register] = 0
895 896 @classmethod
897 - def set_bp(cls, ctx, register, address, trigger, watch):
898 """ 899 Sets a hardware breakpoint. 900 901 @see: clear_bp, find_slot 902 903 @type ctx: dict( str S{->} int ) 904 @param ctx: Thread context dictionary. 905 906 @type register: int 907 @param register: Slot (debug register). 908 909 @type address: int 910 @param address: Memory address. 911 912 @type trigger: int 913 @param trigger: Trigger flag. See L{HardwareBreakpoint.validTriggers}. 914 915 @type watch: int 916 @param watch: Watch flag. See L{HardwareBreakpoint.validWatchSizes}. 917 """ 918 Dr7 = ctx['Dr7'] 919 Dr7 |= cls.enableMask[register] 920 orMask, andMask = cls.triggerMask[register][trigger] 921 Dr7 &= andMask 922 Dr7 |= orMask 923 orMask, andMask = cls.watchMask[register][watch] 924 Dr7 &= andMask 925 Dr7 |= orMask 926 ctx['Dr7'] = Dr7 927 ctx['Dr%d' % register] = address
928 929 @classmethod
930 - def find_slot(cls, ctx):
931 """ 932 Finds an empty slot to set a hardware breakpoint. 933 934 @see: clear_bp, set_bp 935 936 @type ctx: dict( str S{->} int ) 937 @param ctx: Thread context dictionary. 938 939 @rtype: int 940 @return: Slot (debug register) for hardware breakpoint. 941 """ 942 Dr7 = ctx['Dr7'] 943 slot = 0 944 for m in cls.enableMask: 945 if (Dr7 & m) == 0: 946 return slot 947 slot += 1 948 return None
949