1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 """
29 Breakpoints module.
30
31 @group Breakpoints:
32 Breakpoint, CodeBreakpoint, PageBreakpoint, HardwareBreakpoint,
33 BufferWatch, Hook, ApiHook
34
35 @group Capabilities (private):
36 BreakpointContainer
37 """
38
39 __revision__ = "$Id: breakpoint.py 675 2010-05-05 11:40:57Z qvasimodo $"
40
41 __all__ = [
42
43
44 'Breakpoint',
45
46
47 'CodeBreakpoint',
48 'PageBreakpoint',
49 'HardwareBreakpoint',
50
51
52 'Hook',
53 'ApiHook',
54 'BufferWatch',
55
56
57 'BreakpointContainer',
58
59 ]
60
61 from system import Process, System, MemoryAddresses
62 from util import DebugRegister
63 from textio import HexDump
64 import win32
65
66
67
69 """
70 Base class for breakpoints.
71 Here's the breakpoints state machine.
72
73 @see: L{CodeBreakpoint}, L{PageBreakpoint}, L{HardwareBreakpoint}
74
75 @group Breakpoint states:
76 DISABLED, ENABLED, ONESHOT, RUNNING
77 @group State machine:
78 hit, disable, enable, one_shot, running,
79 is_disabled, is_enabled, is_one_shot, is_running,
80 get_state, get_state_name
81 @group Information:
82 get_address, get_size, is_here
83 @group Conditional breakpoints:
84 is_conditional, is_unconditional,
85 get_condition, set_condition, eval_condition
86 @group Automatic breakpoints:
87 is_automatic, is_interactive,
88 get_action, set_action, run_action
89
90 @cvar DISABLED: I{Disabled} S{->} Enabled, OneShot
91 @cvar ENABLED: I{Enabled} S{->} I{Running}, Disabled
92 @cvar ONESHOT: I{OneShot} S{->} I{Disabled}
93 @cvar RUNNING: I{Running} S{->} I{Enabled}, Disabled
94
95 @type DISABLED: int
96 @type ENABLED: int
97 @type ONESHOT: int
98 @type RUNNING: int
99
100 @type stateNames: dict E{lb} int S{->} str E{rb}
101 @cvar stateNames: User-friendly names for each breakpoint state.
102
103 @type typeName: str
104 @cvar typeName: User friendly breakpoint type string.
105 """
106
107
108
109
110 DISABLED = 0
111 ENABLED = 1
112 ONESHOT = 2
113 RUNNING = 3
114
115 typeName = 'breakpoint'
116
117 stateNames = {
118 DISABLED : 'disabled',
119 ENABLED : 'enabled',
120 ONESHOT : 'one shot',
121 RUNNING : 'running',
122 }
123
124 - def __init__(self, address, size = 1, condition = True, action = None):
125 """
126 Breakpoint object.
127
128 @type address: int
129 @param address: Memory address for breakpoint.
130
131 @type size: int
132 @param size: Size of breakpoint in bytes (defaults to 1).
133
134 @type condition: function
135 @param condition: (Optional) Condition callback function.
136
137 The callback signature is::
138
139 def condition_callback(event):
140 return True # returns True or False
141
142 Where B{event} is an L{Event} object,
143 and the return value is a boolean
144 (C{True} to dispatch the event, C{False} otherwise).
145
146 @type action: function
147 @param action: (Optional) Action callback function.
148 If specified, the event is handled by this callback instead of
149 being dispatched normally.
150
151 The callback signature is::
152
153 def action_callback(event):
154 pass # no return value
155
156 Where B{event} is an L{Event} object.
157 """
158 self.__address = address
159 self.__size = size
160 self.__state = self.DISABLED
161
162 self.set_condition(condition)
163 self.set_action(action)
164
187
188
189
191 """
192 @rtype: bool
193 @return: C{True} if the breakpoint is in L{DISABLED} state.
194 """
195 return self.get_state() == self.DISABLED
196
198 """
199 @rtype: bool
200 @return: C{True} if the breakpoint is in L{ENABLED} state.
201 """
202 return self.get_state() == self.ENABLED
203
205 """
206 @rtype: bool
207 @return: C{True} if the breakpoint is in L{ONESHOT} state.
208 """
209 return self.get_state() == self.ONESHOT
210
212 """
213 @rtype: bool
214 @return: C{True} if the breakpoint is in L{RUNNING} state.
215 """
216 return self.get_state() == self.RUNNING
217
219 """
220 @rtype: bool
221 @return: C{True} if the address is within the range of the breakpoint.
222 """
223 begin = self.get_address()
224 end = begin + self.get_size()
225 return begin <= address < end
226
228 """
229 @rtype: int
230 @return: The target memory address for the breakpoint.
231 """
232 return self.__address
233
235 """
236 @rtype: int
237 @return: The size in bytes of the breakpoint.
238 """
239 return self.__size
240
242 """
243 @rtype: tuple( int, int )
244 @return:
245 Starting and ending address of the memory range
246 covered by the breakpoint.
247 """
248 address = self.get_address()
249 size = self.get_size()
250 return ( address, address + size )
251
253 """
254 @rtype: int
255 @return: The current state of the breakpoint
256 (L{DISABLED}, L{ENABLED}, L{ONESHOT}, L{RUNNING}).
257 """
258 return self.__state
259
261 """
262 @rtype: str
263 @return: The name of the current state of the breakpoint.
264 """
265 return self.stateNames[ self.get_state() ]
266
267
268
270 """
271 @see: L{__init__}
272 @rtype: bool
273 @return: C{True} if the breakpoint has a condition callback defined.
274 """
275 return self.__condition is not True
276
278 """
279 @rtype: bool
280 @return: C{True} if the breakpoint doesn't have a condition callback defined.
281 """
282 return self.__condition is True
283
285 """
286 @rtype: bool, function
287 @return: Returns the condition callback for conditional breakpoints.
288 Returns C{True} for unconditional breakpoints.
289 """
290 return self.__condition
291
293 """
294 Sets a new condition callback for the breakpoint.
295
296 @see: L{__init__}
297
298 @type condition: function
299 @param condition: (Optional) Condition callback function.
300 """
301 if condition in (True, False, None):
302 self.__condition = True
303 else:
304 self.__condition = condition
305
307 """
308 Evaluates the breakpoint condition, if any was set.
309
310 @type event: L{Event}
311 @param event: Debug event triggered by the breakpoint.
312
313 @rtype: bool
314 @return: C{True} to dispatch the event, C{False} otherwise.
315 """
316 condition = self.get_condition()
317 if condition is True:
318 return True
319 if callable(condition):
320 return condition(event)
321 return condition
322
323
324
326 """
327 @rtype: bool
328 @return: C{True} if the breakpoint has an action callback defined.
329 """
330 return self.__action is not None
331
333 """
334 @rtype: bool
335 @return:
336 C{True} if the breakpoint doesn't have an action callback defined.
337 """
338 return self.__action is None
339
341 """
342 @rtype: bool, function
343 @return: Returns the action callback for automatic breakpoints.
344 Returns C{None} for interactive breakpoints.
345 """
346 return self.__action
347
349 """
350 Sets a new action callback for the breakpoint.
351
352 @type action: function
353 @param action: (Optional) Action callback function.
354 """
355 self.__action = action
356
358 """
359 Executes the breakpoint action callback, if any was set.
360
361 @type event: L{Event}
362 @param event: Debug event triggered by the breakpoint.
363 """
364 action = self.get_action()
365 if action is not None:
366 return bool( action(event) )
367 return True
368
369
370
372 """
373 Raises an C{AssertionError} exception for an invalid state transition.
374
375 @see: L{stateNames}
376
377 @type state: int
378 @param state: Intended breakpoint state.
379
380 @raise Exception: Always.
381 """
382 statemsg = ""
383 oldState = self.stateNames[ self.get_state() ]
384 newState = self.stateNames[ state ]
385 msg = "Invalid state transition (%s -> %s)" \
386 " for breakpoint at address %s"
387 msg = msg % (oldState, newState, HexDump.address(self.get_address()))
388 raise AssertionError, msg
389
390 - def disable(self, aProcess, aThread):
391 """
392 Transition to L{DISABLED} state.
393 - When hit: OneShot S{->} Disabled
394 - Forced by user: Enabled, OneShot, Running S{->} Disabled
395 - Transition from running state may require special handling
396 by the breakpoint implementation class.
397
398 @type aProcess: L{Process}
399 @param aProcess: Process object.
400
401 @type aThread: L{Thread}
402 @param aThread: Thread object.
403 """
404
405
406 self.__state = self.DISABLED
407
408 - def enable(self, aProcess, aThread):
409 """
410 Transition to L{ENABLED} state.
411 - When hit: Running S{->} Enabled
412 - Forced by user: Disabled, Running S{->} Enabled
413 - Transition from running state may require special handling
414 by the breakpoint implementation class.
415
416 @type aProcess: L{Process}
417 @param aProcess: Process object.
418
419 @type aThread: L{Thread}
420 @param aThread: Thread object.
421 """
422
423
424 self.__state = self.ENABLED
425
427 """
428 Transition to L{ONESHOT} state.
429 - Forced by user: Disabled S{->} OneShot
430
431 @type aProcess: L{Process}
432 @param aProcess: Process object.
433
434 @type aThread: L{Thread}
435 @param aThread: Thread object.
436 """
437
438
439 self.__state = self.ONESHOT
440
441 - def running(self, aProcess, aThread):
442 """
443 Transition to L{RUNNING} state.
444 - When hit: Enabled S{->} Running
445
446 @type aProcess: L{Process}
447 @param aProcess: Process object.
448
449 @type aThread: L{Thread}
450 @param aThread: Thread object.
451 """
452 if self.__state != self.ENABLED:
453 self.__bad_transition(self.RUNNING)
454 self.__state = self.RUNNING
455
456 - def hit(self, event):
457 """
458 Notify a breakpoint that it's been hit.
459 This triggers the corresponding state transition.
460
461 @see: L{disable}, L{enable}, L{one_shot}, L{running}
462
463 @type event: L{Event}
464 @param event: Debug event to handle (depends on the breakpoint type).
465
466 @raise AssertionError: Disabled breakpoints can't be hit.
467 """
468 aProcess = event.get_process()
469 aThread = event.get_thread()
470 state = self.get_state()
471
472 if state == self.ENABLED:
473 self.running(aProcess, aThread)
474
475 elif state == self.RUNNING:
476 self.enable(aProcess, aThread)
477
478 elif state == self.ONESHOT:
479 self.disable(aProcess, aThread)
480
481 elif state == self.DISABLED:
482
483 msg = "Hit a disabled breakpoint at address %s"
484 msg = msg % HexDump.address( self.get_address() )
485 raise AssertionError, msg
486
487
488
489
490
491
492
493
495 """
496 Code execution breakpoints (using an int3 opcode).
497
498 @see: L{Debug.break_at}
499
500 @type bpInstruction: str
501 @cvar bpInstruction: Breakpoint instruction for the current processor.
502 """
503
504 typeName = 'code breakpoint'
505
506 if System.arch in ('i386', 'amd64'):
507 bpInstruction = '\xCC'
508
509 - def __init__(self, address, condition = True, action = None):
510 """
511 Code breakpoint object.
512
513 @see: L{Breakpoint.__init__}
514
515 @type address: int
516 @param address: Memory address for breakpoint.
517
518 @type condition: function
519 @param condition: (Optional) Condition callback function.
520
521 @type action: function
522 @param action: (Optional) Action callback function.
523 """
524 if System.arch not in ('i386', 'amd64'):
525 msg = "Code breakpoints not supported for %s" % System.arch
526 raise NotImplementedError, msg
527 Breakpoint.__init__(self, address, len(self.bpInstruction),
528 condition, action)
529 self.__previousValue = self.bpInstruction
530
542
544 """
545 Restores the original byte at the target address.
546
547 @type aProcess: L{Process}
548 @param aProcess: Process object.
549 """
550
551 address = self.get_address()
552 currentValue = aProcess.read(address, len(self.bpInstruction))
553 if currentValue == self.bpInstruction:
554 aProcess.write(self.get_address(), self.__previousValue)
555 else:
556 self.__previousValue = currentValue
557
558 - def disable(self, aProcess, aThread):
562
563 - def enable(self, aProcess, aThread):
567
572
573
574
575
576
577
578 - def running(self, aProcess, aThread):
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598 -class PageBreakpoint (Breakpoint):
599 """
600 Page access breakpoint (using guard pages).
601
602 @see: L{Debug.watch_buffer}
603 """
604
605 typeName = 'page breakpoint'
606
607
608
609 - def __init__(self, address, pages = 1, condition = True, action = None):
610 """
611 Page breakpoint object.
612
613 @see: L{Breakpoint.__init__}
614
615 @type address: int
616 @param address: Memory address for breakpoint.
617
618 @type pages: int
619 @param address: Size of breakpoint in pages.
620
621 @type condition: function
622 @param condition: (Optional) Condition callback function.
623
624 @type action: function
625 @param action: (Optional) Action callback function.
626 """
627 Breakpoint.__init__(self, address, pages * System.pageSize, condition,
628 action)
629
630 floordiv_align = long(address) // long(System.pageSize)
631 truediv_align = float(address) / float(System.pageSize)
632 if floordiv_align != truediv_align:
633 msg = "Address of page breakpoint " \
634 "must be aligned to a page size boundary " \
635 "(value %s received)" % HexDump.address(address)
636 raise ValueError, msg
637
639 """
640 @rtype: int
641 @return: The size in pages of the breakpoint.
642 """
643
644 return self.get_size() // System.pageSize
645
646 - def __set_bp(self, aProcess):
647 """
648 Sets the target pages as guard pages.
649
650 @type aProcess: L{Process}
651 @param aProcess: Process object.
652 """
653 lpAddress = self.get_address()
654 dwSize = self.get_size()
655 flNewProtect = aProcess.mquery(lpAddress).Protect
656 flNewProtect = flNewProtect | win32.PAGE_GUARD
657 aProcess.mprotect(lpAddress, dwSize, flNewProtect)
658
659 - def __clear_bp(self, aProcess):
660 """
661 Restores the original permissions of the target pages.
662
663 @type aProcess: L{Process}
664 @param aProcess: Process object.
665 """
666 lpAddress = self.get_address()
667 flNewProtect = aProcess.mquery(lpAddress).Protect
668 flNewProtect = flNewProtect & (0xFFFFFFFF ^ win32.PAGE_GUARD)
669 aProcess.mprotect(lpAddress, self.get_size(), flNewProtect)
670
671 - def disable(self, aProcess, aThread):
672 if not self.is_disabled():
673 self.__clear_bp(aProcess)
674 super(PageBreakpoint, self).disable(aProcess, aThread)
675
676 - def enable(self, aProcess, aThread):
677 if System.arch not in ('i386', 'amd64'):
678 msg = "Only one-shot page breakpoints are supported for %s"
679 raise NotImplementedError, msg % System.arch
680 if not self.is_enabled() and not self.is_one_shot():
681 self.__set_bp(aProcess)
682 super(PageBreakpoint, self).enable(aProcess, aThread)
683
684 - def one_shot(self, aProcess, aThread):
685 if not self.is_enabled() and not self.is_one_shot():
686 self.__set_bp(aProcess)
687 super(PageBreakpoint, self).one_shot(aProcess, aThread)
688
689 - def running(self, aProcess, aThread):
690 aThread.set_tf()
691 super(PageBreakpoint, self).running(aProcess, aThread)
692
693
694
696 """
697 Hardware breakpoint (using debug registers).
698
699 @see: L{Debug.watch_variable}
700 @group Trigger flags:
701 BREAK_ON_EXECUTION, BREAK_ON_WRITE, BREAK_ON_ACCESS, BREAK_ON_IO_ACCESS
702 @group Watch size flags:
703 WATCH_BYTE, WATCH_WORD, WATCH_DWORD, WATCH_QWORD
704
705 @type BREAK_ON_EXECUTION: int
706 @cvar BREAK_ON_EXECUTION: Break on execution.
707
708 @type BREAK_ON_WRITE: int
709 @cvar BREAK_ON_WRITE: Break on write.
710
711 @type BREAK_ON_ACCESS: int
712 @cvar BREAK_ON_ACCESS: Break on read or write.
713
714 @type BREAK_ON_IO_ACCESS: int
715 @cvar BREAK_ON_IO_ACCESS: Break on I/O port access.
716
717 @type WATCH_BYTE: int
718 @cvar WATCH_BYTE: Watch a byte.
719
720 @type WATCH_WORD: int
721 @cvar WATCH_WORD: Watch a word.
722
723 @type WATCH_DWORD: int
724 @cvar WATCH_DWORD: Watch a double word.
725
726 @type WATCH_QWORD: int
727 @cvar WATCH_QWORD: Watch one quad word.
728
729 @type validTriggers: tuple
730 @cvar validTriggers: Valid trigger flag values.
731
732 @type validWatchSizes: tuple
733 @cvar validWatchSizes: Valid watch flag values.
734 """
735
736 typeName = 'hardware breakpoint'
737
738 BREAK_ON_EXECUTION = DebugRegister.BREAK_ON_EXECUTION
739 BREAK_ON_WRITE = DebugRegister.BREAK_ON_WRITE
740 BREAK_ON_ACCESS = DebugRegister.BREAK_ON_ACCESS
741 BREAK_ON_IO_ACCESS = DebugRegister.BREAK_ON_IO_ACCESS
742
743 WATCH_BYTE = DebugRegister.WATCH_BYTE
744 WATCH_WORD = DebugRegister.WATCH_WORD
745 WATCH_DWORD = DebugRegister.WATCH_DWORD
746 WATCH_QWORD = DebugRegister.WATCH_QWORD
747
748 validTriggers = (
749 BREAK_ON_EXECUTION,
750 BREAK_ON_WRITE,
751 BREAK_ON_ACCESS,
752 BREAK_ON_IO_ACCESS,
753 )
754
755 validWatchSizes = (
756 WATCH_BYTE,
757 WATCH_WORD,
758 WATCH_DWORD,
759 WATCH_QWORD,
760 )
761
766 """
767 Hardware breakpoint object.
768
769 @see: L{Breakpoint.__init__}
770
771 @type address: int
772 @param address: Memory address for breakpoint.
773
774 @type triggerFlag: int
775 @param triggerFlag: Trigger of breakpoint. Must be one of the following:
776
777 - L{BREAK_ON_EXECUTION}
778
779 Break on code execution.
780
781 - L{BREAK_ON_WRITE}
782
783 Break on memory read or write.
784
785 - L{BREAK_ON_ACCESS}
786
787 Break on memory write.
788
789 @type sizeFlag: int
790 @param sizeFlag: Size of breakpoint. Must be one of the following:
791
792 - L{WATCH_BYTE}
793
794 One (1) byte in size.
795
796 - L{WATCH_WORD}
797
798 Two (2) bytes in size.
799
800 - L{WATCH_DWORD}
801
802 Four (4) bytes in size.
803
804 - L{WATCH_QWORD}
805
806 Eight (8) bytes in size.
807
808 @type condition: function
809 @param condition: (Optional) Condition callback function.
810
811 @type action: function
812 @param action: (Optional) Action callback function.
813 """
814 if System.arch not in ('i386', 'amd64'):
815 msg = "Hardware breakpoints not supported for %s" % System.arch
816 raise NotImplementedError, msg
817 if sizeFlag == self.WATCH_BYTE:
818 size = 1
819 elif sizeFlag == self.WATCH_WORD:
820 size = 2
821 elif sizeFlag == self.WATCH_DWORD:
822 size = 4
823 elif sizeFlag == self.WATCH_QWORD:
824 size = 8
825 else:
826 msg = "Invalid size flag for hardware breakpoint (%s)"
827 msg = msg % repr(sizeFlag)
828 raise ValueError, msg
829
830 if triggerFlag not in self.validTriggers:
831 msg = "Invalid trigger flag for hardware breakpoint (%s)"
832 msg = msg % repr(triggerFlag)
833 raise ValueError, msg
834
835 Breakpoint.__init__(self, address, size, condition, action)
836 self.__trigger = triggerFlag
837 self.__watch = sizeFlag
838 self.__slot = None
839
856
858 """
859 Sets this breakpoint in the debug registers.
860
861 @type aThread: L{Thread}
862 @param aThread: Thread object.
863 """
864 if self.__slot is None:
865 aThread.suspend()
866 try:
867 ctx = aThread.get_context(win32.CONTEXT_DEBUG_REGISTERS)
868 self.__slot = DebugRegister.find_slot(ctx)
869 if self.__slot is None:
870 msg = "No available hardware breakpoint slots for thread ID %d"
871 msg = msg % aThread.get_tid()
872 raise RuntimeError, msg
873 DebugRegister.set_bp(ctx, self.__slot, self.get_address(),
874 self.__trigger, self.__watch)
875 aThread.set_context(ctx)
876 finally:
877 aThread.resume()
878
880 """
881 @rtype: int
882 @return: The debug register number used by this breakpoint,
883 or C{None} if the breakpoint is not active.
884 """
885 return self.__slot
886
888 """
889 @see: L{validTriggers}
890 @rtype: int
891 @return: The breakpoint trigger flag.
892 """
893 return self.__trigger
894
896 """
897 @see: L{validWatchSizes}
898 @rtype: int
899 @return: The breakpoint watch flag.
900 """
901 return self.__watch
902
903 - def disable(self, aProcess, aThread):
907
908 - def enable(self, aProcess, aThread):
912
917
918 - def running(self, aProcess, aThread):
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961 -class Hook (object):
962 """
963 Used by L{Debug.hook_function}.
964
965 This class acts as an action callback for code breakpoints set at the
966 beginning of a function. It automatically retrieves the parameters from
967 the stack, sets a breakpoint at the return address and retrieves the
968 return value from the function call.
969
970 @type useHardwareBreakpoints: bool
971 @cvar useHardwareBreakpoints: C{True} to try to use hardware breakpoints,
972 C{False} otherwise.
973 """
974
975
976
977
978
979
980
981
982
983
984
985
986 useHardwareBreakpoints = False
987
988 - def __init__(self, preCB = None, postCB = None, paramCount = 0):
989 """
990 @type preCB: function
991 @param preCB: (Optional) Callback triggered on function entry.
992
993 The signature for the callback can be something like this::
994
995 def pre_LoadLibraryEx(event, *params):
996 ra = params[0] # return address
997 argv = params[1:] # function parameters
998
999 # (...)
1000
1001 But if you passed the right number of arguments, you can also
1002 use a signature like this::
1003
1004 def pre_LoadLibraryEx(event, ra, lpFilename, hFile, dwFlags):
1005 szFilename = event.get_process().peek_string(lpFilename)
1006
1007 # (...)
1008
1009 In the above example, the value for C{paramCount} would be C{3}.
1010
1011 Note that the second example assumes all parameters are DWORDs.
1012 This may not always be so, especially in 64 bits Windows.
1013
1014 @type postCB: function
1015 @param postCB: (Optional) Callback triggered on function exit.
1016
1017 The signature for the callback would be something like this::
1018
1019 def post_LoadLibraryEx(event, return_value):
1020
1021 # (...)
1022
1023 @type paramCount: int
1024 @param paramCount:
1025 (Optional) Number of parameters for the C{preCB} callback,
1026 not counting the return address. Parameters are read from
1027 the stack and assumed to be DWORDs.
1028 """
1029 self.__paramCount = paramCount
1030 self.__preCB = preCB
1031 self.__postCB = postCB
1032 self.__paramStack = dict()
1033
1034
1035
1036
1037
1038
1039
1040
1042 """
1043 Handles the breakpoint event on entry of the function.
1044
1045 @type event: L{ExceptionEvent}
1046 @param event: Breakpoint hit event.
1047
1048 @raise WindowsError: An error occured.
1049 """
1050 debug = event.debug
1051
1052
1053 dwProcessId = event.get_pid()
1054 dwThreadId = event.get_tid()
1055 aProcess = event.get_process()
1056 aThread = event.get_thread()
1057 ra = aProcess.read_pointer( aThread.get_sp() )
1058 params = aThread.read_stack_dwords(self.__paramCount,
1059 offset = win32.sizeof(win32.LPVOID))
1060
1061
1062 self.__push_params(dwThreadId, params)
1063
1064
1065 if self.__postCB is not None:
1066
1067
1068 useHardwareBreakpoints = self.useHardwareBreakpoints
1069 if useHardwareBreakpoints:
1070 try:
1071 debug.define_hardware_breakpoint(
1072 dwThreadId,
1073 ra,
1074 event.debug.BP_BREAK_ON_EXECUTION,
1075 event.debug.BP_WATCH_BYTE,
1076 True,
1077 self.__postCallAction_hwbp
1078 )
1079 debug.enable_one_shot_hardware_breakpoint(dwThreadId, ra)
1080 except Exception, e:
1081
1082
1083 useHardwareBreakpoints = False
1084
1085
1086 if not useHardwareBreakpoints:
1087 debug.break_at(dwProcessId, ra, self.__postCallAction_codebp)
1088
1089
1090 try:
1091 self.__callHandler(self.__preCB, event, ra, *params)
1092
1093
1094 finally:
1095 if self.__postCB is None:
1096 self.__pop_params(dwThreadId)
1097
1098 - def __postCallAction_hwbp(self, event):
1099 """
1100 Handles hardware breakpoint events on return from the function.
1101
1102 @type event: L{ExceptionEvent}
1103 @param event: Single step event.
1104 """
1105
1106
1107
1108 tid = event.get_tid()
1109 address = event.breakpoint.get_address()
1110 event.debug.erase_hardware_breakpoint(tid, address)
1111
1112
1113 try:
1114 self.__postCallAction(event)
1115
1116
1117 finally:
1118 self.__pop_params(tid)
1119
1120 - def __postCallAction_codebp(self, event):
1121 """
1122 Handles code breakpoint events on return from the function.
1123
1124 @type event: L{ExceptionEvent}
1125 @param event: Breakpoint hit event.
1126 """
1127
1128
1129
1130
1131
1132
1133
1134 tid = event.get_tid()
1135 if not self.__paramStack.has_key(tid):
1136 return True
1137
1138
1139 pid = event.get_pid()
1140 address = event.breakpoint.get_address()
1141 event.debug.dont_break_at(pid, address)
1142
1143
1144 try:
1145 self.__postCallAction(event)
1146
1147
1148 finally:
1149 self.__pop_params(tid)
1150
1151 - def __postCallAction(self, event):
1152 """
1153 Calls the "post" callback.
1154
1155 @type event: L{ExceptionEvent}
1156 @param event: Breakpoint hit event.
1157 """
1158 aThread = event.get_thread()
1159 ctx = aThread.get_context(win32.CONTEXT_INTEGER)
1160 if win32.CONTEXT.arch == 'i386':
1161 retval = ctx['Eax']
1162 elif win32.CONTEXT.arch == 'amd64':
1163 retval = ctx['Rax']
1164
1165
1166 else:
1167 retval = None
1168 self.__callHandler(self.__postCB, event, retval)
1169
1171 """
1172 Calls a "pre" or "post" handler, if set.
1173
1174 @type callback: function
1175 @param callback: Callback function to call.
1176
1177 @type event: L{ExceptionEvent}
1178 @param event: Breakpoint hit event.
1179
1180 @type params: tuple
1181 @param params: Parameters for the callback function.
1182 """
1183 event.hook = self
1184 if callback is not None:
1185 callback(event, *params)
1186
1188 """
1189 Remembers the arguments tuple for the last call to the hooked function
1190 from this thread.
1191
1192 @type tid: int
1193 @param tid: Thread global ID.
1194
1195 @type params: tuple( arg, arg, arg... )
1196 @param params: Tuple of arguments.
1197 """
1198 stack = self.__paramStack.get( tid, [] )
1199 stack.append(params)
1200 self.__paramStack[tid] = stack
1201
1203 """
1204 Forgets the arguments tuple for the last call to the hooked function
1205 from this thread.
1206
1207 @type tid: int
1208 @param tid: Thread global ID.
1209 """
1210 stack = self.__paramStack[tid]
1211 stack.pop()
1212 if not stack:
1213 del self.__paramStack[tid]
1214
1216 """
1217 Returns the parameters found in the stack when the hooked function
1218 was last called by this thread.
1219
1220 @type tid: int
1221 @param tid: Thread global ID.
1222
1223 @rtype: tuple( arg, arg, arg... )
1224 @return: Tuple of arguments.
1225 """
1226 try:
1227 params = self.get_params_stack(tid)[-1]
1228 except IndexError:
1229 msg = "Hooked function called from thread %d already returned"
1230 raise IndexError, msg % tid
1231 return params
1232
1234 """
1235 Returns the parameters found in the stack each time the hooked function
1236 was called by this thread and haven't returned yet.
1237
1238 @type tid: int
1239 @param tid: Thread global ID.
1240
1241 @rtype: list of tuple( arg, arg, arg... )
1242 @return: List of argument tuples.
1243 """
1244 try:
1245 stack = self.__paramStack[tid]
1246 except KeyError:
1247 msg = "Hooked function was not called from thread %d"
1248 raise KeyError, msg % tid
1249 return stack
1250
1251 - def hook(self, debug, pid, address):
1252 """
1253 Installs the function hook at a given process and address.
1254
1255 @see: L{unhook}
1256
1257 @warning: Do not call from an function hook callback.
1258
1259 @type debug: L{Debug}
1260 @param debug: Debug object.
1261
1262 @type pid: int
1263 @param pid: Process ID.
1264
1265 @type address: int
1266 @param address: Function address.
1267 """
1268 return debug.break_at(pid, address, self)
1269
1270 - def unhook(self, debug, pid, address):
1271 """
1272 Removes the function hook at a given process and address.
1273
1274 @see: L{hook}
1275
1276 @warning: Do not call from an function hook callback.
1277
1278 @type debug: L{Debug}
1279 @param debug: Debug object.
1280
1281 @type pid: int
1282 @param pid: Process ID.
1283
1284 @type address: int
1285 @param address: Function address.
1286 """
1287 return debug.dont_break_at(pid, address)
1288
1289
1290
1292 """
1293 Used by L{EventHandler}.
1294
1295 This class acts as an action callback for code breakpoints set at the
1296 beginning of a function. It automatically retrieves the parameters from
1297 the stack, sets a breakpoint at the return address and retrieves the
1298 return value from the function call.
1299
1300 @see: L{EventHandler.apiHooks}
1301 """
1302
1303 - def __init__(self, eventHandler, procName, paramCount = 0):
1304 """
1305 @type eventHandler: L{EventHandler}
1306 @param eventHandler: Event handler instance.
1307
1308 @type procName: str
1309 @param procName: Procedure name.
1310 The pre and post callbacks will be deduced from it.
1311
1312 For example, if the procedure is "LoadLibraryEx" the callback
1313 routines will be "pre_LoadLibraryEx" and "post_LoadLibraryEx".
1314
1315 The signature for the callbacks can be something like this::
1316
1317 def pre_LoadLibraryEx(event, *params):
1318 ra = params[0] # return address
1319 argv = params[1:] # function parameters
1320
1321 # (...)
1322
1323 def post_LoadLibraryEx(event, return_value):
1324
1325 # (...)
1326
1327 But if you passed the right number of arguments, you can also
1328 use a signature like this::
1329
1330 def pre_LoadLibraryEx(event, ra, lpFilename, hFile, dwFlags):
1331 szFilename = event.get_process().peek_string(lpFilename)
1332
1333 # (...)
1334
1335 Note that the second example assumes all parameters are DWORDs.
1336 This may not always be so, especially in 64 bits Windows.
1337
1338 @type paramCount: int
1339 @param paramCount: (Optional) Number of parameters for the callback.
1340 Parameters are read from the stack and assumed to be DWORDs.
1341 The first parameter of the pre callback is always the return address.
1342 """
1343 self.__procName = procName
1344
1345 preCB = getattr(eventHandler, 'pre_%s' % procName, None)
1346 postCB = getattr(eventHandler, 'post_%s' % procName, None)
1347 Hook.__init__(self, preCB, postCB, paramCount)
1348
1349 - def hook(self, debug, pid, modName):
1350 """
1351 Installs the API hook on a given process and module.
1352
1353 @warning: Do not call from an API hook callback.
1354
1355 @type debug: L{Debug}
1356 @param debug: Debug object.
1357
1358 @type pid: int
1359 @param pid: Process ID.
1360
1361 @type modName: str
1362 @param modName: Module name.
1363 """
1364 address = debug.resolve_exported_function(pid, modName, self.__procName)
1365 if address is None:
1366 msg = "Cannot resolve symbol %s at module %s"
1367 msg = msg % (modName, self.__procName)
1368 raise ValueError, msg
1369 Hook.hook(self, debug, pid, address)
1370
1371 - def unhook(self, debug, pid, modName):
1372 """
1373 Removes the API hook from the given process and module.
1374
1375 @warning: Do not call from an API hook callback.
1376
1377 @type debug: L{Debug}
1378 @param debug: Debug object.
1379
1380 @type pid: int
1381 @param pid: Process ID.
1382
1383 @type modName: str
1384 @param modName: Module name.
1385 """
1386 address = debug.resolve_exported_function(pid, modName, self.__procName)
1387 Hook.unhook(self, debug, pid, address)
1388
1389
1390
1392 """
1393 Used by L{Debug.watch_buffer}.
1394
1395 This class acts as a condition callback for page breakpoints.
1396 It emulates page breakpoints that can overlap and/or take up less
1397 than a page's size.
1398 """
1399
1401 self.__ranges = dict()
1402
1403 - def add(self, address, size, action = None):
1404 """
1405 Adds a buffer to the watch object.
1406
1407 @type address: int
1408 @param address: Memory address of buffer to watch.
1409
1410 @type size: int
1411 @param size: Size in bytes of buffer to watch.
1412
1413 @type action: function
1414 @param action: (Optional) Action callback function.
1415
1416 See L{Debug.define_page_breakpoint} for more details.
1417 """
1418 key = (address, address + size)
1419 if key in self.__ranges:
1420 msg = "Buffer from %s to %s is already being watched"
1421 begin = HexDump.address(key[0])
1422 end = HexDump.address(key[1])
1423 raise RuntimeError, msg % (begin, end)
1424 self.__ranges[key] = action
1425
1426 - def remove(self, address, size):
1427 """
1428 Removes a buffer from the watch object.
1429
1430 @type address: int
1431 @param address: Memory address of buffer to stop watching.
1432
1433 @type size: int
1434 @param size: Size in bytes of buffer to stop watching.
1435 """
1436 key = (address, address + size)
1437 if key not in self.__ranges:
1438 msg = "No buffer watch set at %s-%s"
1439 begin = HexDump.address(key[0])
1440 end = HexDump.address(key[1])
1441 raise RuntimeError, msg % (begin, end)
1442 del self.__ranges[key]
1443
1444 - def exists(self, address, size):
1445 """
1446 @type address: int
1447 @param address: Memory address of buffer being watched.
1448
1449 @type size: int
1450 @param size: Size in bytes of buffer being watched.
1451
1452 @rtype: bool
1453 @return: C{True} if the buffer is being watched, C{False} otherwise.
1454 """
1455 key = (address, address + size)
1456 return key in self.__ranges
1457
1459 """
1460 @rtype: tuple( int, int )
1461 @return:
1462 Base address and size in pages required to watch all the buffers.
1463 """
1464 min_start = 0
1465 max_end = 0
1466 for ((start, end), action) in self.__ranges.iteritems():
1467 if start < min_start:
1468 min_start = start
1469 if end > max_end:
1470 max_end = end
1471 base = MemoryAddresses.align_address_to_page_start(min_start)
1472 size = max_end - min_start
1473 pages = MemoryAddresses.get_buffer_size_in_pages(min_start, size)
1474 return ( base, pages )
1475
1477 """
1478 @rtype: int
1479 @return: Number of buffers being watched.
1480 """
1481 return len(self.__ranges)
1482
1484 """
1485 Breakpoint condition callback.
1486
1487 This method will also call the action callbacks for each
1488 buffer being watched.
1489
1490 @type event: L{ExceptionEvent}
1491 @param event: Guard page exception event.
1492
1493 @rtype: bool
1494 @return: C{True} if the address being accessed belongs
1495 to at least one of the buffers that was being watched
1496 and had no action callback.
1497 """
1498 address = event.get_exception_information(1)
1499 bCondition = False
1500 for ((start, end), action) in self.__ranges.iteritems():
1501 bMatched = ( start <= address < end )
1502 if bMatched and action is not None:
1503 action(event)
1504 else:
1505 bCondition = bCondition or bMatched
1506 return bCondition
1507
1508
1509
1511 """
1512 Encapsulates the capability to contain Breakpoint objects.
1513
1514 @group Breakpoints:
1515 break_at, watch_variable, watch_buffer, hook_function,
1516 dont_break_at, dont_watch_variable, dont_watch_buffer,
1517 dont_hook_function, unhook_function
1518
1519 @group Stalking:
1520 stalk_at, stalk_variable, stalk_buffer, stalk_function,
1521 dont_stalk_at, dont_stalk_variable, dont_stalk_buffer,
1522 dont_stalk_function
1523
1524 @group Tracing:
1525 is_tracing, get_traced_tids,
1526 start_tracing, stop_tracing,
1527 start_tracing_process, stop_tracing_process,
1528 start_tracing_all, stop_tracing_all
1529
1530 @group Symbols:
1531 resolve_label, resolve_exported_function
1532
1533 @group Advanced breakpoint use:
1534 define_code_breakpoint,
1535 define_page_breakpoint,
1536 define_hardware_breakpoint,
1537 has_code_breakpoint,
1538 has_page_breakpoint,
1539 has_hardware_breakpoint,
1540 get_code_breakpoint,
1541 get_page_breakpoint,
1542 get_hardware_breakpoint,
1543 erase_code_breakpoint,
1544 erase_page_breakpoint,
1545 erase_hardware_breakpoint,
1546 enable_code_breakpoint,
1547 enable_page_breakpoint,
1548 enable_hardware_breakpoint,
1549 enable_one_shot_code_breakpoint,
1550 enable_one_shot_page_breakpoint,
1551 enable_one_shot_hardware_breakpoint,
1552 disable_code_breakpoint,
1553 disable_page_breakpoint,
1554 disable_hardware_breakpoint
1555
1556 @group Listing breakpoints:
1557 get_all_breakpoints,
1558 get_all_code_breakpoints,
1559 get_all_page_breakpoints,
1560 get_all_hardware_breakpoints,
1561 get_process_breakpoints,
1562 get_process_code_breakpoints,
1563 get_process_page_breakpoints,
1564 get_process_hardware_breakpoints,
1565 get_thread_hardware_breakpoints
1566
1567 @group Batch operations on breakpoints:
1568 enable_all_breakpoints,
1569 enable_one_shot_all_breakpoints,
1570 disable_all_breakpoints,
1571 erase_all_breakpoints,
1572 enable_process_breakpoints,
1573 enable_one_shot_process_breakpoints,
1574 disable_process_breakpoints,
1575 erase_process_breakpoints
1576
1577 @group Event notifications (private):
1578 notify_guard_page,
1579 notify_breakpoint,
1580 notify_single_step,
1581 notify_exit_thread,
1582 notify_exit_process
1583
1584 @group Breakpoint types:
1585 BP_TYPE_ANY, BP_TYPE_CODE, BP_TYPE_PAGE, BP_TYPE_HARDWARE
1586 @group Breakpoint states:
1587 BP_STATE_DISABLED, BP_STATE_ENABLED, BP_STATE_ONESHOT, BP_STATE_RUNNING
1588 @group Memory breakpoint trigger flags:
1589 BP_BREAK_ON_EXECUTION, BP_BREAK_ON_WRITE, BP_BREAK_ON_ACCESS
1590 @group Memory breakpoint size flags:
1591 BP_WATCH_BYTE, BP_WATCH_WORD, BP_WATCH_DWORD, BP_WATCH_QWORD
1592
1593 @type BP_TYPE_ANY: int
1594 @cvar BP_TYPE_ANY: To get all breakpoints
1595 @type BP_TYPE_CODE: int
1596 @cvar BP_TYPE_CODE: To get code breakpoints only
1597 @type BP_TYPE_PAGE: int
1598 @cvar BP_TYPE_PAGE: To get page breakpoints only
1599 @type BP_TYPE_HARDWARE: int
1600 @cvar BP_TYPE_HARDWARE: To get hardware breakpoints only
1601
1602 @type BP_STATE_DISABLED: int
1603 @cvar BP_STATE_DISABLED: Breakpoint is disabled.
1604 @type BP_STATE_ENABLED: int
1605 @cvar BP_STATE_ENABLED: Breakpoint is enabled.
1606 @type BP_STATE_ONESHOT: int
1607 @cvar BP_STATE_ONESHOT: Breakpoint is enabled for one shot.
1608 @type BP_STATE_RUNNING: int
1609 @cvar BP_STATE_RUNNING: Breakpoint is running (recently hit).
1610
1611 @type BP_BREAK_ON_EXECUTION: int
1612 @cvar BP_BREAK_ON_EXECUTION: Break on code execution.
1613 @type BP_BREAK_ON_WRITE: int
1614 @cvar BP_BREAK_ON_WRITE: Break on memory write.
1615 @type BP_BREAK_ON_ACCESS: int
1616 @cvar BP_BREAK_ON_ACCESS: Break on memory read or write.
1617 """
1618
1619
1620 BP_TYPE_ANY = 0
1621 BP_TYPE_CODE = 1
1622 BP_TYPE_PAGE = 2
1623 BP_TYPE_HARDWARE = 3
1624
1625
1626 BP_STATE_DISABLED = Breakpoint.DISABLED
1627 BP_STATE_ENABLED = Breakpoint.ENABLED
1628 BP_STATE_ONESHOT = Breakpoint.ONESHOT
1629 BP_STATE_RUNNING = Breakpoint.RUNNING
1630
1631
1632 BP_BREAK_ON_EXECUTION = HardwareBreakpoint.BREAK_ON_EXECUTION
1633 BP_BREAK_ON_WRITE = HardwareBreakpoint.BREAK_ON_WRITE
1634 BP_BREAK_ON_IO_ACCESS = HardwareBreakpoint.BREAK_ON_IO_ACCESS
1635 BP_BREAK_ON_ACCESS = HardwareBreakpoint.BREAK_ON_ACCESS
1636
1637
1638 BP_WATCH_BYTE = HardwareBreakpoint.WATCH_BYTE
1639 BP_WATCH_WORD = HardwareBreakpoint.WATCH_WORD
1640 BP_WATCH_QWORD = HardwareBreakpoint.WATCH_QWORD
1641 BP_WATCH_DWORD = HardwareBreakpoint.WATCH_DWORD
1642
1644 self.__codeBP = dict()
1645 self.__pageBP = dict()
1646 self.__hardwareBP = dict()
1647 self.__runningBP = dict()
1648 self.__tracing = set()
1649
1650
1651
1652
1653
1654
1655
1657 "Auxiliary method."
1658 return tid in self.__runningBP and self.__runningBP[tid]
1659
1661 "Auxiliary method."
1662 return self.__runningBP[tid].pop()
1663
1665 "Auxiliary method."
1666 if tid not in self.__runningBP:
1667 self.__runningBP[tid] = set()
1668 self.__runningBP[tid].add(bp)
1669
1671 "Auxiliary method."
1672 self.__runningBP[tid].remove(bp)
1673 if not self.__runningBP[tid]:
1674 del self.__runningBP[tid]
1675
1677 "Auxiliary method."
1678 for (tid, bpset) in self.__runningBP.iteritems():
1679 if bp in bpset:
1680 bpset.remove(bp)
1681 self.system.get_thread(tid).clear_tf()
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1717
1719 """
1720 Auxiliary method for L{notify_exit_thread} and L{notify_exit_process}.
1721 """
1722 tid = event.get_tid()
1723
1724
1725 try:
1726 for bp in self.__runningBP[tid]:
1727 self.__cleanup_breakpoint( event, bp )
1728 del self.__runningBP[tid]
1729 except KeyError:
1730 pass
1731
1732
1733 try:
1734 for bp in self.__hardwareBP[tid]:
1735 self.__cleanup_breakpoint( event, bp )
1736 del self.__hardwareBP[tid]
1737 except KeyError:
1738 pass
1739
1740
1741 if tid in self.__tracing:
1742 self.__tracing.remove(tid)
1743
1745 """
1746 Auxiliary method for L{notify_exit_process}.
1747 """
1748 pid = event.get_pid()
1749 process = event.get_process()
1750
1751
1752 for (bp_pid, bp_address) in self.__codeBP.keys():
1753 if bp_pid == pid:
1754 self.__cleanup_breakpoint( event, self.__codeBP[(bp_pid, bp_address)] )
1755 del self.__codeBP[(bp_pid, bp_address)]
1756
1757
1758 for (bp_pid, bp_address) in self.__pageBP.keys():
1759 if bp_pid == pid:
1760 self.__cleanup_breakpoint( event, self.__pageBP[(bp_pid, bp_address)] )
1761 del self.__pageBP[(bp_pid, bp_address)]
1762
1763
1764
1765
1766
1767
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1824 """
1825 Creates a disabled code breakpoint at the given address.
1826
1827 @see:
1828 L{has_code_breakpoint},
1829 L{get_code_breakpoint},
1830 L{enable_code_breakpoint},
1831 L{enable_one_shot_code_breakpoint},
1832 L{disable_code_breakpoint},
1833 L{erase_code_breakpoint}
1834
1835 @type dwProcessId: int
1836 @param dwProcessId: Process global ID.
1837
1838 @type address: int
1839 @param address: Memory address of the code instruction to break at.
1840
1841 @type condition: function
1842 @param condition: (Optional) Condition callback function.
1843
1844 The callback signature is::
1845
1846 def condition_callback(event):
1847 return True # returns True or False
1848
1849 Where B{event} is an L{Event} object,
1850 and the return value is a boolean
1851 (C{True} to dispatch the event, C{False} otherwise).
1852
1853 @type action: function
1854 @param action: (Optional) Action callback function.
1855 If specified, the event is handled by this callback instead of
1856 being dispatched normally.
1857
1858 The callback signature is::
1859
1860 def action_callback(event):
1861 pass # no return value
1862
1863 Where B{event} is an L{Event} object,
1864 and the return value is a boolean
1865 (C{True} to dispatch the event, C{False} otherwise).
1866
1867 @rtype: L{CodeBreakpoint}
1868 @return: The code breakpoint object.
1869 """
1870 process = self.system.get_process(dwProcessId)
1871 bp = CodeBreakpoint(address, condition, action)
1872
1873 key = (dwProcessId, bp.get_address())
1874 if key in self.__codeBP:
1875 msg = "Already exists (PID %d) : %r"
1876 raise KeyError, msg % (dwProcessId, self.__codeBP[key])
1877 self.__codeBP[key] = bp
1878 return bp
1879
1880 - def define_page_breakpoint(self, dwProcessId, address, pages = 1,
1881 condition = True,
1882 action = None):
1883 """
1884 Creates a disabled page breakpoint at the given address.
1885
1886 @see:
1887 L{has_page_breakpoint},
1888 L{get_page_breakpoint},
1889 L{enable_page_breakpoint},
1890 L{enable_one_shot_page_breakpoint},
1891 L{disable_page_breakpoint},
1892 L{erase_page_breakpoint}
1893
1894 @type dwProcessId: int
1895 @param dwProcessId: Process global ID.
1896
1897 @type address: int
1898 @param address: Memory address of the first page to watch.
1899
1900 @type pages: int
1901 @param pages: Number of pages to watch.
1902
1903 @type condition: function
1904 @param condition: (Optional) Condition callback function.
1905
1906 The callback signature is::
1907
1908 def condition_callback(event):
1909 return True # returns True or False
1910
1911 Where B{event} is an L{Event} object,
1912 and the return value is a boolean
1913 (C{True} to dispatch the event, C{False} otherwise).
1914
1915 @type action: function
1916 @param action: (Optional) Action callback function.
1917 If specified, the event is handled by this callback instead of
1918 being dispatched normally.
1919
1920 The callback signature is::
1921
1922 def action_callback(event):
1923 pass # no return value
1924
1925 Where B{event} is an L{Event} object,
1926 and the return value is a boolean
1927 (C{True} to dispatch the event, C{False} otherwise).
1928
1929 @rtype: L{PageBreakpoint}
1930 @return: The page breakpoint object.
1931 """
1932 process = self.system.get_process(dwProcessId)
1933 bp = PageBreakpoint(address, pages, condition, action)
1934 begin = bp.get_address()
1935 end = begin + bp.get_size()
1936
1937 address = begin
1938 pageSize = System.pageSize
1939 while address < end:
1940 key = (dwProcessId, address)
1941 if key in self.__pageBP:
1942 msg = "Already exists (PID %d) : %r"
1943 msg = msg % (dwProcessId, self.__pageBP[key])
1944 raise KeyError, msg
1945 address = address + pageSize
1946
1947 address = begin
1948 while address < end:
1949 key = (dwProcessId, address)
1950 self.__pageBP[key] = bp
1951 address = address + pageSize
1952 return bp
1953
1959 """
1960 Creates a disabled hardware breakpoint at the given address.
1961
1962 @see:
1963 L{has_hardware_breakpoint},
1964 L{get_hardware_breakpoint},
1965 L{enable_hardware_breakpoint},
1966 L{enable_one_shot_hardware_breakpoint},
1967 L{disable_hardware_breakpoint},
1968 L{erase_hardware_breakpoint}
1969
1970 @note:
1971 Hardware breakpoints do not seem to work properly on VirtualBox.
1972 See U{http://www.virtualbox.org/ticket/477}.
1973
1974 @type dwThreadId: int
1975 @param dwThreadId: Thread global ID.
1976
1977 @type address: int
1978 @param address: Memory address to watch.
1979
1980 @type triggerFlag: int
1981 @param triggerFlag: Trigger of breakpoint. Must be one of the following:
1982
1983 - L{BP_BREAK_ON_EXECUTION}
1984
1985 Break on code execution.
1986
1987 - L{BP_BREAK_ON_WRITE}
1988
1989 Break on memory read or write.
1990
1991 - L{BP_BREAK_ON_ACCESS}
1992
1993 Break on memory write.
1994
1995 @type sizeFlag: int
1996 @param sizeFlag: Size of breakpoint. Must be one of the following:
1997
1998 - L{BP_WATCH_BYTE}
1999
2000 One (1) byte in size.
2001
2002 - L{BP_WATCH_WORD}
2003
2004 Two (2) bytes in size.
2005
2006 - L{BP_WATCH_DWORD}
2007
2008 Four (4) bytes in size.
2009
2010 - L{BP_WATCH_QWORD}
2011
2012 Eight (8) bytes in size.
2013
2014 @type condition: function
2015 @param condition: (Optional) Condition callback function.
2016
2017 The callback signature is::
2018
2019 def condition_callback(event):
2020 return True # returns True or False
2021
2022 Where B{event} is an L{Event} object,
2023 and the return value is a boolean
2024 (C{True} to dispatch the event, C{False} otherwise).
2025
2026 @type action: function
2027 @param action: (Optional) Action callback function.
2028 If specified, the event is handled by this callback instead of
2029 being dispatched normally.
2030
2031 The callback signature is::
2032
2033 def action_callback(event):
2034 pass # no return value
2035
2036 Where B{event} is an L{Event} object,
2037 and the return value is a boolean
2038 (C{True} to dispatch the event, C{False} otherwise).
2039
2040 @rtype: L{HardwareBreakpoint}
2041 @return: The hardware breakpoint object.
2042 """
2043 thread = self.system.get_thread(dwThreadId)
2044 bp = HardwareBreakpoint(address, triggerFlag, sizeFlag, condition,
2045 action)
2046 begin = bp.get_address()
2047 end = begin + bp.get_size()
2048
2049 if dwThreadId in self.__hardwareBP:
2050 bpSet = self.__hardwareBP[dwThreadId]
2051 for oldbp in bpSet:
2052 old_begin = oldbp.get_address()
2053 old_end = old_begin + oldbp.get_size()
2054 if MemoryAddresses.do_ranges_intersect(begin, end, old_begin,
2055 old_end):
2056 msg = "Already exists (TID %d) : %r" % (dwThreadId, oldbp)
2057 raise KeyError, msg
2058 else:
2059 bpSet = set()
2060 self.__hardwareBP[dwThreadId] = bpSet
2061 bpSet.add(bp)
2062 return bp
2063
2064
2065
2066
2067
2069 """
2070 Checks if a code breakpoint is defined at the given address.
2071
2072 @see:
2073 L{define_code_breakpoint},
2074 L{get_code_breakpoint},
2075 L{erase_code_breakpoint},
2076 L{enable_code_breakpoint},
2077 L{enable_one_shot_code_breakpoint},
2078 L{disable_code_breakpoint}
2079
2080 @type dwProcessId: int
2081 @param dwProcessId: Process global ID.
2082
2083 @type address: int
2084 @param address: Memory address of breakpoint.
2085
2086 @rtype: bool
2087 @return: C{True} if the breakpoint is defined, C{False} otherwise.
2088 """
2089 return (dwProcessId, address) in self.__codeBP
2090
2091 - def has_page_breakpoint(self, dwProcessId, address):
2092 """
2093 Checks if a page breakpoint is defined at the given address.
2094
2095 @see:
2096 L{define_page_breakpoint},
2097 L{get_page_breakpoint},
2098 L{erase_page_breakpoint},
2099 L{enable_page_breakpoint},
2100 L{enable_one_shot_page_breakpoint},
2101 L{disable_page_breakpoint}
2102
2103 @type dwProcessId: int
2104 @param dwProcessId: Process global ID.
2105
2106 @type address: int
2107 @param address: Memory address of breakpoint.
2108
2109 @rtype: bool
2110 @return: C{True} if the breakpoint is defined, C{False} otherwise.
2111 """
2112 return (dwProcessId, address) in self.__pageBP
2113
2115 """
2116 Checks if a hardware breakpoint is defined at the given address.
2117
2118 @see:
2119 L{define_hardware_breakpoint},
2120 L{get_hardware_breakpoint},
2121 L{erase_hardware_breakpoint},
2122 L{enable_hardware_breakpoint},
2123 L{enable_one_shot_hardware_breakpoint},
2124 L{disable_hardware_breakpoint}
2125
2126 @type dwThreadId: int
2127 @param dwThreadId: Thread global ID.
2128
2129 @type address: int
2130 @param address: Memory address of breakpoint.
2131
2132 @rtype: bool
2133 @return: C{True} if the breakpoint is defined, C{False} otherwise.
2134 """
2135 if dwThreadId in self.__hardwareBP:
2136 bpSet = self.__hardwareBP[dwThreadId]
2137 for bp in bpSet:
2138 if bp.get_address() == address:
2139 return True
2140 return False
2141
2142
2143
2144
2145
2147 """
2148 Returns the internally used breakpoint object,
2149 for the code breakpoint defined at the given address.
2150
2151 @warning: It's usually best to call the L{Debug} methods
2152 instead of accessing the breakpoint objects directly.
2153
2154 @see:
2155 L{define_code_breakpoint},
2156 L{has_code_breakpoint},
2157 L{enable_code_breakpoint},
2158 L{enable_one_shot_code_breakpoint},
2159 L{disable_code_breakpoint},
2160 L{erase_code_breakpoint}
2161
2162 @type dwProcessId: int
2163 @param dwProcessId: Process global ID.
2164
2165 @type address: int
2166 @param address: Memory address where the breakpoint is defined.
2167
2168 @rtype: L{CodeBreakpoint}
2169 @return: The code breakpoint object.
2170 """
2171 key = (dwProcessId, address)
2172 if key not in self.__codeBP:
2173 msg = "No breakpoint at process %d, address %s"
2174 address = HexDump.address(address)
2175 raise KeyError, msg % (dwProcessId, address)
2176 return self.__codeBP[key]
2177
2178 - def get_page_breakpoint(self, dwProcessId, address):
2179 """
2180 Returns the internally used breakpoint object,
2181 for the page breakpoint defined at the given address.
2182
2183 @warning: It's usually best to call the L{Debug} methods
2184 instead of accessing the breakpoint objects directly.
2185
2186 @see:
2187 L{define_page_breakpoint},
2188 L{has_page_breakpoint},
2189 L{enable_page_breakpoint},
2190 L{enable_one_shot_page_breakpoint},
2191 L{disable_page_breakpoint},
2192 L{erase_page_breakpoint}
2193
2194 @type dwProcessId: int
2195 @param dwProcessId: Process global ID.
2196
2197 @type address: int
2198 @param address: Memory address where the breakpoint is defined.
2199
2200 @rtype: L{PageBreakpoint}
2201 @return: The page breakpoint object.
2202 """
2203 key = (dwProcessId, address)
2204 if key not in self.__pageBP:
2205 msg = "No breakpoint at process %d, address %s"
2206 address = HexDump.addresS(address)
2207 raise KeyError, msg % (dwProcessId, address)
2208 return self.__pageBP[key]
2209
2211 """
2212 Returns the internally used breakpoint object,
2213 for the code breakpoint defined at the given address.
2214
2215 @warning: It's usually best to call the L{Debug} methods
2216 instead of accessing the breakpoint objects directly.
2217
2218 @see:
2219 L{define_hardware_breakpoint},
2220 L{has_hardware_breakpoint},
2221 L{get_code_breakpoint},
2222 L{enable_hardware_breakpoint},
2223 L{enable_one_shot_hardware_breakpoint},
2224 L{disable_hardware_breakpoint},
2225 L{erase_hardware_breakpoint}
2226
2227 @type dwThreadId: int
2228 @param dwThreadId: Thread global ID.
2229
2230 @type address: int
2231 @param address: Memory address where the breakpoint is defined.
2232
2233 @rtype: L{HardwareBreakpoint}
2234 @return: The hardware breakpoint object.
2235 """
2236 if dwThreadId not in self.__hardwareBP:
2237 msg = "No hardware breakpoints set for thread %d"
2238 raise KeyError, msg % dwThreadId
2239 for bp in self.__hardwareBP[dwThreadId]:
2240 if bp.is_here(address):
2241 return bp
2242 msg = "No hardware breakpoint at thread %d, address %s"
2243 raise KeyError, msg % (dwThreadId, HexDump.address(address))
2244
2245
2246
2247
2248
2250 """
2251 Enables the code breakpoint at the given address.
2252
2253 @see:
2254 L{define_code_breakpoint},
2255 L{has_code_breakpoint},
2256 L{enable_one_shot_code_breakpoint},
2257 L{disable_code_breakpoint}
2258 L{erase_code_breakpoint},
2259
2260 @type dwProcessId: int
2261 @param dwProcessId: Process global ID.
2262
2263 @type address: int
2264 @param address: Memory address of breakpoint.
2265 """
2266 p = self.system.get_process(dwProcessId)
2267 bp = self.get_code_breakpoint(dwProcessId, address)
2268 if bp.is_running():
2269 self.__del_running_bp_from_all_threads(bp)
2270 bp.enable(p, None)
2271
2272 - def enable_page_breakpoint(self, dwProcessId, address):
2273 """
2274 Enables the page breakpoint at the given address.
2275
2276 @see:
2277 L{define_page_breakpoint},
2278 L{has_page_breakpoint},
2279 L{get_page_breakpoint},
2280 L{enable_one_shot_page_breakpoint},
2281 L{disable_page_breakpoint}
2282 L{erase_page_breakpoint},
2283
2284 @type dwProcessId: int
2285 @param dwProcessId: Process global ID.
2286
2287 @type address: int
2288 @param address: Memory address of breakpoint.
2289 """
2290 p = self.system.get_process(dwProcessId)
2291 bp = self.get_page_breakpoint(dwProcessId, address)
2292 if bp.is_running():
2293 self.__del_running_bp_from_all_threads(bp)
2294 bp.enable(p, None)
2295
2297 """
2298 Enables the hardware breakpoint at the given address.
2299
2300 @see:
2301 L{define_hardware_breakpoint},
2302 L{has_hardware_breakpoint},
2303 L{get_hardware_breakpoint},
2304 L{enable_one_shot_hardware_breakpoint},
2305 L{disable_hardware_breakpoint}
2306 L{erase_hardware_breakpoint},
2307
2308 @note: Do not set hardware breakpoints while processing the system
2309 breakpoint event.
2310
2311 @type dwThreadId: int
2312 @param dwThreadId: Thread global ID.
2313
2314 @type address: int
2315 @param address: Memory address of breakpoint.
2316 """
2317 t = self.system.get_thread(dwThreadId)
2318 bp = self.get_hardware_breakpoint(dwThreadId, address)
2319 if bp.is_running():
2320 self.__del_running_bp_from_all_threads(bp)
2321 bp.enable(None, t)
2322
2324 """
2325 Enables the code breakpoint at the given address for only one shot.
2326
2327 @see:
2328 L{define_code_breakpoint},
2329 L{has_code_breakpoint},
2330 L{get_code_breakpoint},
2331 L{enable_code_breakpoint},
2332 L{disable_code_breakpoint}
2333 L{erase_code_breakpoint},
2334
2335 @type dwProcessId: int
2336 @param dwProcessId: Process global ID.
2337
2338 @type address: int
2339 @param address: Memory address of breakpoint.
2340 """
2341 p = self.system.get_process(dwProcessId)
2342 bp = self.get_code_breakpoint(dwProcessId, address)
2343 if bp.is_running():
2344 self.__del_running_bp_from_all_threads(bp)
2345 bp.one_shot(p, None)
2346
2347 - def enable_one_shot_page_breakpoint(self, dwProcessId, address):
2348 """
2349 Enables the page breakpoint at the given address for only one shot.
2350
2351 @see:
2352 L{define_page_breakpoint},
2353 L{has_page_breakpoint},
2354 L{get_page_breakpoint},
2355 L{enable_page_breakpoint},
2356 L{disable_page_breakpoint}
2357 L{erase_page_breakpoint},
2358
2359 @type dwProcessId: int
2360 @param dwProcessId: Process global ID.
2361
2362 @type address: int
2363 @param address: Memory address of breakpoint.
2364 """
2365 p = self.system.get_process(dwProcessId)
2366 bp = self.get_page_breakpoint(dwProcessId, address)
2367 if bp.is_running():
2368 self.__del_running_bp_from_all_threads(bp)
2369 bp.one_shot(p, None)
2370
2372 """
2373 Enables the hardware breakpoint at the given address for only one shot.
2374
2375 @see:
2376 L{define_hardware_breakpoint},
2377 L{has_hardware_breakpoint},
2378 L{get_hardware_breakpoint},
2379 L{enable_hardware_breakpoint},
2380 L{disable_hardware_breakpoint}
2381 L{erase_hardware_breakpoint},
2382
2383 @type dwThreadId: int
2384 @param dwThreadId: Thread global ID.
2385
2386 @type address: int
2387 @param address: Memory address of breakpoint.
2388 """
2389 t = self.system.get_thread(dwThreadId)
2390 bp = self.get_hardware_breakpoint(dwThreadId, address)
2391 if bp.is_running():
2392 self.__del_running_bp_from_all_threads(bp)
2393 bp.one_shot(None, t)
2394
2396 """
2397 Disables the code breakpoint at the given address.
2398
2399 @see:
2400 L{define_code_breakpoint},
2401 L{has_code_breakpoint},
2402 L{get_code_breakpoint},
2403 L{enable_code_breakpoint}
2404 L{enable_one_shot_code_breakpoint},
2405 L{erase_code_breakpoint},
2406
2407 @type dwProcessId: int
2408 @param dwProcessId: Process global ID.
2409
2410 @type address: int
2411 @param address: Memory address of breakpoint.
2412 """
2413 p = self.system.get_process(dwProcessId)
2414 bp = self.get_code_breakpoint(dwProcessId, address)
2415 if bp.is_running():
2416 self.__del_running_bp_from_all_threads(bp)
2417 bp.disable(p, None)
2418
2419 - def disable_page_breakpoint(self, dwProcessId, address):
2420 """
2421 Disables the page breakpoint at the given address.
2422
2423 @see:
2424 L{define_page_breakpoint},
2425 L{has_page_breakpoint},
2426 L{get_page_breakpoint},
2427 L{enable_page_breakpoint}
2428 L{enable_one_shot_page_breakpoint},
2429 L{erase_page_breakpoint},
2430
2431 @type dwProcessId: int
2432 @param dwProcessId: Process global ID.
2433
2434 @type address: int
2435 @param address: Memory address of breakpoint.
2436 """
2437 p = self.system.get_process(dwProcessId)
2438 bp = self.get_page_breakpoint(dwProcessId, address)
2439 if bp.is_running():
2440 self.__del_running_bp_from_all_threads(bp)
2441 bp.disable(p, None)
2442
2444 """
2445 Disables the hardware breakpoint at the given address.
2446
2447 @see:
2448 L{define_hardware_breakpoint},
2449 L{has_hardware_breakpoint},
2450 L{get_hardware_breakpoint},
2451 L{enable_hardware_breakpoint}
2452 L{enable_one_shot_hardware_breakpoint},
2453 L{erase_hardware_breakpoint},
2454
2455 @type dwThreadId: int
2456 @param dwThreadId: Thread global ID.
2457
2458 @type address: int
2459 @param address: Memory address of breakpoint.
2460 """
2461 t = self.system.get_thread(dwThreadId)
2462 p = t.get_process()
2463 bp = self.get_hardware_breakpoint(dwThreadId, address)
2464 if bp.is_running():
2465 self.__del_running_bp(dwThreadId, bp)
2466 bp.disable(p, t)
2467
2468
2469
2470
2471
2473 """
2474 Erases the code breakpoint at the given address.
2475
2476 @see:
2477 L{define_code_breakpoint},
2478 L{has_code_breakpoint},
2479 L{get_code_breakpoint},
2480 L{enable_code_breakpoint},
2481 L{enable_one_shot_code_breakpoint},
2482 L{disable_code_breakpoint}
2483
2484 @type dwProcessId: int
2485 @param dwProcessId: Process global ID.
2486
2487 @type address: int
2488 @param address: Memory address of breakpoint.
2489 """
2490 bp = self.get_code_breakpoint(dwProcessId, address)
2491 if not bp.is_disabled():
2492 self.disable_code_breakpoint(dwProcessId, address)
2493 del self.__codeBP[ (dwProcessId, address) ]
2494
2495 - def erase_page_breakpoint(self, dwProcessId, address):
2496 """
2497 Erases the page breakpoint at the given address.
2498
2499 @see:
2500 L{define_page_breakpoint},
2501 L{has_page_breakpoint},
2502 L{get_page_breakpoint},
2503 L{enable_page_breakpoint},
2504 L{enable_one_shot_page_breakpoint},
2505 L{disable_page_breakpoint}
2506
2507 @type dwProcessId: int
2508 @param dwProcessId: Process global ID.
2509
2510 @type address: int
2511 @param address: Memory address of breakpoint.
2512 """
2513 bp = self.get_page_breakpoint(dwProcessId, address)
2514 begin = bp.get_address()
2515 end = begin + bp.get_size()
2516 if not bp.is_disabled():
2517 self.disable_page_breakpoint(dwProcessId, address)
2518 address = begin
2519 pageSize = System.pageSize
2520 while address < end:
2521 del self.__pageBP[ (dwProcessId, address) ]
2522 address = address + pageSize
2523
2525 """
2526 Erases the hardware breakpoint at the given address.
2527
2528 @see:
2529 L{define_hardware_breakpoint},
2530 L{has_hardware_breakpoint},
2531 L{get_hardware_breakpoint},
2532 L{enable_hardware_breakpoint},
2533 L{enable_one_shot_hardware_breakpoint},
2534 L{disable_hardware_breakpoint}
2535
2536 @type dwThreadId: int
2537 @param dwThreadId: Thread global ID.
2538
2539 @type address: int
2540 @param address: Memory address of breakpoint.
2541 """
2542 bp = self.get_hardware_breakpoint(dwThreadId, address)
2543 if not bp.is_disabled():
2544 self.disable_hardware_breakpoint(dwThreadId, address)
2545 bpSet = self.__hardwareBP[dwThreadId]
2546 bpSet.remove(bp)
2547 if not bpSet:
2548 del self.__hardwareBP[dwThreadId]
2549
2550
2551
2552
2553
2555 """
2556 Returns all breakpoint objects as a list of tuples.
2557
2558 Each tuple contains:
2559 - Process global ID to which the breakpoint applies.
2560 - Thread global ID to which the breakpoint applies, or C{None}.
2561 - The L{Breakpoint} object itself.
2562
2563 @note: If you're only interested in a specific breakpoint type, or in
2564 breakpoints for a specific process or thread, it's probably faster
2565 to call one of the following methods:
2566 - L{get_all_code_breakpoints}
2567 - L{get_all_page_breakpoints}
2568 - L{get_all_hardware_breakpoints}
2569 - L{get_process_code_breakpoints}
2570 - L{get_process_page_breakpoints}
2571 - L{get_process_hardware_breakpoints}
2572 - L{get_thread_hardware_breakpoints}
2573
2574 @rtype: list of tuple( pid, tid, bp )
2575 @return: List of all breakpoints.
2576 """
2577 bplist = list()
2578
2579
2580 for (pid, bp) in self.get_all_code_breakpoints():
2581 bplist.append( (pid, None, bp) )
2582
2583
2584 for (pid, bp) in self.get_all_page_breakpoints():
2585 bplist.append( (pid, None, bp) )
2586
2587
2588 for (tid, bp) in self.get_all_hardware_breakpoints():
2589 pid = self.system.get_thread(tid).get_pid()
2590 bplist.append( (pid, tid, bp) )
2591
2592
2593 return bplist
2594
2596 """
2597 @rtype: list of tuple( int, L{CodeBreakpoint} )
2598 @return: All code breakpoints as a list of tuples (pid, bp).
2599 """
2600 return [ (pid, bp) for ((pid, address), bp) in self.__codeBP.iteritems() ]
2601
2603 """
2604 @rtype: list of tuple( int, L{PageBreakpoint} )
2605 @return: All page breakpoints as a list of tuples (pid, bp).
2606 """
2607
2608 result = set()
2609 for ((pid, address), bp) in self.__pageBP.iteritems():
2610 result.add( (pid, bp) )
2611 return list(result)
2612
2614 """
2615 @rtype: list of tuple( int, L{HardwareBreakpoint} )
2616 @return: All hardware breakpoints as a list of tuples (tid, bp).
2617 """
2618 result = list()
2619 for (tid, bplist) in self.__hardwareBP.iteritems():
2620 for bp in bplist:
2621 result.append( (tid, bp) )
2622 return result
2623
2625 """
2626 Returns all breakpoint objects for the given process as a list of tuples.
2627
2628 Each tuple contains:
2629 - Process global ID to which the breakpoint applies.
2630 - Thread global ID to which the breakpoint applies, or C{None}.
2631 - The L{Breakpoint} object itself.
2632
2633 @note: If you're only interested in a specific breakpoint type, or in
2634 breakpoints for a specific process or thread, it's probably faster
2635 to call one of the following methods:
2636 - L{get_all_code_breakpoints}
2637 - L{get_all_page_breakpoints}
2638 - L{get_all_hardware_breakpoints}
2639 - L{get_process_code_breakpoints}
2640 - L{get_process_page_breakpoints}
2641 - L{get_process_hardware_breakpoints}
2642 - L{get_thread_hardware_breakpoints}
2643
2644 @type dwProcessId: int
2645 @param dwProcessId: Process global ID.
2646
2647 @rtype: list of tuple( pid, tid, bp )
2648 @return: List of all breakpoints for the given process.
2649 """
2650 bplist = list()
2651
2652
2653 for bp in self.get_process_code_breakpoints(dwProcessId):
2654 bplist.append( (dwProcessId, None, bp) )
2655
2656
2657 for bp in self.get_process_page_breakpoints(dwProcessId):
2658 bplist.append( (dwProcessId, None, bp) )
2659
2660
2661 for (tid, bp) in self.get_process_hardware_breakpoints(dwProcessId):
2662 pid = self.system.get_thread(tid).get_pid()
2663 bplist.append( (dwProcessId, tid, bp) )
2664
2665
2666 return bplist
2667
2669 """
2670 @type dwProcessId: int
2671 @param dwProcessId: Process global ID.
2672
2673 @rtype: list of L{CodeBreakpoint}
2674 @return: All code breakpoints for the given process.
2675 """
2676 return [ bp for ((pid, address), bp) in self.__codeBP.iteritems() \
2677 if pid == dwProcessId ]
2678
2679 - def get_process_page_breakpoints(self, dwProcessId):
2680 """
2681 @type dwProcessId: int
2682 @param dwProcessId: Process global ID.
2683
2684 @rtype: list of L{PageBreakpoint}
2685 @return: All page breakpoints for the given process.
2686 """
2687 return [ bp for ((pid, address), bp) in self.__pageBP.iteritems() \
2688 if pid == dwProcessId ]
2689
2691 """
2692 @see: L{get_process_hardware_breakpoints}
2693
2694 @type dwThreadId: int
2695 @param dwThreadId: Thread global ID.
2696
2697 @rtype: list of L{HardwareBreakpoint}
2698 @return: All hardware breakpoints for the given thread.
2699 """
2700 result = list()
2701 for (tid, bplist) in self.__hardwareBP.iteritems():
2702 if tid == dwThreadId:
2703 for bp in bplist:
2704 result.append(bp)
2705 return result
2706
2708 """
2709 @see: L{get_thread_hardware_breakpoints}
2710
2711 @type dwProcessId: int
2712 @param dwProcessId: Process global ID.
2713
2714 @rtype: list of tuple( int, L{HardwareBreakpoint} )
2715 @return: All hardware breakpoints for each thread in the given process
2716 as a list of tuples (tid, bp).
2717 """
2718 result = list()
2719 aProcess = self.system.get_process(dwProcessId)
2720 for dwThreadId in aProcess.iter_thread_ids():
2721 if dwThreadId in self.__hardwareBP:
2722 bplist = self.__hardwareBP[dwThreadId]
2723 for bp in bplist:
2724 result.append( (dwThreadId, bp) )
2725 return result
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2780
2805
2827
2861
2862
2863
2864
2865
2895
2925
2952
2987
2988
2989
2990
2991
2992 - def notify_guard_page(self, event):
2993 """
2994 Notify breakpoints of a guard page exception event.
2995
2996 @type event: L{ExceptionEvent}
2997 @param event: Guard page exception event.
2998
2999 @rtype: bool
3000 @return: C{True} to call the user-defined handle, C{False} otherwise.
3001 """
3002 address = event.get_fault_address()
3003 pid = event.get_pid()
3004 bCallHandler = True
3005
3006
3007 address = address & 0xFFFFF000
3008
3009
3010 key = (pid, address)
3011 if key in self.__pageBP:
3012 bp = self.__pageBP[key]
3013
3014
3015 event.continueStatus = win32.DBG_EXCEPTION_HANDLED
3016
3017
3018 event.breakpoint = bp
3019
3020
3021
3022 if bp.is_enabled() or bp.is_one_shot():
3023
3024
3025 bp.hit(event)
3026
3027
3028 if bp.is_running():
3029 tid = event.get_tid()
3030 self.__add_running_bp(tid, bp)
3031
3032
3033 bCondition = bp.eval_condition(event)
3034
3035
3036
3037 if bCondition and bp.is_automatic():
3038 bp.run_action(event)
3039 bCallHandler = False
3040 else:
3041 bCallHandler = bCondition
3042
3043 return bCallHandler
3044
3103
3171
3173 """
3174 Notify the termination of a thread.
3175
3176 @type event: L{ExitThreadEvent}
3177 @param event: Exit thread event.
3178
3179 @rtype: bool
3180 @return: C{True} to call the user-defined handle, C{False} otherwise.
3181 """
3182 self.__cleanup_thread(event)
3183 return True
3184
3186 """
3187 Notify the termination of a process.
3188
3189 @type event: L{ExitProcessEvent}
3190 @param event: Exit process event.
3191
3192 @rtype: bool
3193 @return: C{True} to call the user-defined handle, C{False} otherwise.
3194 """
3195 self.__cleanup_process(event)
3196 self.__cleanup_thread(event)
3197 return True
3198
3200 """
3201 Notify the unloading of a DLL.
3202
3203 @type event: L{UnloadDLLEvent}
3204 @param event: Unload DLL event.
3205
3206 @rtype: bool
3207 @return: C{True} to call the user-defined handle, C{False} otherwise.
3208 """
3209 self.__cleanup_module(event)
3210 return True
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3225 """
3226 Used by L{break_at} and L{stalk_at}.
3227
3228 @type pid: int
3229 @param pid: Process global ID.
3230
3231 @type address: int
3232 @param address: Memory address of code instruction to break at.
3233
3234 @type action: function
3235 @param action: (Optional) Action callback function.
3236
3237 See L{define_code_breakpoint} for more details.
3238 """
3239 if self.has_code_breakpoint(pid, address):
3240 bp = self.get_code_breakpoint(pid, address)
3241 if bp.get_action() != action:
3242 bp.set_action(action)
3243 else:
3244 self.define_code_breakpoint(pid, address, True, action)
3245 bp = self.get_code_breakpoint(pid, address)
3246 return bp
3247
3249 """
3250 Used by L{dont_break_at} and L{dont_stalk_at}.
3251
3252 @type pid: int
3253 @param pid: Process global ID.
3254
3255 @type address: int
3256 @param address: Memory address of code breakpoint.
3257 """
3258 if self.has_code_breakpoint(pid, address):
3259 self.erase_code_breakpoint(pid, address)
3260
3261 - def stalk_at(self, pid, address, action = None):
3262 """
3263 Sets a one shot code breakpoint at the given process and address.
3264
3265 @see: L{break_at}, L{dont_stalk_at}
3266
3267 @type pid: int
3268 @param pid: Process global ID.
3269
3270 @type address: int
3271 @param address: Memory address of code instruction to break at.
3272
3273 @type action: function
3274 @param action: (Optional) Action callback function.
3275
3276 See L{define_code_breakpoint} for more details.
3277 """
3278 bp = self.__set_break(pid, address, action)
3279 if not bp.is_one_shot():
3280 self.enable_one_shot_code_breakpoint(pid, address)
3281
3282 - def break_at(self, pid, address, action = None):
3283 """
3284 Sets a code breakpoint at the given process and address.
3285
3286 @see: L{stalk_at}, L{dont_break_at}
3287
3288 @type pid: int
3289 @param pid: Process global ID.
3290
3291 @type address: int
3292 @param address: Memory address of code instruction to break at.
3293
3294 @type action: function
3295 @param action: (Optional) Action callback function.
3296
3297 See L{define_code_breakpoint} for more details.
3298 """
3299 bp = self.__set_break(pid, address, action)
3300 if not bp.is_enabled():
3301 self.enable_code_breakpoint(pid, address)
3302
3304 """
3305 Clears a code breakpoint set by L{break_at}.
3306
3307 @type pid: int
3308 @param pid: Process global ID.
3309
3310 @type address: int
3311 @param address: Memory address of code instruction to break at.
3312 """
3313 self.__clear_break(pid, address)
3314
3316 """
3317 Clears a code breakpoint set by L{stalk_at}.
3318
3319 @type pid: int
3320 @param pid: Process global ID.
3321
3322 @type address: int
3323 @param address: Memory address of code instruction to break at.
3324 """
3325 self.__clear_break(pid, address)
3326
3327
3328
3329
3330
3331 - def hook_function(self, pid, address, preCB = None, postCB = None,
3332 paramCount = 0):
3333 """
3334 Sets a function hook at the given address.
3335
3336 @type pid: int
3337 @param pid: Process global ID.
3338
3339 @type address: int
3340 @param address: Function address.
3341
3342 @type preCB: function
3343 @param preCB: (Optional) Callback triggered on function entry.
3344
3345 The signature for the callback can be something like this::
3346
3347 def pre_LoadLibraryEx(event, *params):
3348 ra = params[0] # return address
3349 argv = params[1:] # function parameters
3350
3351 # (...)
3352
3353 But if you passed the right number of arguments, you can also
3354 use a signature like this::
3355
3356 def pre_LoadLibraryEx(event, ra, lpFilename, hFile, dwFlags):
3357 szFilename = event.get_process().peek_string(lpFilename)
3358
3359 # (...)
3360
3361 In the above example, the value for C{paramCount} would be C{3}.
3362
3363 @type postCB: function
3364 @param postCB: (Optional) Callback triggered on function exit.
3365
3366 The signature for the callback would be something like this::
3367
3368 def post_LoadLibraryEx(event, return_value):
3369
3370 # (...)
3371
3372 @type paramCount: int
3373 @param paramCount:
3374 (Optional) Number of parameters for the C{preCB} callback,
3375 not counting the return address. Parameters are read from
3376 the stack and assumed to be DWORDs.
3377 """
3378
3379
3380 if System.arch != 'i386':
3381 raise NotImplementedError
3382
3383 hookObj = Hook(preCB, postCB, paramCount)
3384 self.break_at(pid, address, hookObj)
3385
3386
3387 - def stalk_function(self, pid, address, preCB = None, postCB = None,
3388 paramCount = 0):
3389 """
3390 Sets a one-shot function hook at the given address.
3391
3392 @type pid: int
3393 @param pid: Process global ID.
3394
3395 @type address: int
3396 @param address: Function address.
3397
3398 @type preCB: function
3399 @param preCB: (Optional) Callback triggered on function entry.
3400
3401 The signature for the callback can be something like this::
3402
3403 def pre_LoadLibraryEx(event, *params):
3404 ra = params[0] # return address
3405 argv = params[1:] # function parameters
3406
3407 # (...)
3408
3409 But if you passed the right number of arguments, you can also
3410 use a signature like this::
3411
3412 def pre_LoadLibraryEx(event, ra, lpFilename, hFile, dwFlags):
3413 szFilename = event.get_process().peek_string(lpFilename)
3414
3415 # (...)
3416
3417 In the above example, the value for C{paramCount} would be C{3}.
3418
3419 @type postCB: function
3420 @param postCB: (Optional) Callback triggered on function exit.
3421
3422 The signature for the callback would be something like this::
3423
3424 def post_LoadLibraryEx(event, return_value):
3425
3426 # (...)
3427
3428 @type paramCount: int
3429 @param paramCount:
3430 (Optional) Number of parameters for the C{preCB} callback,
3431 not counting the return address. Parameters are read from
3432 the stack and assumed to be DWORDs.
3433 """
3434
3435
3436 if System.arch != 'i386':
3437 raise NotImplementedError
3438
3439 hookObj = Hook(preCB, postCB, paramCount)
3440 self.stalk_at(pid, address, hookObj)
3441
3442
3444 """
3445 Removes a function hook set by L{hook_function}.
3446
3447 @type pid: int
3448 @param pid: Process global ID.
3449
3450 @type address: int
3451 @param address: Function address.
3452 """
3453 self.dont_break_at(pid, address)
3454
3455
3456
3457 unhook_function = dont_hook_function
3458
3460 """
3461 Removes a function hook set by L{stalk_function}.
3462
3463 @type pid: int
3464 @param pid: Process global ID.
3465
3466 @type address: int
3467 @param address: Function address.
3468 """
3469 self.dont_stalk_at(pid, address)
3470
3471
3472
3473
3474
3475
3477 """
3478 Used by L{watch_variable} and L{stalk_variable}.
3479
3480 @type tid: int
3481 @param tid: Thread global ID.
3482
3483 @type address: int
3484 @param address: Memory address of variable to watch.
3485
3486 @type size: int
3487 @param size: Size of variable to watch. The only supported sizes are:
3488 byte (1), word (2), dword (4) and qword (8).
3489
3490 @type action: function
3491 @param action: (Optional) Action callback function.
3492
3493 See L{define_hardware_breakpoint} for more details.
3494
3495 @rtype: L{HardwareBreakpoint}
3496 @return: Hardware breakpoint at the requested address.
3497 """
3498
3499
3500
3501
3502 if size == 1:
3503 sizeFlag = self.BP_WATCH_BYTE
3504 elif size == 2:
3505 sizeFlag = self.BP_WATCH_WORD
3506 elif size == 4:
3507 sizeFlag = self.BP_WATCH_DWORD
3508 elif size == 8:
3509 sizeFlag = self.BP_WATCH_QWORD
3510 else:
3511 raise ValueError, "Bad size for variable watch: %r" % size
3512 if self.has_hardware_breakpoint(tid, address):
3513 bp = self.get_hardware_breakpoint(tid, address)
3514 if bp.get_trigger() != self.BP_BREAK_ON_ACCESS or \
3515 bp.get_watch() != sizeFlag:
3516 self.erase_hardware_breakpoint(tid, address)
3517 self.define_hardware_breakpoint(tid, address,
3518 self.BP_BREAK_ON_ACCESS, sizeFlag, True, action)
3519 bp = self.get_hardware_breakpoint(tid, address)
3520 else:
3521 self.define_hardware_breakpoint(tid, address,
3522 self.BP_BREAK_ON_ACCESS, sizeFlag, True, action)
3523 bp = self.get_hardware_breakpoint(tid, address)
3524 return bp
3525
3527 """
3528 Used by L{dont_watch_variable} and L{dont_stalk_variable}.
3529
3530 @type tid: int
3531 @param tid: Thread global ID.
3532
3533 @type address: int
3534 @param address: Memory address of variable to stop watching.
3535 """
3536 if self.has_hardware_breakpoint(tid, address):
3537 self.erase_hardware_breakpoint(tid, address)
3538
3540 """
3541 Sets a hardware breakpoint at the given thread, address and size.
3542
3543 @see: L{dont_watch_variable}
3544
3545 @type tid: int
3546 @param tid: Thread global ID.
3547
3548 @type address: int
3549 @param address: Memory address of variable to watch.
3550
3551 @type size: int
3552 @param size: Size of variable to watch. The only supported sizes are:
3553 byte (1), word (2), dword (4) and qword (8).
3554
3555 @type action: function
3556 @param action: (Optional) Action callback function.
3557
3558 See L{define_hardware_breakpoint} for more details.
3559 """
3560 bp = self.__set_variable_watch(tid, address, size, action)
3561 if not bp.is_enabled():
3562 self.enable_hardware_breakpoint(tid, address)
3563
3565 """
3566 Sets a one-shot hardware breakpoint at the given thread,
3567 address and size.
3568
3569 @see: L{dont_watch_variable}
3570
3571 @type tid: int
3572 @param tid: Thread global ID.
3573
3574 @type address: int
3575 @param address: Memory address of variable to watch.
3576
3577 @type size: int
3578 @param size: Size of variable to watch. The only supported sizes are:
3579 byte (1), word (2), dword (4) and qword (8).
3580
3581 @type action: function
3582 @param action: (Optional) Action callback function.
3583
3584 See L{define_hardware_breakpoint} for more details.
3585 """
3586 bp = self.__set_variable_watch(tid, address, size, action)
3587 if not bp.is_one_shot():
3588 self.enable_one_shot_hardware_breakpoint(tid, address)
3589
3591 """
3592 Clears a hardware breakpoint set by L{watch_variable}.
3593
3594 @type tid: int
3595 @param tid: Thread global ID.
3596
3597 @type address: int
3598 @param address: Memory address of variable to stop watching.
3599 """
3600 self.__clear_variable_watch(tid, address)
3601
3603 """
3604 Clears a hardware breakpoint set by L{stalk_variable}.
3605
3606 @type tid: int
3607 @param tid: Thread global ID.
3608
3609 @type address: int
3610 @param address: Memory address of variable to stop watching.
3611 """
3612 self.__clear_variable_watch(tid, address)
3613
3614
3615
3616
3617
3619 """
3620 Used by L{watch_buffer} and L{stalk_buffer}.
3621
3622 @type pid: int
3623 @param pid: Process global ID.
3624
3625 @type address: int
3626 @param address: Memory address of buffer to watch.
3627
3628 @type size: int
3629 @param size: Size in bytes of buffer to watch.
3630
3631 @type action: function
3632 @param action: (Optional) Action callback function.
3633
3634 See L{define_page_breakpoint} for more details.
3635
3636 @type bOneShot: bool
3637 @param bOneShot:
3638 C{True} to set a one-shot breakpoint,
3639 C{False} to set a normal breakpoint.
3640 """
3641
3642
3643
3644
3645
3646 if size < 1:
3647 raise ValueError, "Bad size for buffer watch: %r" % size
3648
3649
3650 aProcess = self.system.get_process(pid)
3651
3652
3653 base = MemoryAddresses.align_address_to_page_start(address)
3654 limit = MemoryAddresses.align_address_to_page_end(address + size)
3655 pages = MemoryAddresses.get_buffer_size_in_pages(address, size)
3656
3657 try:
3658
3659
3660
3661
3662
3663 bset = set()
3664 nset = set()
3665 cset = set()
3666
3667 page_addr = base
3668 pageSize = System.pageSize
3669 while page_addr < limit:
3670
3671
3672 if self.has_page_breakpoint(pid, page_addr):
3673 bp = self.get_page_breakpoint(pid, page_addr)
3674 if bp not in bset:
3675 condition = bp.get_condition()
3676 if not condition in cset:
3677 if not isinstance(condition, BufferWatch):
3678
3679
3680 msg = "Can't watch buffer at page %s"
3681 msg = msg % HexDump.address(page_addr)
3682 raise RuntimeError, msg
3683 cset.add(condition)
3684 bset.add(bp)
3685
3686
3687 else:
3688 condition = BufferWatch()
3689 bp = self.define_page_breakpoint(pid, page_addr, 1,
3690 condition = condition)
3691 bset.add(bp)
3692 nset.add(bp)
3693 cset.add(condition)
3694
3695
3696 page_addr = page_addr + pageSize
3697
3698
3699 if bOneShot:
3700 for bp in bset:
3701 if not bp.is_one_shot():
3702 bp.one_shot(aProcess, None)
3703 else:
3704 for bp in bset:
3705 if not bp.is_enabled():
3706 bp.enable(aProcess, None)
3707
3708
3709 except:
3710
3711
3712 for bp in nset:
3713 try:
3714 self.erase_page_breakpoint(pid, bp.get_address())
3715 except:
3716 pass
3717
3718
3719 raise
3720
3721
3722 for condition in cset:
3723 condition.add(address, size, action)
3724
3772
3773 - def watch_buffer(self, pid, address, size, action = None):
3774 """
3775 Sets a page breakpoint and notifies when the given buffer is accessed.
3776
3777 @see: L{dont_watch_variable}
3778
3779 @type pid: int
3780 @param pid: Process global ID.
3781
3782 @type address: int
3783 @param address: Memory address of buffer to watch.
3784
3785 @type size: int
3786 @param size: Size in bytes of buffer to watch.
3787
3788 @type action: function
3789 @param action: (Optional) Action callback function.
3790
3791 See L{define_page_breakpoint} for more details.
3792 """
3793 self.__set_buffer_watch(pid, address, size, action, False)
3794
3795 - def stalk_buffer(self, pid, address, size, action = None):
3796 """
3797 Sets a one-shot page breakpoint and notifies
3798 when the given buffer is accessed.
3799
3800 @see: L{dont_watch_variable}
3801
3802 @type pid: int
3803 @param pid: Process global ID.
3804
3805 @type address: int
3806 @param address: Memory address of buffer to watch.
3807
3808 @type size: int
3809 @param size: Size in bytes of buffer to watch.
3810
3811 @type action: function
3812 @param action: (Optional) Action callback function.
3813
3814 See L{define_page_breakpoint} for more details.
3815 """
3816 self.__set_buffer_watch(pid, address, size, action, True)
3817
3819 """
3820 Clears a page breakpoint set by L{watch_buffer}.
3821
3822 @type pid: int
3823 @param pid: Process global ID.
3824
3825 @type address: int
3826 @param address: Memory address of buffer to stop watching.
3827
3828 @type size: int
3829 @param size: Size in bytes of buffer to stop watching.
3830 """
3831 self.__clear_buffer_watch(pid, address, size)
3832
3834 """
3835 Clears a page breakpoint set by L{stalk_buffer}.
3836
3837 @type pid: int
3838 @param pid: Process global ID.
3839
3840 @type address: int
3841 @param address: Memory address of buffer to stop watching.
3842
3843 @type size: int
3844 @param size: Size in bytes of buffer to stop watching.
3845 """
3846 self.__clear_buffer_watch(pid, address, size)
3847
3848
3849
3850
3851
3852
3853
3854
3856 """
3857 @type thread: L{Thread}
3858 @param thread: Thread to start tracing.
3859 """
3860 tid = thread.get_tid()
3861 if not tid in self.__tracing:
3862 thread.set_tf()
3863 self.__tracing.add(tid)
3864
3866 """
3867 @type thread: L{Thread}
3868 @param thread: Thread to stop tracing.
3869 """
3870 tid = thread.get_tid()
3871 if tid in self.__tracing:
3872 self.__tracing.remove(tid)
3873 thread.clear_tf()
3874
3876 """
3877 @type tid: int
3878 @param tid: Thread global ID.
3879
3880 @rtype: bool
3881 @return: C{True} if the thread is being traced, C{False} otherwise.
3882 """
3883 return tid in self.__tracing
3884
3886 """
3887 Retrieves the list of global IDs of all threads being traced.
3888
3889 @rtype: list( int... )
3890 @return: List of thread global IDs.
3891 """
3892 tids = list(self.__tracing)
3893 tids.sort()
3894 return tids
3895
3906
3917
3927
3937
3944
3951
3952
3953
3954
3955
3957 """
3958 Resolves the exported DLL function for the given process.
3959
3960 @type pid: int
3961 @param pid: Process global ID.
3962
3963 @type modName: str
3964 @param modName: Name of the module that exports the function.
3965
3966 @type procName: str
3967 @param procName: Name of the exported function to resolve.
3968
3969 @rtype: int, None
3970 @return: On success, the address of the exported function.
3971 On failure, returns C{None}.
3972 """
3973 aProcess = self.system.get_process(pid)
3974 aModule = aProcess.get_module_by_name(modName)
3975 if not aModule:
3976 aProcess.scan_modules()
3977 aModule = aProcess.get_module_by_name(modName)
3978 if aModule:
3979 address = aModule.resolve(procName)
3980 return address
3981 return None
3982
3984 """
3985 Resolves a label for the given process.
3986
3987 @type pid: int
3988 @param pid: Process global ID.
3989
3990 @type label: str
3991 @param label: Label to resolve.
3992
3993 @rtype: int
3994 @return: Memory address pointed to by the label.
3995
3996 @raise ValueError: The label is malformed or impossible to resolve.
3997 @raise RuntimeError: Cannot resolve the module or function.
3998 """
3999 return self.get_process(pid).resolve_label(label)
4000