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
30
31 """
32 Breakpoints.
33
34 @group Breakpoints:
35 Breakpoint, CodeBreakpoint, PageBreakpoint, HardwareBreakpoint,
36 BufferWatch, Hook, ApiHook
37
38 @group Warnings:
39 BreakpointWarning, BreakpointCallbackWarning
40 """
41
42 __revision__ = "$Id: breakpoint.py 1299 2013-12-20 09:30:55Z qvasimodo $"
43
44 __all__ = [
45
46
47 'Breakpoint',
48
49
50 'CodeBreakpoint',
51 'PageBreakpoint',
52 'HardwareBreakpoint',
53
54
55 'Hook',
56 'ApiHook',
57 'BufferWatch',
58
59
60 'BreakpointWarning',
61 'BreakpointCallbackWarning',
62
63 ]
64
65 import win32
66 from process import Process, Thread
67 from util import DebugRegister, MemoryAddresses
68 from textio import HexDump
69
70 import ctypes
71 import warnings
72 import traceback
77 """
78 This warning is issued when a non-fatal error occurs that's related to
79 breakpoints.
80 """
81
83 """
84 This warning is issued when an uncaught exception was raised by a
85 breakpoint's user-defined callback.
86 """
87
91 """
92 Base class for breakpoints.
93 Here's the breakpoints state machine.
94
95 @see: L{CodeBreakpoint}, L{PageBreakpoint}, L{HardwareBreakpoint}
96
97 @group Breakpoint states:
98 DISABLED, ENABLED, ONESHOT, RUNNING
99 @group State machine:
100 hit, disable, enable, one_shot, running,
101 is_disabled, is_enabled, is_one_shot, is_running,
102 get_state, get_state_name
103 @group Information:
104 get_address, get_size, get_span, is_here
105 @group Conditional breakpoints:
106 is_conditional, is_unconditional,
107 get_condition, set_condition, eval_condition
108 @group Automatic breakpoints:
109 is_automatic, is_interactive,
110 get_action, set_action, run_action
111
112 @cvar DISABLED: I{Disabled} S{->} Enabled, OneShot
113 @cvar ENABLED: I{Enabled} S{->} I{Running}, Disabled
114 @cvar ONESHOT: I{OneShot} S{->} I{Disabled}
115 @cvar RUNNING: I{Running} S{->} I{Enabled}, Disabled
116
117 @type DISABLED: int
118 @type ENABLED: int
119 @type ONESHOT: int
120 @type RUNNING: int
121
122 @type stateNames: dict E{lb} int S{->} str E{rb}
123 @cvar stateNames: User-friendly names for each breakpoint state.
124
125 @type typeName: str
126 @cvar typeName: User friendly breakpoint type string.
127 """
128
129
130
131
132 DISABLED = 0
133 ENABLED = 1
134 ONESHOT = 2
135 RUNNING = 3
136
137 typeName = 'breakpoint'
138
139 stateNames = {
140 DISABLED : 'disabled',
141 ENABLED : 'enabled',
142 ONESHOT : 'one shot',
143 RUNNING : 'running',
144 }
145
146 - def __init__(self, address, size = 1, condition = True, action = None):
147 """
148 Breakpoint object.
149
150 @type address: int
151 @param address: Memory address for breakpoint.
152
153 @type size: int
154 @param size: Size of breakpoint in bytes (defaults to 1).
155
156 @type condition: function
157 @param condition: (Optional) Condition callback function.
158
159 The callback signature is::
160
161 def condition_callback(event):
162 return True # returns True or False
163
164 Where B{event} is an L{Event} object,
165 and the return value is a boolean
166 (C{True} to dispatch the event, C{False} otherwise).
167
168 @type action: function
169 @param action: (Optional) Action callback function.
170 If specified, the event is handled by this callback instead of
171 being dispatched normally.
172
173 The callback signature is::
174
175 def action_callback(event):
176 pass # no return value
177
178 Where B{event} is an L{Event} object.
179 """
180 self.__address = address
181 self.__size = size
182 self.__state = self.DISABLED
183
184 self.set_condition(condition)
185 self.set_action(action)
186
209
210
211
213 """
214 @rtype: bool
215 @return: C{True} if the breakpoint is in L{DISABLED} state.
216 """
217 return self.get_state() == self.DISABLED
218
220 """
221 @rtype: bool
222 @return: C{True} if the breakpoint is in L{ENABLED} state.
223 """
224 return self.get_state() == self.ENABLED
225
227 """
228 @rtype: bool
229 @return: C{True} if the breakpoint is in L{ONESHOT} state.
230 """
231 return self.get_state() == self.ONESHOT
232
234 """
235 @rtype: bool
236 @return: C{True} if the breakpoint is in L{RUNNING} state.
237 """
238 return self.get_state() == self.RUNNING
239
241 """
242 @rtype: bool
243 @return: C{True} if the address is within the range of the breakpoint.
244 """
245 begin = self.get_address()
246 end = begin + self.get_size()
247 return begin <= address < end
248
250 """
251 @rtype: int
252 @return: The target memory address for the breakpoint.
253 """
254 return self.__address
255
257 """
258 @rtype: int
259 @return: The size in bytes of the breakpoint.
260 """
261 return self.__size
262
264 """
265 @rtype: tuple( int, int )
266 @return:
267 Starting and ending address of the memory range
268 covered by the breakpoint.
269 """
270 address = self.get_address()
271 size = self.get_size()
272 return ( address, address + size )
273
275 """
276 @rtype: int
277 @return: The current state of the breakpoint
278 (L{DISABLED}, L{ENABLED}, L{ONESHOT}, L{RUNNING}).
279 """
280 return self.__state
281
283 """
284 @rtype: str
285 @return: The name of the current state of the breakpoint.
286 """
287 return self.stateNames[ self.get_state() ]
288
289
290
292 """
293 @see: L{__init__}
294 @rtype: bool
295 @return: C{True} if the breakpoint has a condition callback defined.
296 """
297
298 return self.__condition is not True
299
301 """
302 @rtype: bool
303 @return: C{True} if the breakpoint doesn't have a condition callback defined.
304 """
305
306 return self.__condition is True
307
309 """
310 @rtype: bool, function
311 @return: Returns the condition callback for conditional breakpoints.
312 Returns C{True} for unconditional breakpoints.
313 """
314 return self.__condition
315
317 """
318 Sets a new condition callback for the breakpoint.
319
320 @see: L{__init__}
321
322 @type condition: function
323 @param condition: (Optional) Condition callback function.
324 """
325 if condition is None:
326 self.__condition = True
327 else:
328 self.__condition = condition
329
331 """
332 Evaluates the breakpoint condition, if any was set.
333
334 @type event: L{Event}
335 @param event: Debug event triggered by the breakpoint.
336
337 @rtype: bool
338 @return: C{True} to dispatch the event, C{False} otherwise.
339 """
340 condition = self.get_condition()
341 if condition is True:
342 return True
343 if callable(condition):
344 try:
345 return bool( condition(event) )
346 except Exception, e:
347 msg = ("Breakpoint condition callback %r"
348 " raised an exception: %s")
349 msg = msg % (condition, traceback.format_exc(e))
350 warnings.warn(msg, BreakpointCallbackWarning)
351 return False
352 return bool( condition )
353
354
355
357 """
358 @rtype: bool
359 @return: C{True} if the breakpoint has an action callback defined.
360 """
361 return self.__action is not None
362
364 """
365 @rtype: bool
366 @return:
367 C{True} if the breakpoint doesn't have an action callback defined.
368 """
369 return self.__action is None
370
372 """
373 @rtype: bool, function
374 @return: Returns the action callback for automatic breakpoints.
375 Returns C{None} for interactive breakpoints.
376 """
377 return self.__action
378
380 """
381 Sets a new action callback for the breakpoint.
382
383 @type action: function
384 @param action: (Optional) Action callback function.
385 """
386 self.__action = action
387
389 """
390 Executes the breakpoint action callback, if any was set.
391
392 @type event: L{Event}
393 @param event: Debug event triggered by the breakpoint.
394 """
395 action = self.get_action()
396 if action is not None:
397 try:
398 return bool( action(event) )
399 except Exception, e:
400 msg = ("Breakpoint action callback %r"
401 " raised an exception: %s")
402 msg = msg % (action, traceback.format_exc(e))
403 warnings.warn(msg, BreakpointCallbackWarning)
404 return False
405 return True
406
407
408
410 """
411 Raises an C{AssertionError} exception for an invalid state transition.
412
413 @see: L{stateNames}
414
415 @type state: int
416 @param state: Intended breakpoint state.
417
418 @raise Exception: Always.
419 """
420 statemsg = ""
421 oldState = self.stateNames[ self.get_state() ]
422 newState = self.stateNames[ state ]
423 msg = "Invalid state transition (%s -> %s)" \
424 " for breakpoint at address %s"
425 msg = msg % (oldState, newState, HexDump.address(self.get_address()))
426 raise AssertionError(msg)
427
428 - def disable(self, aProcess, aThread):
429 """
430 Transition to L{DISABLED} state.
431 - When hit: OneShot S{->} Disabled
432 - Forced by user: Enabled, OneShot, Running S{->} Disabled
433 - Transition from running state may require special handling
434 by the breakpoint implementation class.
435
436 @type aProcess: L{Process}
437 @param aProcess: Process object.
438
439 @type aThread: L{Thread}
440 @param aThread: Thread object.
441 """
442
443
444 self.__state = self.DISABLED
445
446 - def enable(self, aProcess, aThread):
447 """
448 Transition to L{ENABLED} state.
449 - When hit: Running S{->} Enabled
450 - Forced by user: Disabled, Running S{->} Enabled
451 - Transition from running state may require special handling
452 by the breakpoint implementation class.
453
454 @type aProcess: L{Process}
455 @param aProcess: Process object.
456
457 @type aThread: L{Thread}
458 @param aThread: Thread object.
459 """
460
461
462 self.__state = self.ENABLED
463
465 """
466 Transition to L{ONESHOT} state.
467 - Forced by user: Disabled S{->} OneShot
468
469 @type aProcess: L{Process}
470 @param aProcess: Process object.
471
472 @type aThread: L{Thread}
473 @param aThread: Thread object.
474 """
475
476
477 self.__state = self.ONESHOT
478
479 - def running(self, aProcess, aThread):
480 """
481 Transition to L{RUNNING} state.
482 - When hit: Enabled S{->} Running
483
484 @type aProcess: L{Process}
485 @param aProcess: Process object.
486
487 @type aThread: L{Thread}
488 @param aThread: Thread object.
489 """
490 if self.__state != self.ENABLED:
491 self.__bad_transition(self.RUNNING)
492 self.__state = self.RUNNING
493
494 - def hit(self, event):
495 """
496 Notify a breakpoint that it's been hit.
497
498 This triggers the corresponding state transition and sets the
499 C{breakpoint} property of the given L{Event} object.
500
501 @see: L{disable}, L{enable}, L{one_shot}, L{running}
502
503 @type event: L{Event}
504 @param event: Debug event to handle (depends on the breakpoint type).
505
506 @raise AssertionError: Disabled breakpoints can't be hit.
507 """
508 aProcess = event.get_process()
509 aThread = event.get_thread()
510 state = self.get_state()
511
512 event.breakpoint = self
513
514 if state == self.ENABLED:
515 self.running(aProcess, aThread)
516
517 elif state == self.RUNNING:
518 self.enable(aProcess, aThread)
519
520 elif state == self.ONESHOT:
521 self.disable(aProcess, aThread)
522
523 elif state == self.DISABLED:
524
525 msg = "Hit a disabled breakpoint at address %s"
526 msg = msg % HexDump.address( self.get_address() )
527 warnings.warn(msg, BreakpointWarning)
528
536 """
537 Code execution breakpoints (using an int3 opcode).
538
539 @see: L{Debug.break_at}
540
541 @type bpInstruction: str
542 @cvar bpInstruction: Breakpoint instruction for the current processor.
543 """
544
545 typeName = 'code breakpoint'
546
547 if win32.arch in (win32.ARCH_I386, win32.ARCH_AMD64):
548 bpInstruction = '\xCC'
549
550 - def __init__(self, address, condition = True, action = None):
551 """
552 Code breakpoint object.
553
554 @see: L{Breakpoint.__init__}
555
556 @type address: int
557 @param address: Memory address for breakpoint.
558
559 @type condition: function
560 @param condition: (Optional) Condition callback function.
561
562 @type action: function
563 @param action: (Optional) Action callback function.
564 """
565 if win32.arch not in (win32.ARCH_I386, win32.ARCH_AMD64):
566 msg = "Code breakpoints not supported for %s" % win32.arch
567 raise NotImplementedError(msg)
568 Breakpoint.__init__(self, address, len(self.bpInstruction),
569 condition, action)
570 self.__previousValue = self.bpInstruction
571
586
604
605 - def disable(self, aProcess, aThread):
609
610 - def enable(self, aProcess, aThread):
614
619
620
621
622
623
624
625 - def running(self, aProcess, aThread):
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646 -class PageBreakpoint (Breakpoint):
647 """
648 Page access breakpoint (using guard pages).
649
650 @see: L{Debug.watch_buffer}
651
652 @group Information:
653 get_size_in_pages
654 """
655
656 typeName = 'page breakpoint'
657
658
659
660 - def __init__(self, address, pages = 1, condition = True, action = None):
661 """
662 Page breakpoint object.
663
664 @see: L{Breakpoint.__init__}
665
666 @type address: int
667 @param address: Memory address for breakpoint.
668
669 @type pages: int
670 @param address: Size of breakpoint in pages.
671
672 @type condition: function
673 @param condition: (Optional) Condition callback function.
674
675 @type action: function
676 @param action: (Optional) Action callback function.
677 """
678 Breakpoint.__init__(self, address, pages * MemoryAddresses.pageSize,
679 condition, action)
680
681 floordiv_align = long(address) // long(MemoryAddresses.pageSize)
682 truediv_align = float(address) / float(MemoryAddresses.pageSize)
683 if floordiv_align != truediv_align:
684 msg = "Address of page breakpoint " \
685 "must be aligned to a page size boundary " \
686 "(value %s received)" % HexDump.address(address)
687 raise ValueError(msg)
688
690 """
691 @rtype: int
692 @return: The size in pages of the breakpoint.
693 """
694
695 return self.get_size() // MemoryAddresses.pageSize
696
697 - def __set_bp(self, aProcess):
698 """
699 Sets the target pages as guard pages.
700
701 @type aProcess: L{Process}
702 @param aProcess: Process object.
703 """
704 lpAddress = self.get_address()
705 dwSize = self.get_size()
706 flNewProtect = aProcess.mquery(lpAddress).Protect
707 flNewProtect = flNewProtect | win32.PAGE_GUARD
708 aProcess.mprotect(lpAddress, dwSize, flNewProtect)
709
710 - def __clear_bp(self, aProcess):
711 """
712 Restores the original permissions of the target pages.
713
714 @type aProcess: L{Process}
715 @param aProcess: Process object.
716 """
717 lpAddress = self.get_address()
718 flNewProtect = aProcess.mquery(lpAddress).Protect
719 flNewProtect = flNewProtect & (0xFFFFFFFF ^ win32.PAGE_GUARD)
720 aProcess.mprotect(lpAddress, self.get_size(), flNewProtect)
721
722 - def disable(self, aProcess, aThread):
723 if not self.is_disabled():
724 self.__clear_bp(aProcess)
725 super(PageBreakpoint, self).disable(aProcess, aThread)
726
727 - def enable(self, aProcess, aThread):
728 if win32.arch not in (win32.ARCH_I386, win32.ARCH_AMD64):
729 msg = "Only one-shot page breakpoints are supported for %s"
730 raise NotImplementedError(msg % win32.arch)
731 if not self.is_enabled() and not self.is_one_shot():
732 self.__set_bp(aProcess)
733 super(PageBreakpoint, self).enable(aProcess, aThread)
734
735 - def one_shot(self, aProcess, aThread):
736 if not self.is_enabled() and not self.is_one_shot():
737 self.__set_bp(aProcess)
738 super(PageBreakpoint, self).one_shot(aProcess, aThread)
739
740 - def running(self, aProcess, aThread):
741 aThread.set_tf()
742 super(PageBreakpoint, self).running(aProcess, aThread)
743
747 """
748 Hardware breakpoint (using debug registers).
749
750 @see: L{Debug.watch_variable}
751
752 @group Information:
753 get_slot, get_trigger, get_watch
754
755 @group Trigger flags:
756 BREAK_ON_EXECUTION, BREAK_ON_WRITE, BREAK_ON_ACCESS
757
758 @group Watch size flags:
759 WATCH_BYTE, WATCH_WORD, WATCH_DWORD, WATCH_QWORD
760
761 @type BREAK_ON_EXECUTION: int
762 @cvar BREAK_ON_EXECUTION: Break on execution.
763
764 @type BREAK_ON_WRITE: int
765 @cvar BREAK_ON_WRITE: Break on write.
766
767 @type BREAK_ON_ACCESS: int
768 @cvar BREAK_ON_ACCESS: Break on read or write.
769
770 @type WATCH_BYTE: int
771 @cvar WATCH_BYTE: Watch a byte.
772
773 @type WATCH_WORD: int
774 @cvar WATCH_WORD: Watch a word (2 bytes).
775
776 @type WATCH_DWORD: int
777 @cvar WATCH_DWORD: Watch a double word (4 bytes).
778
779 @type WATCH_QWORD: int
780 @cvar WATCH_QWORD: Watch one quad word (8 bytes).
781
782 @type validTriggers: tuple
783 @cvar validTriggers: Valid trigger flag values.
784
785 @type validWatchSizes: tuple
786 @cvar validWatchSizes: Valid watch flag values.
787 """
788
789 typeName = 'hardware breakpoint'
790
791 BREAK_ON_EXECUTION = DebugRegister.BREAK_ON_EXECUTION
792 BREAK_ON_WRITE = DebugRegister.BREAK_ON_WRITE
793 BREAK_ON_ACCESS = DebugRegister.BREAK_ON_ACCESS
794
795 WATCH_BYTE = DebugRegister.WATCH_BYTE
796 WATCH_WORD = DebugRegister.WATCH_WORD
797 WATCH_DWORD = DebugRegister.WATCH_DWORD
798 WATCH_QWORD = DebugRegister.WATCH_QWORD
799
800 validTriggers = (
801 BREAK_ON_EXECUTION,
802 BREAK_ON_WRITE,
803 BREAK_ON_ACCESS,
804 )
805
806 validWatchSizes = (
807 WATCH_BYTE,
808 WATCH_WORD,
809 WATCH_DWORD,
810 WATCH_QWORD,
811 )
812
817 """
818 Hardware breakpoint object.
819
820 @see: L{Breakpoint.__init__}
821
822 @type address: int
823 @param address: Memory address for breakpoint.
824
825 @type triggerFlag: int
826 @param triggerFlag: Trigger of breakpoint. Must be one of the following:
827
828 - L{BREAK_ON_EXECUTION}
829
830 Break on code execution.
831
832 - L{BREAK_ON_WRITE}
833
834 Break on memory read or write.
835
836 - L{BREAK_ON_ACCESS}
837
838 Break on memory write.
839
840 @type sizeFlag: int
841 @param sizeFlag: Size of breakpoint. Must be one of the following:
842
843 - L{WATCH_BYTE}
844
845 One (1) byte in size.
846
847 - L{WATCH_WORD}
848
849 Two (2) bytes in size.
850
851 - L{WATCH_DWORD}
852
853 Four (4) bytes in size.
854
855 - L{WATCH_QWORD}
856
857 Eight (8) bytes in size.
858
859 @type condition: function
860 @param condition: (Optional) Condition callback function.
861
862 @type action: function
863 @param action: (Optional) Action callback function.
864 """
865 if win32.arch not in (win32.ARCH_I386, win32.ARCH_AMD64):
866 msg = "Hardware breakpoints not supported for %s" % win32.arch
867 raise NotImplementedError(msg)
868 if sizeFlag == self.WATCH_BYTE:
869 size = 1
870 elif sizeFlag == self.WATCH_WORD:
871 size = 2
872 elif sizeFlag == self.WATCH_DWORD:
873 size = 4
874 elif sizeFlag == self.WATCH_QWORD:
875 size = 8
876 else:
877 msg = "Invalid size flag for hardware breakpoint (%s)"
878 msg = msg % repr(sizeFlag)
879 raise ValueError(msg)
880
881 if triggerFlag not in self.validTriggers:
882 msg = "Invalid trigger flag for hardware breakpoint (%s)"
883 msg = msg % repr(triggerFlag)
884 raise ValueError(msg)
885
886 Breakpoint.__init__(self, address, size, condition, action)
887 self.__trigger = triggerFlag
888 self.__watch = sizeFlag
889 self.__slot = None
890
907
909 """
910 Sets this breakpoint in the debug registers.
911
912 @type aThread: L{Thread}
913 @param aThread: Thread object.
914 """
915 if self.__slot is None:
916 aThread.suspend()
917 try:
918 ctx = aThread.get_context(win32.CONTEXT_DEBUG_REGISTERS)
919 self.__slot = DebugRegister.find_slot(ctx)
920 if self.__slot is None:
921 msg = "No available hardware breakpoint slots for thread ID %d"
922 msg = msg % aThread.get_tid()
923 raise RuntimeError(msg)
924 DebugRegister.set_bp(ctx, self.__slot, self.get_address(),
925 self.__trigger, self.__watch)
926 aThread.set_context(ctx)
927 finally:
928 aThread.resume()
929
931 """
932 @rtype: int
933 @return: The debug register number used by this breakpoint,
934 or C{None} if the breakpoint is not active.
935 """
936 return self.__slot
937
939 """
940 @see: L{validTriggers}
941 @rtype: int
942 @return: The breakpoint trigger flag.
943 """
944 return self.__trigger
945
947 """
948 @see: L{validWatchSizes}
949 @rtype: int
950 @return: The breakpoint watch flag.
951 """
952 return self.__watch
953
954 - def disable(self, aProcess, aThread):
958
959 - def enable(self, aProcess, aThread):
963
968
969 - def running(self, aProcess, aThread):
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009 -class Hook (object):
1010 """
1011 Factory class to produce hook objects. Used by L{Debug.hook_function} and
1012 L{Debug.stalk_function}.
1013
1014 When you try to instance this class, one of the architecture specific
1015 implementations is returned instead.
1016
1017 Instances act as an action callback for code breakpoints set at the
1018 beginning of a function. It automatically retrieves the parameters from
1019 the stack, sets a breakpoint at the return address and retrieves the
1020 return value from the function call.
1021
1022 @see: L{_Hook_i386}, L{_Hook_amd64}
1023
1024 @type useHardwareBreakpoints: bool
1025 @cvar useHardwareBreakpoints: C{True} to try to use hardware breakpoints,
1026 C{False} otherwise.
1027 """
1028
1029
1030
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060 useHardwareBreakpoints = False
1061
1062 - def __init__(self, preCB = None, postCB = None,
1063 paramCount = None, signature = None,
1064 arch = None):
1065 """
1066 @type preCB: function
1067 @param preCB: (Optional) Callback triggered on function entry.
1068
1069 The signature for the callback should be something like this::
1070
1071 def pre_LoadLibraryEx(event, ra, lpFilename, hFile, dwFlags):
1072
1073 # return address
1074 ra = params[0]
1075
1076 # function arguments start from here...
1077 szFilename = event.get_process().peek_string(lpFilename)
1078
1079 # (...)
1080
1081 Note that all pointer types are treated like void pointers, so your
1082 callback won't get the string or structure pointed to by it, but
1083 the remote memory address instead. This is so to prevent the ctypes
1084 library from being "too helpful" and trying to dereference the
1085 pointer. To get the actual data being pointed to, use one of the
1086 L{Process.read} methods.
1087
1088 @type postCB: function
1089 @param postCB: (Optional) Callback triggered on function exit.
1090
1091 The signature for the callback should be something like this::
1092
1093 def post_LoadLibraryEx(event, return_value):
1094
1095 # (...)
1096
1097 @type paramCount: int
1098 @param paramCount:
1099 (Optional) Number of parameters for the C{preCB} callback,
1100 not counting the return address. Parameters are read from
1101 the stack and assumed to be DWORDs in 32 bits and QWORDs in 64.
1102
1103 This is a faster way to pull stack parameters in 32 bits, but in 64
1104 bits (or with some odd APIs in 32 bits) it won't be useful, since
1105 not all arguments to the hooked function will be of the same size.
1106
1107 For a more reliable and cross-platform way of hooking use the
1108 C{signature} argument instead.
1109
1110 @type signature: tuple
1111 @param signature:
1112 (Optional) Tuple of C{ctypes} data types that constitute the
1113 hooked function signature. When the function is called, this will
1114 be used to parse the arguments from the stack. Overrides the
1115 C{paramCount} argument.
1116
1117 @type arch: str
1118 @param arch: (Optional) Target architecture. Defaults to the current
1119 architecture. See: L{win32.arch}
1120 """
1121 self.__preCB = preCB
1122 self.__postCB = postCB
1123 self.__paramStack = dict()
1124
1125 self._paramCount = paramCount
1126
1127 if win32.arch != win32.ARCH_I386:
1128 self.useHardwareBreakpoints = False
1129
1130 if win32.bits == 64 and paramCount and not signature:
1131 signature = (win32.QWORD,) * paramCount
1132
1133 if signature:
1134 self._signature = self._calc_signature(signature)
1135 else:
1136 self._signature = None
1137
1149
1151 raise NotImplementedError(
1152 "Hook signatures are not supported for architecture: %s" \
1153 % win32.arch)
1154
1157
1159 if self._signature or self._paramCount:
1160 raise NotImplementedError(
1161 "Hook signatures are not supported for architecture: %s" \
1162 % win32.arch)
1163 return ()
1164
1167
1168
1169
1170
1171
1172
1173
1174
1176 """
1177 Handles the breakpoint event on entry of the function.
1178
1179 @type event: L{ExceptionEvent}
1180 @param event: Breakpoint hit event.
1181
1182 @raise WindowsError: An error occured.
1183 """
1184 debug = event.debug
1185
1186 dwProcessId = event.get_pid()
1187 dwThreadId = event.get_tid()
1188 aProcess = event.get_process()
1189 aThread = event.get_thread()
1190
1191
1192 ra = self._get_return_address(aProcess, aThread)
1193 params = self._get_function_arguments(aProcess, aThread)
1194
1195
1196 self.__push_params(dwThreadId, params)
1197
1198
1199 bHookedReturn = False
1200 if ra is not None and self.__postCB is not None:
1201
1202
1203 useHardwareBreakpoints = self.useHardwareBreakpoints
1204 if useHardwareBreakpoints:
1205 try:
1206 debug.define_hardware_breakpoint(
1207 dwThreadId,
1208 ra,
1209 event.debug.BP_BREAK_ON_EXECUTION,
1210 event.debug.BP_WATCH_BYTE,
1211 True,
1212 self.__postCallAction_hwbp
1213 )
1214 debug.enable_one_shot_hardware_breakpoint(dwThreadId, ra)
1215 bHookedReturn = True
1216 except Exception, e:
1217 useHardwareBreakpoints = False
1218 msg = ("Failed to set hardware breakpoint"
1219 " at address %s for thread ID %d")
1220 msg = msg % (HexDump.address(ra), dwThreadId)
1221 warnings.warn(msg, BreakpointWarning)
1222
1223
1224 if not useHardwareBreakpoints:
1225 try:
1226 debug.break_at(dwProcessId, ra,
1227 self.__postCallAction_codebp)
1228 bHookedReturn = True
1229 except Exception, e:
1230 msg = ("Failed to set code breakpoint"
1231 " at address %s for process ID %d")
1232 msg = msg % (HexDump.address(ra), dwProcessId)
1233 warnings.warn(msg, BreakpointWarning)
1234
1235
1236 try:
1237 self.__callHandler(self.__preCB, event, ra, *params)
1238
1239
1240 finally:
1241 if not bHookedReturn:
1242 self.__pop_params(dwThreadId)
1243
1244 - def __postCallAction_hwbp(self, event):
1245 """
1246 Handles hardware breakpoint events on return from the function.
1247
1248 @type event: L{ExceptionEvent}
1249 @param event: Single step event.
1250 """
1251
1252
1253
1254 tid = event.get_tid()
1255 address = event.breakpoint.get_address()
1256 event.debug.erase_hardware_breakpoint(tid, address)
1257
1258
1259 try:
1260 self.__postCallAction(event)
1261
1262
1263 finally:
1264 self.__pop_params(tid)
1265
1266 - def __postCallAction_codebp(self, event):
1267 """
1268 Handles code breakpoint events on return from the function.
1269
1270 @type event: L{ExceptionEvent}
1271 @param event: Breakpoint hit event.
1272 """
1273
1274
1275
1276
1277
1278
1279
1280 tid = event.get_tid()
1281 if tid not in self.__paramStack:
1282 return True
1283
1284
1285 pid = event.get_pid()
1286 address = event.breakpoint.get_address()
1287 event.debug.dont_break_at(pid, address)
1288
1289
1290 try:
1291 self.__postCallAction(event)
1292
1293
1294 finally:
1295 self.__pop_params(tid)
1296
1297 - def __postCallAction(self, event):
1298 """
1299 Calls the "post" callback.
1300
1301 @type event: L{ExceptionEvent}
1302 @param event: Breakpoint hit event.
1303 """
1304 aThread = event.get_thread()
1305 retval = self._get_return_value(aThread)
1306 self.__callHandler(self.__postCB, event, retval)
1307
1309 """
1310 Calls a "pre" or "post" handler, if set.
1311
1312 @type callback: function
1313 @param callback: Callback function to call.
1314
1315 @type event: L{ExceptionEvent}
1316 @param event: Breakpoint hit event.
1317
1318 @type params: tuple
1319 @param params: Parameters for the callback function.
1320 """
1321 if callback is not None:
1322 event.hook = self
1323 callback(event, *params)
1324
1326 """
1327 Remembers the arguments tuple for the last call to the hooked function
1328 from this thread.
1329
1330 @type tid: int
1331 @param tid: Thread global ID.
1332
1333 @type params: tuple( arg, arg, arg... )
1334 @param params: Tuple of arguments.
1335 """
1336 stack = self.__paramStack.get( tid, [] )
1337 stack.append(params)
1338 self.__paramStack[tid] = stack
1339
1341 """
1342 Forgets the arguments tuple for the last call to the hooked function
1343 from this thread.
1344
1345 @type tid: int
1346 @param tid: Thread global ID.
1347 """
1348 stack = self.__paramStack[tid]
1349 stack.pop()
1350 if not stack:
1351 del self.__paramStack[tid]
1352
1354 """
1355 Returns the parameters found in the stack when the hooked function
1356 was last called by this thread.
1357
1358 @type tid: int
1359 @param tid: Thread global ID.
1360
1361 @rtype: tuple( arg, arg, arg... )
1362 @return: Tuple of arguments.
1363 """
1364 try:
1365 params = self.get_params_stack(tid)[-1]
1366 except IndexError:
1367 msg = "Hooked function called from thread %d already returned"
1368 raise IndexError(msg % tid)
1369 return params
1370
1372 """
1373 Returns the parameters found in the stack each time the hooked function
1374 was called by this thread and hasn't returned yet.
1375
1376 @type tid: int
1377 @param tid: Thread global ID.
1378
1379 @rtype: list of tuple( arg, arg, arg... )
1380 @return: List of argument tuples.
1381 """
1382 try:
1383 stack = self.__paramStack[tid]
1384 except KeyError:
1385 msg = "Hooked function was not called from thread %d"
1386 raise KeyError(msg % tid)
1387 return stack
1388
1389 - def hook(self, debug, pid, address):
1390 """
1391 Installs the function hook at a given process and address.
1392
1393 @see: L{unhook}
1394
1395 @warning: Do not call from an function hook callback.
1396
1397 @type debug: L{Debug}
1398 @param debug: Debug object.
1399
1400 @type pid: int
1401 @param pid: Process ID.
1402
1403 @type address: int
1404 @param address: Function address.
1405 """
1406 return debug.break_at(pid, address, self)
1407
1408 - def unhook(self, debug, pid, address):
1409 """
1410 Removes the function hook at a given process and address.
1411
1412 @see: L{hook}
1413
1414 @warning: Do not call from an function hook callback.
1415
1416 @type debug: L{Debug}
1417 @param debug: Debug object.
1418
1419 @type pid: int
1420 @param pid: Process ID.
1421
1422 @type address: int
1423 @param address: Function address.
1424 """
1425 return debug.dont_break_at(pid, address)
1426
1428 """
1429 Implementation details for L{Hook} on the L{win32.ARCH_I386} architecture.
1430 """
1431
1432
1433 __new__ = object.__new__
1434
1440 return Arguments
1441
1444
1446 if self._signature:
1447 params = aThread.read_stack_structure(self._signature,
1448 offset = win32.sizeof(win32.LPVOID))
1449 elif self._paramCount:
1450 params = aThread.read_stack_dwords(self._paramCount,
1451 offset = win32.sizeof(win32.LPVOID))
1452 else:
1453 params = ()
1454 return params
1455
1459
1461 """
1462 Implementation details for L{Hook} on the L{win32.ARCH_AMD64} architecture.
1463 """
1464
1465
1466 __new__ = object.__new__
1467
1468
1469 __float_types = (
1470 ctypes.c_double,
1471 ctypes.c_float,
1472 )
1473
1474 try:
1475 __float_types += (ctypes.c_longdouble,)
1476 except AttributeError:
1477 pass
1478
1480 self._cast_signature_pointers_to_void(signature)
1481
1482 float_types = self.__float_types
1483 c_sizeof = ctypes.sizeof
1484 reg_size = c_sizeof(ctypes.c_size_t)
1485
1486 reg_int_sig = []
1487 reg_float_sig = []
1488 stack_sig = []
1489
1490 for i in xrange(len(signature)):
1491 arg = signature[i]
1492 name = "arg_%d" % i
1493 stack_sig.insert( 0, (name, arg) )
1494 if i < 4:
1495 if type(arg) in float_types:
1496 reg_float_sig.append( (name, arg) )
1497 elif c_sizeof(arg) <= reg_size:
1498 reg_int_sig.append( (name, arg) )
1499 else:
1500 msg = ("Hook signatures don't support structures"
1501 " within the first 4 arguments of a function"
1502 " for the %s architecture") % win32.arch
1503 raise NotImplementedError(msg)
1504
1505 if reg_int_sig:
1506 class RegisterArguments (ctypes.Structure):
1507 _fields_ = reg_int_sig
1508 else:
1509 RegisterArguments = None
1510 if reg_float_sig:
1511 class FloatArguments (ctypes.Structure):
1512 _fields_ = reg_float_sig
1513 else:
1514 FloatArguments = None
1515 if stack_sig:
1516 class StackArguments (ctypes.Structure):
1517 _fields_ = stack_sig
1518 else:
1519 StackArguments = None
1520
1521 return (len(signature),
1522 RegisterArguments,
1523 FloatArguments,
1524 StackArguments)
1525
1528
1530 if self._signature:
1531 (args_count,
1532 RegisterArguments,
1533 FloatArguments,
1534 StackArguments) = self._signature
1535 arguments = {}
1536 if StackArguments:
1537 address = aThread.get_sp() + win32.sizeof(win32.LPVOID)
1538 stack_struct = aProcess.read_structure(address,
1539 StackArguments)
1540 stack_args = dict(
1541 [ (name, stack_struct.__getattribute__(name))
1542 for (name, type) in stack_struct._fields_ ]
1543 )
1544 arguments.update(stack_args)
1545 flags = 0
1546 if RegisterArguments:
1547 flags = flags | win32.CONTEXT_INTEGER
1548 if FloatArguments:
1549 flags = flags | win32.CONTEXT_MMX_REGISTERS
1550 if flags:
1551 ctx = aThread.get_context(flags)
1552 if RegisterArguments:
1553 buffer = (win32.QWORD * 4)(ctx['Rcx'], ctx['Rdx'],
1554 ctx['R8'], ctx['R9'])
1555 reg_args = self._get_arguments_from_buffer(buffer,
1556 RegisterArguments)
1557 arguments.update(reg_args)
1558 if FloatArguments:
1559 buffer = (win32.M128A * 4)(ctx['XMM0'], ctx['XMM1'],
1560 ctx['XMM2'], ctx['XMM3'])
1561 float_args = self._get_arguments_from_buffer(buffer,
1562 FloatArguments)
1563 arguments.update(float_args)
1564 params = tuple( [ arguments["arg_%d" % i]
1565 for i in xrange(args_count) ] )
1566 else:
1567 params = ()
1568 return params
1569
1571 b_ptr = ctypes.pointer(buffer)
1572 v_ptr = ctypes.cast(b_ptr, ctypes.c_void_p)
1573 s_ptr = ctypes.cast(v_ptr, ctypes.POINTER(structure))
1574 struct = s_ptr.contents
1575 return dict(
1576 [ (name, struct.__getattribute__(name))
1577 for (name, type) in struct._fields_ ]
1578 )
1579
1583
1584
1585
1586
1587
1588
1589 -class ApiHook (object):
1590 """
1591 Used by L{EventHandler}.
1592
1593 This class acts as an action callback for code breakpoints set at the
1594 beginning of a function. It automatically retrieves the parameters from
1595 the stack, sets a breakpoint at the return address and retrieves the
1596 return value from the function call.
1597
1598 @see: L{EventHandler.apiHooks}
1599
1600 @type modName: str
1601 @ivar modName: Module name.
1602
1603 @type procName: str
1604 @ivar procName: Procedure name.
1605 """
1606
1607 - def __init__(self, eventHandler, modName, procName, paramCount = None,
1608 signature = None):
1609 """
1610 @type eventHandler: L{EventHandler}
1611 @param eventHandler: Event handler instance. This is where the hook
1612 callbacks are to be defined (see below).
1613
1614 @type modName: str
1615 @param modName: Module name.
1616
1617 @type procName: str
1618 @param procName: Procedure name.
1619 The pre and post callbacks will be deduced from it.
1620
1621 For example, if the procedure is "LoadLibraryEx" the callback
1622 routines will be "pre_LoadLibraryEx" and "post_LoadLibraryEx".
1623
1624 The signature for the callbacks should be something like this::
1625
1626 def pre_LoadLibraryEx(self, event, ra, lpFilename, hFile, dwFlags):
1627
1628 # return address
1629 ra = params[0]
1630
1631 # function arguments start from here...
1632 szFilename = event.get_process().peek_string(lpFilename)
1633
1634 # (...)
1635
1636 def post_LoadLibraryEx(self, event, return_value):
1637
1638 # (...)
1639
1640 Note that all pointer types are treated like void pointers, so your
1641 callback won't get the string or structure pointed to by it, but
1642 the remote memory address instead. This is so to prevent the ctypes
1643 library from being "too helpful" and trying to dereference the
1644 pointer. To get the actual data being pointed to, use one of the
1645 L{Process.read} methods.
1646
1647 @type paramCount: int
1648 @param paramCount:
1649 (Optional) Number of parameters for the C{preCB} callback,
1650 not counting the return address. Parameters are read from
1651 the stack and assumed to be DWORDs in 32 bits and QWORDs in 64.
1652
1653 This is a faster way to pull stack parameters in 32 bits, but in 64
1654 bits (or with some odd APIs in 32 bits) it won't be useful, since
1655 not all arguments to the hooked function will be of the same size.
1656
1657 For a more reliable and cross-platform way of hooking use the
1658 C{signature} argument instead.
1659
1660 @type signature: tuple
1661 @param signature:
1662 (Optional) Tuple of C{ctypes} data types that constitute the
1663 hooked function signature. When the function is called, this will
1664 be used to parse the arguments from the stack. Overrides the
1665 C{paramCount} argument.
1666 """
1667 self.__modName = modName
1668 self.__procName = procName
1669 self.__paramCount = paramCount
1670 self.__signature = signature
1671 self.__preCB = getattr(eventHandler, 'pre_%s' % procName, None)
1672 self.__postCB = getattr(eventHandler, 'post_%s' % procName, None)
1673 self.__hook = dict()
1674
1676 """
1677 Handles the breakpoint event on entry of the function.
1678
1679 @type event: L{ExceptionEvent}
1680 @param event: Breakpoint hit event.
1681
1682 @raise WindowsError: An error occured.
1683 """
1684 pid = event.get_pid()
1685 try:
1686 hook = self.__hook[pid]
1687 except KeyError:
1688 hook = Hook(self.__preCB, self.__postCB,
1689 self.__paramCount, self.__signature,
1690 event.get_process().get_arch() )
1691 self.__hook[pid] = hook
1692 return hook(event)
1693
1694 @property
1696 return self.__modName
1697
1698 @property
1700 return self.__procName
1701
1702 - def hook(self, debug, pid):
1703 """
1704 Installs the API hook on a given process and module.
1705
1706 @warning: Do not call from an API hook callback.
1707
1708 @type debug: L{Debug}
1709 @param debug: Debug object.
1710
1711 @type pid: int
1712 @param pid: Process ID.
1713 """
1714 label = "%s!%s" % (self.__modName, self.__procName)
1715 try:
1716 hook = self.__hook[pid]
1717 except KeyError:
1718 try:
1719 aProcess = debug.system.get_process(pid)
1720 except KeyError:
1721 aProcess = Process(pid)
1722 hook = Hook(self.__preCB, self.__postCB,
1723 self.__paramCount, self.__signature,
1724 aProcess.get_arch() )
1725 self.__hook[pid] = hook
1726 hook.hook(debug, pid, label)
1727
1728 - def unhook(self, debug, pid):
1729 """
1730 Removes the API hook from the given process and module.
1731
1732 @warning: Do not call from an API hook callback.
1733
1734 @type debug: L{Debug}
1735 @param debug: Debug object.
1736
1737 @type pid: int
1738 @param pid: Process ID.
1739 """
1740 try:
1741 hook = self.__hook[pid]
1742 except KeyError:
1743 return
1744 label = "%s!%s" % (self.__modName, self.__procName)
1745 hook.unhook(debug, pid, label)
1746 del self.__hook[pid]
1747
1751 """
1752 Returned by L{Debug.watch_buffer}.
1753
1754 This object uniquely references a buffer being watched, even if there are
1755 multiple watches set on the exact memory region.
1756
1757 @type pid: int
1758 @ivar pid: Process ID.
1759
1760 @type start: int
1761 @ivar start: Memory address of the start of the buffer.
1762
1763 @type end: int
1764 @ivar end: Memory address of the end of the buffer.
1765
1766 @type action: callable
1767 @ivar action: Action callback.
1768
1769 @type oneshot: bool
1770 @ivar oneshot: C{True} for one shot breakpoints, C{False} otherwise.
1771 """
1772
1773 - def __init__(self, pid, start, end, action = None, oneshot = False):
1774 self.__pid = pid
1775 self.__start = start
1776 self.__end = end
1777 self.__action = action
1778 self.__oneshot = oneshot
1779
1780 @property
1783
1784 @property
1787
1788 @property
1791
1792 @property
1794 return self.__action
1795
1796 @property
1798 return self.__oneshot
1799
1800 - def match(self, address):
1801 """
1802 Determine if the given memory address lies within the watched buffer.
1803
1804 @rtype: bool
1805 @return: C{True} if the given memory address lies within the watched
1806 buffer, C{False} otherwise.
1807 """
1808 return self.__start <= address < self.__end
1809
1813 """
1814 Used by L{Debug.watch_buffer}.
1815
1816 This class acts as a condition callback for page breakpoints.
1817 It emulates page breakpoints that can overlap and/or take up less
1818 than a page's size.
1819 """
1820
1822 self.__ranges = list()
1823
1824 - def add(self, bw):
1825 """
1826 Adds a buffer watch identifier.
1827
1828 @type bw: L{BufferWatch}
1829 @param bw:
1830 Buffer watch identifier.
1831 """
1832 self.__ranges.append(bw)
1833
1835 """
1836 Removes a buffer watch identifier.
1837
1838 @type bw: L{BufferWatch}
1839 @param bw:
1840 Buffer watch identifier.
1841
1842 @raise KeyError: The buffer watch identifier was already removed.
1843 """
1844 try:
1845 self.__ranges.remove(bw)
1846 except KeyError:
1847 if not bw.oneshot:
1848 raise
1849
1851 """
1852 Removes the last buffer from the watch object
1853 to match the given address and size.
1854
1855 @type address: int
1856 @param address: Memory address of buffer to stop watching.
1857
1858 @type size: int
1859 @param size: Size in bytes of buffer to stop watching.
1860
1861 @rtype: int
1862 @return: Number of matching elements found. Only the last one to be
1863 added is actually deleted upon calling this method.
1864
1865 This counter allows you to know if there are more matching elements
1866 and how many.
1867 """
1868 count = 0
1869 start = address
1870 end = address + size - 1
1871 matched = None
1872 for item in self.__ranges:
1873 if item.match(start) and item.match(end):
1874 matched = item
1875 count += 1
1876 self.__ranges.remove(matched)
1877 return count
1878
1880 """
1881 @rtype: int
1882 @return: Number of buffers being watched.
1883 """
1884 return len(self.__ranges)
1885
1887 """
1888 Breakpoint condition callback.
1889
1890 This method will also call the action callbacks for each
1891 buffer being watched.
1892
1893 @type event: L{ExceptionEvent}
1894 @param event: Guard page exception event.
1895
1896 @rtype: bool
1897 @return: C{True} if the address being accessed belongs
1898 to at least one of the buffers that was being watched
1899 and had no action callback.
1900 """
1901 address = event.get_exception_information(1)
1902 bCondition = False
1903 for bw in self.__ranges:
1904 bMatched = bw.match(address)
1905 try:
1906 action = bw.action
1907 if bMatched and action is not None:
1908 try:
1909 action(event)
1910 except Exception, e:
1911 msg = ("Breakpoint action callback %r"
1912 " raised an exception: %s")
1913 msg = msg % (action, traceback.format_exc(e))
1914 warnings.warn(msg, BreakpointCallbackWarning)
1915 else:
1916 bCondition = bCondition or bMatched
1917 finally:
1918 if bMatched and bw.oneshot:
1919 event.debug.dont_watch_buffer(bw)
1920 return bCondition
1921
1925 """
1926 Encapsulates the capability to contain Breakpoint objects.
1927
1928 @group Breakpoints:
1929 break_at, watch_variable, watch_buffer, hook_function,
1930 dont_break_at, dont_watch_variable, dont_watch_buffer,
1931 dont_hook_function, unhook_function,
1932 break_on_error, dont_break_on_error
1933
1934 @group Stalking:
1935 stalk_at, stalk_variable, stalk_buffer, stalk_function,
1936 dont_stalk_at, dont_stalk_variable, dont_stalk_buffer,
1937 dont_stalk_function
1938
1939 @group Tracing:
1940 is_tracing, get_traced_tids,
1941 start_tracing, stop_tracing,
1942 start_tracing_process, stop_tracing_process,
1943 start_tracing_all, stop_tracing_all
1944
1945 @group Symbols:
1946 resolve_label, resolve_exported_function
1947
1948 @group Advanced breakpoint use:
1949 define_code_breakpoint,
1950 define_page_breakpoint,
1951 define_hardware_breakpoint,
1952 has_code_breakpoint,
1953 has_page_breakpoint,
1954 has_hardware_breakpoint,
1955 get_code_breakpoint,
1956 get_page_breakpoint,
1957 get_hardware_breakpoint,
1958 erase_code_breakpoint,
1959 erase_page_breakpoint,
1960 erase_hardware_breakpoint,
1961 enable_code_breakpoint,
1962 enable_page_breakpoint,
1963 enable_hardware_breakpoint,
1964 enable_one_shot_code_breakpoint,
1965 enable_one_shot_page_breakpoint,
1966 enable_one_shot_hardware_breakpoint,
1967 disable_code_breakpoint,
1968 disable_page_breakpoint,
1969 disable_hardware_breakpoint
1970
1971 @group Listing breakpoints:
1972 get_all_breakpoints,
1973 get_all_code_breakpoints,
1974 get_all_page_breakpoints,
1975 get_all_hardware_breakpoints,
1976 get_process_breakpoints,
1977 get_process_code_breakpoints,
1978 get_process_page_breakpoints,
1979 get_process_hardware_breakpoints,
1980 get_thread_hardware_breakpoints,
1981 get_all_deferred_code_breakpoints,
1982 get_process_deferred_code_breakpoints
1983
1984 @group Batch operations on breakpoints:
1985 enable_all_breakpoints,
1986 enable_one_shot_all_breakpoints,
1987 disable_all_breakpoints,
1988 erase_all_breakpoints,
1989 enable_process_breakpoints,
1990 enable_one_shot_process_breakpoints,
1991 disable_process_breakpoints,
1992 erase_process_breakpoints
1993
1994 @group Breakpoint types:
1995 BP_TYPE_ANY, BP_TYPE_CODE, BP_TYPE_PAGE, BP_TYPE_HARDWARE
1996 @group Breakpoint states:
1997 BP_STATE_DISABLED, BP_STATE_ENABLED, BP_STATE_ONESHOT, BP_STATE_RUNNING
1998 @group Memory breakpoint trigger flags:
1999 BP_BREAK_ON_EXECUTION, BP_BREAK_ON_WRITE, BP_BREAK_ON_ACCESS
2000 @group Memory breakpoint size flags:
2001 BP_WATCH_BYTE, BP_WATCH_WORD, BP_WATCH_DWORD, BP_WATCH_QWORD
2002
2003 @type BP_TYPE_ANY: int
2004 @cvar BP_TYPE_ANY: To get all breakpoints
2005 @type BP_TYPE_CODE: int
2006 @cvar BP_TYPE_CODE: To get code breakpoints only
2007 @type BP_TYPE_PAGE: int
2008 @cvar BP_TYPE_PAGE: To get page breakpoints only
2009 @type BP_TYPE_HARDWARE: int
2010 @cvar BP_TYPE_HARDWARE: To get hardware breakpoints only
2011
2012 @type BP_STATE_DISABLED: int
2013 @cvar BP_STATE_DISABLED: Breakpoint is disabled.
2014 @type BP_STATE_ENABLED: int
2015 @cvar BP_STATE_ENABLED: Breakpoint is enabled.
2016 @type BP_STATE_ONESHOT: int
2017 @cvar BP_STATE_ONESHOT: Breakpoint is enabled for one shot.
2018 @type BP_STATE_RUNNING: int
2019 @cvar BP_STATE_RUNNING: Breakpoint is running (recently hit).
2020
2021 @type BP_BREAK_ON_EXECUTION: int
2022 @cvar BP_BREAK_ON_EXECUTION: Break on code execution.
2023 @type BP_BREAK_ON_WRITE: int
2024 @cvar BP_BREAK_ON_WRITE: Break on memory write.
2025 @type BP_BREAK_ON_ACCESS: int
2026 @cvar BP_BREAK_ON_ACCESS: Break on memory read or write.
2027 """
2028
2029
2030 BP_TYPE_ANY = 0
2031 BP_TYPE_CODE = 1
2032 BP_TYPE_PAGE = 2
2033 BP_TYPE_HARDWARE = 3
2034
2035
2036 BP_STATE_DISABLED = Breakpoint.DISABLED
2037 BP_STATE_ENABLED = Breakpoint.ENABLED
2038 BP_STATE_ONESHOT = Breakpoint.ONESHOT
2039 BP_STATE_RUNNING = Breakpoint.RUNNING
2040
2041
2042 BP_BREAK_ON_EXECUTION = HardwareBreakpoint.BREAK_ON_EXECUTION
2043 BP_BREAK_ON_WRITE = HardwareBreakpoint.BREAK_ON_WRITE
2044 BP_BREAK_ON_ACCESS = HardwareBreakpoint.BREAK_ON_ACCESS
2045
2046
2047 BP_WATCH_BYTE = HardwareBreakpoint.WATCH_BYTE
2048 BP_WATCH_WORD = HardwareBreakpoint.WATCH_WORD
2049 BP_WATCH_QWORD = HardwareBreakpoint.WATCH_QWORD
2050 BP_WATCH_DWORD = HardwareBreakpoint.WATCH_DWORD
2051
2053 self.__codeBP = dict()
2054 self.__pageBP = dict()
2055 self.__hardwareBP = dict()
2056 self.__runningBP = dict()
2057 self.__tracing = set()
2058 self.__deferredBP = dict()
2059
2060
2061
2062
2063
2064
2066 "Auxiliary method."
2067 return self.__runningBP.get(tid, ())
2068
2070 "Auxiliary method."
2071 if tid not in self.__runningBP:
2072 self.__runningBP[tid] = set()
2073 self.__runningBP[tid].add(bp)
2074
2076 "Auxiliary method."
2077 self.__runningBP[tid].remove(bp)
2078 if not self.__runningBP[tid]:
2079 del self.__runningBP[tid]
2080
2087
2088
2089
2090
2091
2092
2093
2104
2106 """
2107 Auxiliary method for L{_notify_exit_thread}
2108 and L{_notify_exit_process}.
2109 """
2110 tid = event.get_tid()
2111
2112
2113 try:
2114 for bp in self.__runningBP[tid]:
2115 self.__cleanup_breakpoint(event, bp)
2116 del self.__runningBP[tid]
2117 except KeyError:
2118 pass
2119
2120
2121 try:
2122 for bp in self.__hardwareBP[tid]:
2123 self.__cleanup_breakpoint(event, bp)
2124 del self.__hardwareBP[tid]
2125 except KeyError:
2126 pass
2127
2128
2129 if tid in self.__tracing:
2130 self.__tracing.remove(tid)
2131
2133 """
2134 Auxiliary method for L{_notify_exit_process}.
2135 """
2136 pid = event.get_pid()
2137 process = event.get_process()
2138
2139
2140 for (bp_pid, bp_address) in self.__codeBP.keys():
2141 if bp_pid == pid:
2142 bp = self.__codeBP[ (bp_pid, bp_address) ]
2143 self.__cleanup_breakpoint(event, bp)
2144 del self.__codeBP[ (bp_pid, bp_address) ]
2145
2146
2147 for (bp_pid, bp_address) in self.__pageBP.keys():
2148 if bp_pid == pid:
2149 bp = self.__pageBP[ (bp_pid, bp_address) ]
2150 self.__cleanup_breakpoint(event, bp)
2151 del self.__pageBP[ (bp_pid, bp_address) ]
2152
2153
2154 try:
2155 del self.__deferredBP[pid]
2156 except KeyError:
2157 pass
2158
2160 """
2161 Auxiliary method for L{_notify_unload_dll}.
2162 """
2163 pid = event.get_pid()
2164 process = event.get_process()
2165 module = event.get_module()
2166
2167
2168 for tid in process.iter_thread_ids():
2169 thread = process.get_thread(tid)
2170
2171
2172 if tid in self.__runningBP:
2173 bplist = list(self.__runningBP[tid])
2174 for bp in bplist:
2175 bp_address = bp.get_address()
2176 if process.get_module_at_address(bp_address) == module:
2177 self.__cleanup_breakpoint(event, bp)
2178 self.__runningBP[tid].remove(bp)
2179
2180
2181 if tid in self.__hardwareBP:
2182 bplist = list(self.__hardwareBP[tid])
2183 for bp in bplist:
2184 bp_address = bp.get_address()
2185 if process.get_module_at_address(bp_address) == module:
2186 self.__cleanup_breakpoint(event, bp)
2187 self.__hardwareBP[tid].remove(bp)
2188
2189
2190 for (bp_pid, bp_address) in self.__codeBP.keys():
2191 if bp_pid == pid:
2192 if process.get_module_at_address(bp_address) == module:
2193 bp = self.__codeBP[ (bp_pid, bp_address) ]
2194 self.__cleanup_breakpoint(event, bp)
2195 del self.__codeBP[ (bp_pid, bp_address) ]
2196
2197
2198 for (bp_pid, bp_address) in self.__pageBP.keys():
2199 if bp_pid == pid:
2200 if process.get_module_at_address(bp_address) == module:
2201 bp = self.__pageBP[ (bp_pid, bp_address) ]
2202 self.__cleanup_breakpoint(event, bp)
2203 del self.__pageBP[ (bp_pid, bp_address) ]
2204
2205
2206
2207
2208
2209
2212 """
2213 Creates a disabled code breakpoint at the given address.
2214
2215 @see:
2216 L{has_code_breakpoint},
2217 L{get_code_breakpoint},
2218 L{enable_code_breakpoint},
2219 L{enable_one_shot_code_breakpoint},
2220 L{disable_code_breakpoint},
2221 L{erase_code_breakpoint}
2222
2223 @type dwProcessId: int
2224 @param dwProcessId: Process global ID.
2225
2226 @type address: int
2227 @param address: Memory address of the code instruction to break at.
2228
2229 @type condition: function
2230 @param condition: (Optional) Condition callback function.
2231
2232 The callback signature is::
2233
2234 def condition_callback(event):
2235 return True # returns True or False
2236
2237 Where B{event} is an L{Event} object,
2238 and the return value is a boolean
2239 (C{True} to dispatch the event, C{False} otherwise).
2240
2241 @type action: function
2242 @param action: (Optional) Action callback function.
2243 If specified, the event is handled by this callback instead of
2244 being dispatched normally.
2245
2246 The callback signature is::
2247
2248 def action_callback(event):
2249 pass # no return value
2250
2251 Where B{event} is an L{Event} object,
2252 and the return value is a boolean
2253 (C{True} to dispatch the event, C{False} otherwise).
2254
2255 @rtype: L{CodeBreakpoint}
2256 @return: The code breakpoint object.
2257 """
2258 process = self.system.get_process(dwProcessId)
2259 bp = CodeBreakpoint(address, condition, action)
2260
2261 key = (dwProcessId, bp.get_address())
2262 if key in self.__codeBP:
2263 msg = "Already exists (PID %d) : %r"
2264 raise KeyError(msg % (dwProcessId, self.__codeBP[key]))
2265 self.__codeBP[key] = bp
2266 return bp
2267
2268
2269 - def define_page_breakpoint(self, dwProcessId, address, pages = 1,
2270 condition = True,
2271 action = None):
2272 """
2273 Creates a disabled page breakpoint at the given address.
2274
2275 @see:
2276 L{has_page_breakpoint},
2277 L{get_page_breakpoint},
2278 L{enable_page_breakpoint},
2279 L{enable_one_shot_page_breakpoint},
2280 L{disable_page_breakpoint},
2281 L{erase_page_breakpoint}
2282
2283 @type dwProcessId: int
2284 @param dwProcessId: Process global ID.
2285
2286 @type address: int
2287 @param address: Memory address of the first page to watch.
2288
2289 @type pages: int
2290 @param pages: Number of pages to watch.
2291
2292 @type condition: function
2293 @param condition: (Optional) Condition callback function.
2294
2295 The callback signature is::
2296
2297 def condition_callback(event):
2298 return True # returns True or False
2299
2300 Where B{event} is an L{Event} object,
2301 and the return value is a boolean
2302 (C{True} to dispatch the event, C{False} otherwise).
2303
2304 @type action: function
2305 @param action: (Optional) Action callback function.
2306 If specified, the event is handled by this callback instead of
2307 being dispatched normally.
2308
2309 The callback signature is::
2310
2311 def action_callback(event):
2312 pass # no return value
2313
2314 Where B{event} is an L{Event} object,
2315 and the return value is a boolean
2316 (C{True} to dispatch the event, C{False} otherwise).
2317
2318 @rtype: L{PageBreakpoint}
2319 @return: The page breakpoint object.
2320 """
2321 process = self.system.get_process(dwProcessId)
2322 bp = PageBreakpoint(address, pages, condition, action)
2323 begin = bp.get_address()
2324 end = begin + bp.get_size()
2325
2326 address = begin
2327 pageSize = MemoryAddresses.pageSize
2328 while address < end:
2329 key = (dwProcessId, address)
2330 if key in self.__pageBP:
2331 msg = "Already exists (PID %d) : %r"
2332 msg = msg % (dwProcessId, self.__pageBP[key])
2333 raise KeyError(msg)
2334 address = address + pageSize
2335
2336 address = begin
2337 while address < end:
2338 key = (dwProcessId, address)
2339 self.__pageBP[key] = bp
2340 address = address + pageSize
2341 return bp
2342
2343
2349 """
2350 Creates a disabled hardware breakpoint at the given address.
2351
2352 @see:
2353 L{has_hardware_breakpoint},
2354 L{get_hardware_breakpoint},
2355 L{enable_hardware_breakpoint},
2356 L{enable_one_shot_hardware_breakpoint},
2357 L{disable_hardware_breakpoint},
2358 L{erase_hardware_breakpoint}
2359
2360 @note:
2361 Hardware breakpoints do not seem to work properly on VirtualBox.
2362 See U{http://www.virtualbox.org/ticket/477}.
2363
2364 @type dwThreadId: int
2365 @param dwThreadId: Thread global ID.
2366
2367 @type address: int
2368 @param address: Memory address to watch.
2369
2370 @type triggerFlag: int
2371 @param triggerFlag: Trigger of breakpoint. Must be one of the following:
2372
2373 - L{BP_BREAK_ON_EXECUTION}
2374
2375 Break on code execution.
2376
2377 - L{BP_BREAK_ON_WRITE}
2378
2379 Break on memory read or write.
2380
2381 - L{BP_BREAK_ON_ACCESS}
2382
2383 Break on memory write.
2384
2385 @type sizeFlag: int
2386 @param sizeFlag: Size of breakpoint. Must be one of the following:
2387
2388 - L{BP_WATCH_BYTE}
2389
2390 One (1) byte in size.
2391
2392 - L{BP_WATCH_WORD}
2393
2394 Two (2) bytes in size.
2395
2396 - L{BP_WATCH_DWORD}
2397
2398 Four (4) bytes in size.
2399
2400 - L{BP_WATCH_QWORD}
2401
2402 Eight (8) bytes in size.
2403
2404 @type condition: function
2405 @param condition: (Optional) Condition callback function.
2406
2407 The callback signature is::
2408
2409 def condition_callback(event):
2410 return True # returns True or False
2411
2412 Where B{event} is an L{Event} object,
2413 and the return value is a boolean
2414 (C{True} to dispatch the event, C{False} otherwise).
2415
2416 @type action: function
2417 @param action: (Optional) Action callback function.
2418 If specified, the event is handled by this callback instead of
2419 being dispatched normally.
2420
2421 The callback signature is::
2422
2423 def action_callback(event):
2424 pass # no return value
2425
2426 Where B{event} is an L{Event} object,
2427 and the return value is a boolean
2428 (C{True} to dispatch the event, C{False} otherwise).
2429
2430 @rtype: L{HardwareBreakpoint}
2431 @return: The hardware breakpoint object.
2432 """
2433 thread = self.system.get_thread(dwThreadId)
2434 bp = HardwareBreakpoint(address, triggerFlag, sizeFlag, condition,
2435 action)
2436 begin = bp.get_address()
2437 end = begin + bp.get_size()
2438
2439 if dwThreadId in self.__hardwareBP:
2440 bpSet = self.__hardwareBP[dwThreadId]
2441 for oldbp in bpSet:
2442 old_begin = oldbp.get_address()
2443 old_end = old_begin + oldbp.get_size()
2444 if MemoryAddresses.do_ranges_intersect(begin, end, old_begin,
2445 old_end):
2446 msg = "Already exists (TID %d) : %r" % (dwThreadId, oldbp)
2447 raise KeyError(msg)
2448 else:
2449 bpSet = set()
2450 self.__hardwareBP[dwThreadId] = bpSet
2451 bpSet.add(bp)
2452 return bp
2453
2454
2455
2456
2457
2459 """
2460 Checks if a code breakpoint is defined at the given address.
2461
2462 @see:
2463 L{define_code_breakpoint},
2464 L{get_code_breakpoint},
2465 L{erase_code_breakpoint},
2466 L{enable_code_breakpoint},
2467 L{enable_one_shot_code_breakpoint},
2468 L{disable_code_breakpoint}
2469
2470 @type dwProcessId: int
2471 @param dwProcessId: Process global ID.
2472
2473 @type address: int
2474 @param address: Memory address of breakpoint.
2475
2476 @rtype: bool
2477 @return: C{True} if the breakpoint is defined, C{False} otherwise.
2478 """
2479 return (dwProcessId, address) in self.__codeBP
2480
2481 - def has_page_breakpoint(self, dwProcessId, address):
2482 """
2483 Checks if a page breakpoint is defined at the given address.
2484
2485 @see:
2486 L{define_page_breakpoint},
2487 L{get_page_breakpoint},
2488 L{erase_page_breakpoint},
2489 L{enable_page_breakpoint},
2490 L{enable_one_shot_page_breakpoint},
2491 L{disable_page_breakpoint}
2492
2493 @type dwProcessId: int
2494 @param dwProcessId: Process global ID.
2495
2496 @type address: int
2497 @param address: Memory address of breakpoint.
2498
2499 @rtype: bool
2500 @return: C{True} if the breakpoint is defined, C{False} otherwise.
2501 """
2502 return (dwProcessId, address) in self.__pageBP
2503
2505 """
2506 Checks if a hardware breakpoint is defined at the given address.
2507
2508 @see:
2509 L{define_hardware_breakpoint},
2510 L{get_hardware_breakpoint},
2511 L{erase_hardware_breakpoint},
2512 L{enable_hardware_breakpoint},
2513 L{enable_one_shot_hardware_breakpoint},
2514 L{disable_hardware_breakpoint}
2515
2516 @type dwThreadId: int
2517 @param dwThreadId: Thread global ID.
2518
2519 @type address: int
2520 @param address: Memory address of breakpoint.
2521
2522 @rtype: bool
2523 @return: C{True} if the breakpoint is defined, C{False} otherwise.
2524 """
2525 if dwThreadId in self.__hardwareBP:
2526 bpSet = self.__hardwareBP[dwThreadId]
2527 for bp in bpSet:
2528 if bp.get_address() == address:
2529 return True
2530 return False
2531
2532
2533
2534
2535
2537 """
2538 Returns the internally used breakpoint object,
2539 for the code breakpoint defined at the given address.
2540
2541 @warning: It's usually best to call the L{Debug} methods
2542 instead of accessing the breakpoint objects directly.
2543
2544 @see:
2545 L{define_code_breakpoint},
2546 L{has_code_breakpoint},
2547 L{enable_code_breakpoint},
2548 L{enable_one_shot_code_breakpoint},
2549 L{disable_code_breakpoint},
2550 L{erase_code_breakpoint}
2551
2552 @type dwProcessId: int
2553 @param dwProcessId: Process global ID.
2554
2555 @type address: int
2556 @param address: Memory address where the breakpoint is defined.
2557
2558 @rtype: L{CodeBreakpoint}
2559 @return: The code breakpoint object.
2560 """
2561 key = (dwProcessId, address)
2562 if key not in self.__codeBP:
2563 msg = "No breakpoint at process %d, address %s"
2564 address = HexDump.address(address)
2565 raise KeyError(msg % (dwProcessId, address))
2566 return self.__codeBP[key]
2567
2568 - def get_page_breakpoint(self, dwProcessId, address):
2569 """
2570 Returns the internally used breakpoint object,
2571 for the page breakpoint defined at the given address.
2572
2573 @warning: It's usually best to call the L{Debug} methods
2574 instead of accessing the breakpoint objects directly.
2575
2576 @see:
2577 L{define_page_breakpoint},
2578 L{has_page_breakpoint},
2579 L{enable_page_breakpoint},
2580 L{enable_one_shot_page_breakpoint},
2581 L{disable_page_breakpoint},
2582 L{erase_page_breakpoint}
2583
2584 @type dwProcessId: int
2585 @param dwProcessId: Process global ID.
2586
2587 @type address: int
2588 @param address: Memory address where the breakpoint is defined.
2589
2590 @rtype: L{PageBreakpoint}
2591 @return: The page breakpoint object.
2592 """
2593 key = (dwProcessId, address)
2594 if key not in self.__pageBP:
2595 msg = "No breakpoint at process %d, address %s"
2596 address = HexDump.addresS(address)
2597 raise KeyError(msg % (dwProcessId, address))
2598 return self.__pageBP[key]
2599
2601 """
2602 Returns the internally used breakpoint object,
2603 for the code breakpoint defined at the given address.
2604
2605 @warning: It's usually best to call the L{Debug} methods
2606 instead of accessing the breakpoint objects directly.
2607
2608 @see:
2609 L{define_hardware_breakpoint},
2610 L{has_hardware_breakpoint},
2611 L{get_code_breakpoint},
2612 L{enable_hardware_breakpoint},
2613 L{enable_one_shot_hardware_breakpoint},
2614 L{disable_hardware_breakpoint},
2615 L{erase_hardware_breakpoint}
2616
2617 @type dwThreadId: int
2618 @param dwThreadId: Thread global ID.
2619
2620 @type address: int
2621 @param address: Memory address where the breakpoint is defined.
2622
2623 @rtype: L{HardwareBreakpoint}
2624 @return: The hardware breakpoint object.
2625 """
2626 if dwThreadId not in self.__hardwareBP:
2627 msg = "No hardware breakpoints set for thread %d"
2628 raise KeyError(msg % dwThreadId)
2629 for bp in self.__hardwareBP[dwThreadId]:
2630 if bp.is_here(address):
2631 return bp
2632 msg = "No hardware breakpoint at thread %d, address %s"
2633 raise KeyError(msg % (dwThreadId, HexDump.address(address)))
2634
2635
2636
2637
2638
2640 """
2641 Enables the code breakpoint at the given address.
2642
2643 @see:
2644 L{define_code_breakpoint},
2645 L{has_code_breakpoint},
2646 L{enable_one_shot_code_breakpoint},
2647 L{disable_code_breakpoint}
2648 L{erase_code_breakpoint},
2649
2650 @type dwProcessId: int
2651 @param dwProcessId: Process global ID.
2652
2653 @type address: int
2654 @param address: Memory address of breakpoint.
2655 """
2656 p = self.system.get_process(dwProcessId)
2657 bp = self.get_code_breakpoint(dwProcessId, address)
2658 if bp.is_running():
2659 self.__del_running_bp_from_all_threads(bp)
2660 bp.enable(p, None)
2661
2662 - def enable_page_breakpoint(self, dwProcessId, address):
2663 """
2664 Enables the page breakpoint at the given address.
2665
2666 @see:
2667 L{define_page_breakpoint},
2668 L{has_page_breakpoint},
2669 L{get_page_breakpoint},
2670 L{enable_one_shot_page_breakpoint},
2671 L{disable_page_breakpoint}
2672 L{erase_page_breakpoint},
2673
2674 @type dwProcessId: int
2675 @param dwProcessId: Process global ID.
2676
2677 @type address: int
2678 @param address: Memory address of breakpoint.
2679 """
2680 p = self.system.get_process(dwProcessId)
2681 bp = self.get_page_breakpoint(dwProcessId, address)
2682 if bp.is_running():
2683 self.__del_running_bp_from_all_threads(bp)
2684 bp.enable(p, None)
2685
2687 """
2688 Enables the hardware breakpoint at the given address.
2689
2690 @see:
2691 L{define_hardware_breakpoint},
2692 L{has_hardware_breakpoint},
2693 L{get_hardware_breakpoint},
2694 L{enable_one_shot_hardware_breakpoint},
2695 L{disable_hardware_breakpoint}
2696 L{erase_hardware_breakpoint},
2697
2698 @note: Do not set hardware breakpoints while processing the system
2699 breakpoint event.
2700
2701 @type dwThreadId: int
2702 @param dwThreadId: Thread global ID.
2703
2704 @type address: int
2705 @param address: Memory address of breakpoint.
2706 """
2707 t = self.system.get_thread(dwThreadId)
2708 bp = self.get_hardware_breakpoint(dwThreadId, address)
2709 if bp.is_running():
2710 self.__del_running_bp_from_all_threads(bp)
2711 bp.enable(None, t)
2712
2714 """
2715 Enables the code breakpoint at the given address for only one shot.
2716
2717 @see:
2718 L{define_code_breakpoint},
2719 L{has_code_breakpoint},
2720 L{get_code_breakpoint},
2721 L{enable_code_breakpoint},
2722 L{disable_code_breakpoint}
2723 L{erase_code_breakpoint},
2724
2725 @type dwProcessId: int
2726 @param dwProcessId: Process global ID.
2727
2728 @type address: int
2729 @param address: Memory address of breakpoint.
2730 """
2731 p = self.system.get_process(dwProcessId)
2732 bp = self.get_code_breakpoint(dwProcessId, address)
2733 if bp.is_running():
2734 self.__del_running_bp_from_all_threads(bp)
2735 bp.one_shot(p, None)
2736
2737 - def enable_one_shot_page_breakpoint(self, dwProcessId, address):
2738 """
2739 Enables the page breakpoint at the given address for only one shot.
2740
2741 @see:
2742 L{define_page_breakpoint},
2743 L{has_page_breakpoint},
2744 L{get_page_breakpoint},
2745 L{enable_page_breakpoint},
2746 L{disable_page_breakpoint}
2747 L{erase_page_breakpoint},
2748
2749 @type dwProcessId: int
2750 @param dwProcessId: Process global ID.
2751
2752 @type address: int
2753 @param address: Memory address of breakpoint.
2754 """
2755 p = self.system.get_process(dwProcessId)
2756 bp = self.get_page_breakpoint(dwProcessId, address)
2757 if bp.is_running():
2758 self.__del_running_bp_from_all_threads(bp)
2759 bp.one_shot(p, None)
2760
2762 """
2763 Enables the hardware breakpoint at the given address for only one shot.
2764
2765 @see:
2766 L{define_hardware_breakpoint},
2767 L{has_hardware_breakpoint},
2768 L{get_hardware_breakpoint},
2769 L{enable_hardware_breakpoint},
2770 L{disable_hardware_breakpoint}
2771 L{erase_hardware_breakpoint},
2772
2773 @type dwThreadId: int
2774 @param dwThreadId: Thread global ID.
2775
2776 @type address: int
2777 @param address: Memory address of breakpoint.
2778 """
2779 t = self.system.get_thread(dwThreadId)
2780 bp = self.get_hardware_breakpoint(dwThreadId, address)
2781 if bp.is_running():
2782 self.__del_running_bp_from_all_threads(bp)
2783 bp.one_shot(None, t)
2784
2786 """
2787 Disables the code breakpoint at the given address.
2788
2789 @see:
2790 L{define_code_breakpoint},
2791 L{has_code_breakpoint},
2792 L{get_code_breakpoint},
2793 L{enable_code_breakpoint}
2794 L{enable_one_shot_code_breakpoint},
2795 L{erase_code_breakpoint},
2796
2797 @type dwProcessId: int
2798 @param dwProcessId: Process global ID.
2799
2800 @type address: int
2801 @param address: Memory address of breakpoint.
2802 """
2803 p = self.system.get_process(dwProcessId)
2804 bp = self.get_code_breakpoint(dwProcessId, address)
2805 if bp.is_running():
2806 self.__del_running_bp_from_all_threads(bp)
2807 bp.disable(p, None)
2808
2809 - def disable_page_breakpoint(self, dwProcessId, address):
2810 """
2811 Disables the page breakpoint at the given address.
2812
2813 @see:
2814 L{define_page_breakpoint},
2815 L{has_page_breakpoint},
2816 L{get_page_breakpoint},
2817 L{enable_page_breakpoint}
2818 L{enable_one_shot_page_breakpoint},
2819 L{erase_page_breakpoint},
2820
2821 @type dwProcessId: int
2822 @param dwProcessId: Process global ID.
2823
2824 @type address: int
2825 @param address: Memory address of breakpoint.
2826 """
2827 p = self.system.get_process(dwProcessId)
2828 bp = self.get_page_breakpoint(dwProcessId, address)
2829 if bp.is_running():
2830 self.__del_running_bp_from_all_threads(bp)
2831 bp.disable(p, None)
2832
2834 """
2835 Disables the hardware breakpoint at the given address.
2836
2837 @see:
2838 L{define_hardware_breakpoint},
2839 L{has_hardware_breakpoint},
2840 L{get_hardware_breakpoint},
2841 L{enable_hardware_breakpoint}
2842 L{enable_one_shot_hardware_breakpoint},
2843 L{erase_hardware_breakpoint},
2844
2845 @type dwThreadId: int
2846 @param dwThreadId: Thread global ID.
2847
2848 @type address: int
2849 @param address: Memory address of breakpoint.
2850 """
2851 t = self.system.get_thread(dwThreadId)
2852 p = t.get_process()
2853 bp = self.get_hardware_breakpoint(dwThreadId, address)
2854 if bp.is_running():
2855 self.__del_running_bp(dwThreadId, bp)
2856 bp.disable(p, t)
2857
2858
2859
2860
2861
2863 """
2864 Erases the code breakpoint at the given address.
2865
2866 @see:
2867 L{define_code_breakpoint},
2868 L{has_code_breakpoint},
2869 L{get_code_breakpoint},
2870 L{enable_code_breakpoint},
2871 L{enable_one_shot_code_breakpoint},
2872 L{disable_code_breakpoint}
2873
2874 @type dwProcessId: int
2875 @param dwProcessId: Process global ID.
2876
2877 @type address: int
2878 @param address: Memory address of breakpoint.
2879 """
2880 bp = self.get_code_breakpoint(dwProcessId, address)
2881 if not bp.is_disabled():
2882 self.disable_code_breakpoint(dwProcessId, address)
2883 del self.__codeBP[ (dwProcessId, address) ]
2884
2885 - def erase_page_breakpoint(self, dwProcessId, address):
2886 """
2887 Erases the page breakpoint at the given address.
2888
2889 @see:
2890 L{define_page_breakpoint},
2891 L{has_page_breakpoint},
2892 L{get_page_breakpoint},
2893 L{enable_page_breakpoint},
2894 L{enable_one_shot_page_breakpoint},
2895 L{disable_page_breakpoint}
2896
2897 @type dwProcessId: int
2898 @param dwProcessId: Process global ID.
2899
2900 @type address: int
2901 @param address: Memory address of breakpoint.
2902 """
2903 bp = self.get_page_breakpoint(dwProcessId, address)
2904 begin = bp.get_address()
2905 end = begin + bp.get_size()
2906 if not bp.is_disabled():
2907 self.disable_page_breakpoint(dwProcessId, address)
2908 address = begin
2909 pageSize = MemoryAddresses.pageSize
2910 while address < end:
2911 del self.__pageBP[ (dwProcessId, address) ]
2912 address = address + pageSize
2913
2915 """
2916 Erases the hardware breakpoint at the given address.
2917
2918 @see:
2919 L{define_hardware_breakpoint},
2920 L{has_hardware_breakpoint},
2921 L{get_hardware_breakpoint},
2922 L{enable_hardware_breakpoint},
2923 L{enable_one_shot_hardware_breakpoint},
2924 L{disable_hardware_breakpoint}
2925
2926 @type dwThreadId: int
2927 @param dwThreadId: Thread global ID.
2928
2929 @type address: int
2930 @param address: Memory address of breakpoint.
2931 """
2932 bp = self.get_hardware_breakpoint(dwThreadId, address)
2933 if not bp.is_disabled():
2934 self.disable_hardware_breakpoint(dwThreadId, address)
2935 bpSet = self.__hardwareBP[dwThreadId]
2936 bpSet.remove(bp)
2937 if not bpSet:
2938 del self.__hardwareBP[dwThreadId]
2939
2940
2941
2942
2943
2945 """
2946 Returns all breakpoint objects as a list of tuples.
2947
2948 Each tuple contains:
2949 - Process global ID to which the breakpoint applies.
2950 - Thread global ID to which the breakpoint applies, or C{None}.
2951 - The L{Breakpoint} object itself.
2952
2953 @note: If you're only interested in a specific breakpoint type, or in
2954 breakpoints for a specific process or thread, it's probably faster
2955 to call one of the following methods:
2956 - L{get_all_code_breakpoints}
2957 - L{get_all_page_breakpoints}
2958 - L{get_all_hardware_breakpoints}
2959 - L{get_process_code_breakpoints}
2960 - L{get_process_page_breakpoints}
2961 - L{get_process_hardware_breakpoints}
2962 - L{get_thread_hardware_breakpoints}
2963
2964 @rtype: list of tuple( pid, tid, bp )
2965 @return: List of all breakpoints.
2966 """
2967 bplist = list()
2968
2969
2970 for (pid, bp) in self.get_all_code_breakpoints():
2971 bplist.append( (pid, None, bp) )
2972
2973
2974 for (pid, bp) in self.get_all_page_breakpoints():
2975 bplist.append( (pid, None, bp) )
2976
2977
2978 for (tid, bp) in self.get_all_hardware_breakpoints():
2979 pid = self.system.get_thread(tid).get_pid()
2980 bplist.append( (pid, tid, bp) )
2981
2982
2983 return bplist
2984
2986 """
2987 @rtype: list of tuple( int, L{CodeBreakpoint} )
2988 @return: All code breakpoints as a list of tuples (pid, bp).
2989 """
2990 return [ (pid, bp) for ((pid, address), bp) in self.__codeBP.iteritems() ]
2991
2993 """
2994 @rtype: list of tuple( int, L{PageBreakpoint} )
2995 @return: All page breakpoints as a list of tuples (pid, bp).
2996 """
2997
2998 result = set()
2999 for ((pid, address), bp) in self.__pageBP.iteritems():
3000 result.add( (pid, bp) )
3001 return list(result)
3002
3004 """
3005 @rtype: list of tuple( int, L{HardwareBreakpoint} )
3006 @return: All hardware breakpoints as a list of tuples (tid, bp).
3007 """
3008 result = list()
3009 for (tid, bplist) in self.__hardwareBP.iteritems():
3010 for bp in bplist:
3011 result.append( (tid, bp) )
3012 return result
3013
3015 """
3016 Returns all breakpoint objects for the given process as a list of tuples.
3017
3018 Each tuple contains:
3019 - Process global ID to which the breakpoint applies.
3020 - Thread global ID to which the breakpoint applies, or C{None}.
3021 - The L{Breakpoint} object itself.
3022
3023 @note: If you're only interested in a specific breakpoint type, or in
3024 breakpoints for a specific process or thread, it's probably faster
3025 to call one of the following methods:
3026 - L{get_all_code_breakpoints}
3027 - L{get_all_page_breakpoints}
3028 - L{get_all_hardware_breakpoints}
3029 - L{get_process_code_breakpoints}
3030 - L{get_process_page_breakpoints}
3031 - L{get_process_hardware_breakpoints}
3032 - L{get_thread_hardware_breakpoints}
3033
3034 @type dwProcessId: int
3035 @param dwProcessId: Process global ID.
3036
3037 @rtype: list of tuple( pid, tid, bp )
3038 @return: List of all breakpoints for the given process.
3039 """
3040 bplist = list()
3041
3042
3043 for bp in self.get_process_code_breakpoints(dwProcessId):
3044 bplist.append( (dwProcessId, None, bp) )
3045
3046
3047 for bp in self.get_process_page_breakpoints(dwProcessId):
3048 bplist.append( (dwProcessId, None, bp) )
3049
3050
3051 for (tid, bp) in self.get_process_hardware_breakpoints(dwProcessId):
3052 pid = self.system.get_thread(tid).get_pid()
3053 bplist.append( (dwProcessId, tid, bp) )
3054
3055
3056 return bplist
3057
3059 """
3060 @type dwProcessId: int
3061 @param dwProcessId: Process global ID.
3062
3063 @rtype: list of L{CodeBreakpoint}
3064 @return: All code breakpoints for the given process.
3065 """
3066 return [ bp for ((pid, address), bp) in self.__codeBP.iteritems() \
3067 if pid == dwProcessId ]
3068
3069 - def get_process_page_breakpoints(self, dwProcessId):
3070 """
3071 @type dwProcessId: int
3072 @param dwProcessId: Process global ID.
3073
3074 @rtype: list of L{PageBreakpoint}
3075 @return: All page breakpoints for the given process.
3076 """
3077 return [ bp for ((pid, address), bp) in self.__pageBP.iteritems() \
3078 if pid == dwProcessId ]
3079
3081 """
3082 @see: L{get_process_hardware_breakpoints}
3083
3084 @type dwThreadId: int
3085 @param dwThreadId: Thread global ID.
3086
3087 @rtype: list of L{HardwareBreakpoint}
3088 @return: All hardware breakpoints for the given thread.
3089 """
3090 result = list()
3091 for (tid, bplist) in self.__hardwareBP.iteritems():
3092 if tid == dwThreadId:
3093 for bp in bplist:
3094 result.append(bp)
3095 return result
3096
3098 """
3099 @see: L{get_thread_hardware_breakpoints}
3100
3101 @type dwProcessId: int
3102 @param dwProcessId: Process global ID.
3103
3104 @rtype: list of tuple( int, L{HardwareBreakpoint} )
3105 @return: All hardware breakpoints for each thread in the given process
3106 as a list of tuples (tid, bp).
3107 """
3108 result = list()
3109 aProcess = self.system.get_process(dwProcessId)
3110 for dwThreadId in aProcess.iter_thread_ids():
3111 if dwThreadId in self.__hardwareBP:
3112 bplist = self.__hardwareBP[dwThreadId]
3113 for bp in bplist:
3114 result.append( (dwThreadId, bp) )
3115 return result
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3170
3195
3217
3251
3252
3253
3254
3255
3285
3315
3342
3377
3378
3379
3380
3381
3382 - def _notify_guard_page(self, event):
3383 """
3384 Notify breakpoints of a guard page exception event.
3385
3386 @type event: L{ExceptionEvent}
3387 @param event: Guard page exception event.
3388
3389 @rtype: bool
3390 @return: C{True} to call the user-defined handle, C{False} otherwise.
3391 """
3392 address = event.get_fault_address()
3393 pid = event.get_pid()
3394 bCallHandler = True
3395
3396
3397 mask = ~(MemoryAddresses.pageSize - 1)
3398 address = address & mask
3399
3400
3401 key = (pid, address)
3402 if key in self.__pageBP:
3403 bp = self.__pageBP[key]
3404 if bp.is_enabled() or bp.is_one_shot():
3405
3406
3407 event.continueStatus = win32.DBG_CONTINUE
3408
3409
3410
3411 bp.hit(event)
3412
3413
3414 if bp.is_running():
3415 tid = event.get_tid()
3416 self.__add_running_bp(tid, bp)
3417
3418
3419 bCondition = bp.eval_condition(event)
3420
3421
3422
3423 if bCondition and bp.is_automatic():
3424 bp.run_action(event)
3425 bCallHandler = False
3426 else:
3427 bCallHandler = bCondition
3428
3429
3430
3431 else:
3432 event.continueStatus = win32.DBG_EXCEPTION_NOT_HANDLED
3433
3434 return bCallHandler
3435
3501
3641
3643 """
3644 Notify the loading of a DLL.
3645
3646 @type event: L{LoadDLLEvent}
3647 @param event: Load DLL event.
3648
3649 @rtype: bool
3650 @return: C{True} to call the user-defined handler, C{False} otherwise.
3651 """
3652 self.__set_deferred_breakpoints(event)
3653 return True
3654
3656 """
3657 Notify the unloading of a DLL.
3658
3659 @type event: L{UnloadDLLEvent}
3660 @param event: Unload DLL event.
3661
3662 @rtype: bool
3663 @return: C{True} to call the user-defined handler, C{False} otherwise.
3664 """
3665 self.__cleanup_module(event)
3666 return True
3667
3669 """
3670 Notify the termination of a thread.
3671
3672 @type event: L{ExitThreadEvent}
3673 @param event: Exit thread event.
3674
3675 @rtype: bool
3676 @return: C{True} to call the user-defined handler, C{False} otherwise.
3677 """
3678 self.__cleanup_thread(event)
3679 return True
3680
3682 """
3683 Notify the termination of a process.
3684
3685 @type event: L{ExitProcessEvent}
3686 @param event: Exit process event.
3687
3688 @rtype: bool
3689 @return: C{True} to call the user-defined handler, C{False} otherwise.
3690 """
3691 self.__cleanup_process(event)
3692 self.__cleanup_thread(event)
3693 return True
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708 - def __set_break(self, pid, address, action, oneshot):
3709 """
3710 Used by L{break_at} and L{stalk_at}.
3711
3712 @type pid: int
3713 @param pid: Process global ID.
3714
3715 @type address: int or str
3716 @param address:
3717 Memory address of code instruction to break at. It can be an
3718 integer value for the actual address or a string with a label
3719 to be resolved.
3720
3721 @type action: function
3722 @param action: (Optional) Action callback function.
3723
3724 See L{define_code_breakpoint} for more details.
3725
3726 @type oneshot: bool
3727 @param oneshot: C{True} for one-shot breakpoints, C{False} otherwise.
3728
3729 @rtype: L{Breakpoint}
3730 @return: Returns the new L{Breakpoint} object, or C{None} if the label
3731 couldn't be resolved and the breakpoint was deferred. Deferred
3732 breakpoints are set when the DLL they point to is loaded.
3733 """
3734 if type(address) not in (int, long):
3735 label = address
3736 try:
3737 address = self.system.get_process(pid).resolve_label(address)
3738 if not address:
3739 raise Exception()
3740 except Exception:
3741 try:
3742 deferred = self.__deferredBP[pid]
3743 except KeyError:
3744 deferred = dict()
3745 self.__deferredBP[pid] = deferred
3746 if label in deferred:
3747 msg = "Redefined deferred code breakpoint at %s in process ID %d"
3748 msg = msg % (label, pid)
3749 warnings.warn(msg, BreakpointWarning)
3750 deferred[label] = (action, oneshot)
3751 return None
3752 if self.has_code_breakpoint(pid, address):
3753 bp = self.get_code_breakpoint(pid, address)
3754 if bp.get_action() != action:
3755 bp.set_action(action)
3756 msg = "Redefined code breakpoint at %s in process ID %d"
3757 msg = msg % (label, pid)
3758 warnings.warn(msg, BreakpointWarning)
3759 else:
3760 self.define_code_breakpoint(pid, address, True, action)
3761 bp = self.get_code_breakpoint(pid, address)
3762 if oneshot:
3763 if not bp.is_one_shot():
3764 self.enable_one_shot_code_breakpoint(pid, address)
3765 else:
3766 if not bp.is_enabled():
3767 self.enable_code_breakpoint(pid, address)
3768 return bp
3769
3771 """
3772 Used by L{dont_break_at} and L{dont_stalk_at}.
3773
3774 @type pid: int
3775 @param pid: Process global ID.
3776
3777 @type address: int or str
3778 @param address:
3779 Memory address of code instruction to break at. It can be an
3780 integer value for the actual address or a string with a label
3781 to be resolved.
3782 """
3783 if type(address) not in (int, long):
3784 unknown = True
3785 label = address
3786 try:
3787 deferred = self.__deferredBP[pid]
3788 del deferred[label]
3789 unknown = False
3790 except KeyError:
3791
3792 pass
3793 aProcess = self.system.get_process(pid)
3794 try:
3795 address = aProcess.resolve_label(label)
3796 if not address:
3797 raise Exception()
3798 except Exception:
3799
3800 if unknown:
3801 msg = ("Can't clear unknown code breakpoint"
3802 " at %s in process ID %d")
3803 msg = msg % (label, pid)
3804 warnings.warn(msg, BreakpointWarning)
3805 return
3806 if self.has_code_breakpoint(pid, address):
3807 self.erase_code_breakpoint(pid, address)
3808
3835
3837 """
3838 Returns a list of deferred code breakpoints.
3839
3840 @rtype: tuple of (int, str, callable, bool)
3841 @return: Tuple containing the following elements:
3842 - Process ID where to set the breakpoint.
3843 - Label pointing to the address where to set the breakpoint.
3844 - Action callback for the breakpoint.
3845 - C{True} of the breakpoint is one-shot, C{False} otherwise.
3846 """
3847 result = []
3848 for pid, deferred in self.__deferredBP.iteritems():
3849 for (label, (action, oneshot)) in deferred.iteritems():
3850 result.add( (pid, label, action, oneshot) )
3851 return result
3852
3854 """
3855 Returns a list of deferred code breakpoints.
3856
3857 @type dwProcessId: int
3858 @param dwProcessId: Process ID.
3859
3860 @rtype: tuple of (int, str, callable, bool)
3861 @return: Tuple containing the following elements:
3862 - Label pointing to the address where to set the breakpoint.
3863 - Action callback for the breakpoint.
3864 - C{True} of the breakpoint is one-shot, C{False} otherwise.
3865 """
3866 return [ (label, action, oneshot)
3867 for (label, (action, oneshot))
3868 in self.__deferredBP.get(dwProcessId, {}).iteritems() ]
3869
3870 - def stalk_at(self, pid, address, action = None):
3871 """
3872 Sets a one shot code breakpoint at the given process and address.
3873
3874 If instead of an address you pass a label, the breakpoint may be
3875 deferred until the DLL it points to is loaded.
3876
3877 @see: L{break_at}, L{dont_stalk_at}
3878
3879 @type pid: int
3880 @param pid: Process global ID.
3881
3882 @type address: int or str
3883 @param address:
3884 Memory address of code instruction to break at. It can be an
3885 integer value for the actual address or a string with a label
3886 to be resolved.
3887
3888 @type action: function
3889 @param action: (Optional) Action callback function.
3890
3891 See L{define_code_breakpoint} for more details.
3892
3893 @rtype: bool
3894 @return: C{True} if the breakpoint was set immediately, or C{False} if
3895 it was deferred.
3896 """
3897 bp = self.__set_break(pid, address, action, oneshot = True)
3898 return bp is not None
3899
3900 - def break_at(self, pid, address, action = None):
3901 """
3902 Sets a code breakpoint at the given process and address.
3903
3904 If instead of an address you pass a label, the breakpoint may be
3905 deferred until the DLL it points to is loaded.
3906
3907 @see: L{stalk_at}, L{dont_break_at}
3908
3909 @type pid: int
3910 @param pid: Process global ID.
3911
3912 @type address: int or str
3913 @param address:
3914 Memory address of code instruction to break at. It can be an
3915 integer value for the actual address or a string with a label
3916 to be resolved.
3917
3918 @type action: function
3919 @param action: (Optional) Action callback function.
3920
3921 See L{define_code_breakpoint} for more details.
3922
3923 @rtype: bool
3924 @return: C{True} if the breakpoint was set immediately, or C{False} if
3925 it was deferred.
3926 """
3927 bp = self.__set_break(pid, address, action, oneshot = False)
3928 return bp is not None
3929
3931 """
3932 Clears a code breakpoint set by L{break_at}.
3933
3934 @type pid: int
3935 @param pid: Process global ID.
3936
3937 @type address: int or str
3938 @param address:
3939 Memory address of code instruction to break at. It can be an
3940 integer value for the actual address or a string with a label
3941 to be resolved.
3942 """
3943 self.__clear_break(pid, address)
3944
3946 """
3947 Clears a code breakpoint set by L{stalk_at}.
3948
3949 @type pid: int
3950 @param pid: Process global ID.
3951
3952 @type address: int or str
3953 @param address:
3954 Memory address of code instruction to break at. It can be an
3955 integer value for the actual address or a string with a label
3956 to be resolved.
3957 """
3958 self.__clear_break(pid, address)
3959
3960
3961
3962
3963
3964 - def hook_function(self, pid, address,
3965 preCB = None, postCB = None,
3966 paramCount = None, signature = None):
3967 """
3968 Sets a function hook at the given address.
3969
3970 If instead of an address you pass a label, the hook may be
3971 deferred until the DLL it points to is loaded.
3972
3973 @type pid: int
3974 @param pid: Process global ID.
3975
3976 @type address: int or str
3977 @param address:
3978 Memory address of code instruction to break at. It can be an
3979 integer value for the actual address or a string with a label
3980 to be resolved.
3981
3982 @type preCB: function
3983 @param preCB: (Optional) Callback triggered on function entry.
3984
3985 The signature for the callback should be something like this::
3986
3987 def pre_LoadLibraryEx(event, ra, lpFilename, hFile, dwFlags):
3988
3989 # return address
3990 ra = params[0]
3991
3992 # function arguments start from here...
3993 szFilename = event.get_process().peek_string(lpFilename)
3994
3995 # (...)
3996
3997 Note that all pointer types are treated like void pointers, so your
3998 callback won't get the string or structure pointed to by it, but
3999 the remote memory address instead. This is so to prevent the ctypes
4000 library from being "too helpful" and trying to dereference the
4001 pointer. To get the actual data being pointed to, use one of the
4002 L{Process.read} methods.
4003
4004 @type postCB: function
4005 @param postCB: (Optional) Callback triggered on function exit.
4006
4007 The signature for the callback should be something like this::
4008
4009 def post_LoadLibraryEx(event, return_value):
4010
4011 # (...)
4012
4013 @type paramCount: int
4014 @param paramCount:
4015 (Optional) Number of parameters for the C{preCB} callback,
4016 not counting the return address. Parameters are read from
4017 the stack and assumed to be DWORDs in 32 bits and QWORDs in 64.
4018
4019 This is a faster way to pull stack parameters in 32 bits, but in 64
4020 bits (or with some odd APIs in 32 bits) it won't be useful, since
4021 not all arguments to the hooked function will be of the same size.
4022
4023 For a more reliable and cross-platform way of hooking use the
4024 C{signature} argument instead.
4025
4026 @type signature: tuple
4027 @param signature:
4028 (Optional) Tuple of C{ctypes} data types that constitute the
4029 hooked function signature. When the function is called, this will
4030 be used to parse the arguments from the stack. Overrides the
4031 C{paramCount} argument.
4032
4033 @rtype: bool
4034 @return: C{True} if the hook was set immediately, or C{False} if
4035 it was deferred.
4036 """
4037 try:
4038 aProcess = self.system.get_process(pid)
4039 except KeyError:
4040 aProcess = Process(pid)
4041 arch = aProcess.get_arch()
4042 hookObj = Hook(preCB, postCB, paramCount, signature, arch)
4043 bp = self.break_at(pid, address, hookObj)
4044 return bp is not None
4045
4046 - def stalk_function(self, pid, address,
4047 preCB = None, postCB = None,
4048 paramCount = None, signature = None):
4049 """
4050 Sets a one-shot function hook at the given address.
4051
4052 If instead of an address you pass a label, the hook may be
4053 deferred until the DLL it points to is loaded.
4054
4055 @type pid: int
4056 @param pid: Process global ID.
4057
4058 @type address: int or str
4059 @param address:
4060 Memory address of code instruction to break at. It can be an
4061 integer value for the actual address or a string with a label
4062 to be resolved.
4063
4064 @type preCB: function
4065 @param preCB: (Optional) Callback triggered on function entry.
4066
4067 The signature for the callback should be something like this::
4068
4069 def pre_LoadLibraryEx(event, ra, lpFilename, hFile, dwFlags):
4070
4071 # return address
4072 ra = params[0]
4073
4074 # function arguments start from here...
4075 szFilename = event.get_process().peek_string(lpFilename)
4076
4077 # (...)
4078
4079 Note that all pointer types are treated like void pointers, so your
4080 callback won't get the string or structure pointed to by it, but
4081 the remote memory address instead. This is so to prevent the ctypes
4082 library from being "too helpful" and trying to dereference the
4083 pointer. To get the actual data being pointed to, use one of the
4084 L{Process.read} methods.
4085
4086 @type postCB: function
4087 @param postCB: (Optional) Callback triggered on function exit.
4088
4089 The signature for the callback should be something like this::
4090
4091 def post_LoadLibraryEx(event, return_value):
4092
4093 # (...)
4094
4095 @type paramCount: int
4096 @param paramCount:
4097 (Optional) Number of parameters for the C{preCB} callback,
4098 not counting the return address. Parameters are read from
4099 the stack and assumed to be DWORDs in 32 bits and QWORDs in 64.
4100
4101 This is a faster way to pull stack parameters in 32 bits, but in 64
4102 bits (or with some odd APIs in 32 bits) it won't be useful, since
4103 not all arguments to the hooked function will be of the same size.
4104
4105 For a more reliable and cross-platform way of hooking use the
4106 C{signature} argument instead.
4107
4108 @type signature: tuple
4109 @param signature:
4110 (Optional) Tuple of C{ctypes} data types that constitute the
4111 hooked function signature. When the function is called, this will
4112 be used to parse the arguments from the stack. Overrides the
4113 C{paramCount} argument.
4114
4115 @rtype: bool
4116 @return: C{True} if the breakpoint was set immediately, or C{False} if
4117 it was deferred.
4118 """
4119 try:
4120 aProcess = self.system.get_process(pid)
4121 except KeyError:
4122 aProcess = Process(pid)
4123 arch = aProcess.get_arch()
4124 hookObj = Hook(preCB, postCB, paramCount, signature, arch)
4125 bp = self.stalk_at(pid, address, hookObj)
4126 return bp is not None
4127
4129 """
4130 Removes a function hook set by L{hook_function}.
4131
4132 @type pid: int
4133 @param pid: Process global ID.
4134
4135 @type address: int or str
4136 @param address:
4137 Memory address of code instruction to break at. It can be an
4138 integer value for the actual address or a string with a label
4139 to be resolved.
4140 """
4141 self.dont_break_at(pid, address)
4142
4143
4144 unhook_function = dont_hook_function
4145
4147 """
4148 Removes a function hook set by L{stalk_function}.
4149
4150 @type pid: int
4151 @param pid: Process global ID.
4152
4153 @type address: int or str
4154 @param address:
4155 Memory address of code instruction to break at. It can be an
4156 integer value for the actual address or a string with a label
4157 to be resolved.
4158 """
4159 self.dont_stalk_at(pid, address)
4160
4161
4162
4163
4164
4166 """
4167 Used by L{watch_variable} and L{stalk_variable}.
4168
4169 @type tid: int
4170 @param tid: Thread global ID.
4171
4172 @type address: int
4173 @param address: Memory address of variable to watch.
4174
4175 @type size: int
4176 @param size: Size of variable to watch. The only supported sizes are:
4177 byte (1), word (2), dword (4) and qword (8).
4178
4179 @type action: function
4180 @param action: (Optional) Action callback function.
4181
4182 See L{define_hardware_breakpoint} for more details.
4183
4184 @rtype: L{HardwareBreakpoint}
4185 @return: Hardware breakpoint at the requested address.
4186 """
4187
4188
4189
4190
4191
4192
4193 if size == 1:
4194 sizeFlag = self.BP_WATCH_BYTE
4195 elif size == 2:
4196 sizeFlag = self.BP_WATCH_WORD
4197 elif size == 4:
4198 sizeFlag = self.BP_WATCH_DWORD
4199 elif size == 8:
4200 sizeFlag = self.BP_WATCH_QWORD
4201 else:
4202 raise ValueError("Bad size for variable watch: %r" % size)
4203
4204 if self.has_hardware_breakpoint(tid, address):
4205 warnings.warn(
4206 "Hardware breakpoint in thread %d at address %s was overwritten!" \
4207 % (tid, HexDump.address(address,
4208 self.system.get_thread(tid).get_bits())),
4209 BreakpointWarning)
4210
4211 bp = self.get_hardware_breakpoint(tid, address)
4212 if bp.get_trigger() != self.BP_BREAK_ON_ACCESS or \
4213 bp.get_watch() != sizeFlag:
4214 self.erase_hardware_breakpoint(tid, address)
4215 self.define_hardware_breakpoint(tid, address,
4216 self.BP_BREAK_ON_ACCESS, sizeFlag, True, action)
4217 bp = self.get_hardware_breakpoint(tid, address)
4218
4219 else:
4220 self.define_hardware_breakpoint(tid, address,
4221 self.BP_BREAK_ON_ACCESS, sizeFlag, True, action)
4222 bp = self.get_hardware_breakpoint(tid, address)
4223
4224 return bp
4225
4238
4240 """
4241 Sets a hardware breakpoint at the given thread, address and size.
4242
4243 @see: L{dont_watch_variable}
4244
4245 @type tid: int
4246 @param tid: Thread global ID.
4247
4248 @type address: int
4249 @param address: Memory address of variable to watch.
4250
4251 @type size: int
4252 @param size: Size of variable to watch. The only supported sizes are:
4253 byte (1), word (2), dword (4) and qword (8).
4254
4255 @type action: function
4256 @param action: (Optional) Action callback function.
4257
4258 See L{define_hardware_breakpoint} for more details.
4259 """
4260 bp = self.__set_variable_watch(tid, address, size, action)
4261 if not bp.is_enabled():
4262 self.enable_hardware_breakpoint(tid, address)
4263
4265 """
4266 Sets a one-shot hardware breakpoint at the given thread,
4267 address and size.
4268
4269 @see: L{dont_watch_variable}
4270
4271 @type tid: int
4272 @param tid: Thread global ID.
4273
4274 @type address: int
4275 @param address: Memory address of variable to watch.
4276
4277 @type size: int
4278 @param size: Size of variable to watch. The only supported sizes are:
4279 byte (1), word (2), dword (4) and qword (8).
4280
4281 @type action: function
4282 @param action: (Optional) Action callback function.
4283
4284 See L{define_hardware_breakpoint} for more details.
4285 """
4286 bp = self.__set_variable_watch(tid, address, size, action)
4287 if not bp.is_one_shot():
4288 self.enable_one_shot_hardware_breakpoint(tid, address)
4289
4291 """
4292 Clears a hardware breakpoint set by L{watch_variable}.
4293
4294 @type tid: int
4295 @param tid: Thread global ID.
4296
4297 @type address: int
4298 @param address: Memory address of variable to stop watching.
4299 """
4300 self.__clear_variable_watch(tid, address)
4301
4303 """
4304 Clears a hardware breakpoint set by L{stalk_variable}.
4305
4306 @type tid: int
4307 @param tid: Thread global ID.
4308
4309 @type address: int
4310 @param address: Memory address of variable to stop watching.
4311 """
4312 self.__clear_variable_watch(tid, address)
4313
4314
4315
4316
4317
4319 """
4320 Used by L{watch_buffer} and L{stalk_buffer}.
4321
4322 @type pid: int
4323 @param pid: Process global ID.
4324
4325 @type address: int
4326 @param address: Memory address of buffer to watch.
4327
4328 @type size: int
4329 @param size: Size in bytes of buffer to watch.
4330
4331 @type action: function
4332 @param action: (Optional) Action callback function.
4333
4334 See L{define_page_breakpoint} for more details.
4335
4336 @type bOneShot: bool
4337 @param bOneShot:
4338 C{True} to set a one-shot breakpoint,
4339 C{False} to set a normal breakpoint.
4340 """
4341
4342
4343 if size < 1:
4344 raise ValueError("Bad size for buffer watch: %r" % size)
4345
4346
4347 bw = BufferWatch(pid, address, address + size, action, bOneShot)
4348
4349
4350 base = MemoryAddresses.align_address_to_page_start(address)
4351 limit = MemoryAddresses.align_address_to_page_end(address + size)
4352 pages = MemoryAddresses.get_buffer_size_in_pages(address, size)
4353
4354 try:
4355
4356
4357
4358
4359
4360 bset = set()
4361 nset = set()
4362 cset = set()
4363
4364 page_addr = base
4365 pageSize = MemoryAddresses.pageSize
4366 while page_addr < limit:
4367
4368
4369 if self.has_page_breakpoint(pid, page_addr):
4370 bp = self.get_page_breakpoint(pid, page_addr)
4371 if bp not in bset:
4372 condition = bp.get_condition()
4373 if not condition in cset:
4374 if not isinstance(condition,_BufferWatchCondition):
4375
4376
4377
4378 msg = "Can't watch buffer at page %s"
4379 msg = msg % HexDump.address(page_addr)
4380 raise RuntimeError(msg)
4381 cset.add(condition)
4382 bset.add(bp)
4383
4384
4385 else:
4386 condition = _BufferWatchCondition()
4387 bp = self.define_page_breakpoint(pid, page_addr, 1,
4388 condition = condition)
4389 bset.add(bp)
4390 nset.add(bp)
4391 cset.add(condition)
4392
4393
4394 page_addr = page_addr + pageSize
4395
4396
4397 aProcess = self.system.get_process(pid)
4398 for bp in bset:
4399 if bp.is_disabled() or bp.is_one_shot():
4400 bp.enable(aProcess, None)
4401
4402
4403 except:
4404
4405
4406 for bp in nset:
4407 try:
4408 self.erase_page_breakpoint(pid, bp.get_address())
4409 except:
4410 pass
4411
4412
4413 raise
4414
4415
4416 for condition in cset:
4417 condition.add(bw)
4418
4468
4512
4513 - def watch_buffer(self, pid, address, size, action = None):
4514 """
4515 Sets a page breakpoint and notifies when the given buffer is accessed.
4516
4517 @see: L{dont_watch_variable}
4518
4519 @type pid: int
4520 @param pid: Process global ID.
4521
4522 @type address: int
4523 @param address: Memory address of buffer to watch.
4524
4525 @type size: int
4526 @param size: Size in bytes of buffer to watch.
4527
4528 @type action: function
4529 @param action: (Optional) Action callback function.
4530
4531 See L{define_page_breakpoint} for more details.
4532
4533 @rtype: L{BufferWatch}
4534 @return: Buffer watch identifier.
4535 """
4536 self.__set_buffer_watch(pid, address, size, action, False)
4537
4538 - def stalk_buffer(self, pid, address, size, action = None):
4539 """
4540 Sets a one-shot page breakpoint and notifies
4541 when the given buffer is accessed.
4542
4543 @see: L{dont_watch_variable}
4544
4545 @type pid: int
4546 @param pid: Process global ID.
4547
4548 @type address: int
4549 @param address: Memory address of buffer to watch.
4550
4551 @type size: int
4552 @param size: Size in bytes of buffer to watch.
4553
4554 @type action: function
4555 @param action: (Optional) Action callback function.
4556
4557 See L{define_page_breakpoint} for more details.
4558
4559 @rtype: L{BufferWatch}
4560 @return: Buffer watch identifier.
4561 """
4562 self.__set_buffer_watch(pid, address, size, action, True)
4563
4565 """
4566 Clears a page breakpoint set by L{watch_buffer}.
4567
4568 @type bw: L{BufferWatch}
4569 @param bw:
4570 Buffer watch identifier returned by L{watch_buffer}.
4571 """
4572
4573
4574 if not (argv or argd):
4575 self.__clear_buffer_watch(bw)
4576
4577
4578 else:
4579 argv = list(argv)
4580 argv.insert(0, bw)
4581 if 'pid' in argd:
4582 argv.insert(0, argd.pop('pid'))
4583 if 'address' in argd:
4584 argv.insert(1, argd.pop('address'))
4585 if 'size' in argd:
4586 argv.insert(2, argd.pop('size'))
4587 if argd:
4588 raise TypeError("Wrong arguments for dont_watch_buffer()")
4589 try:
4590 pid, address, size = argv
4591 except ValueError:
4592 raise TypeError("Wrong arguments for dont_watch_buffer()")
4593 self.__clear_buffer_watch_old_method(pid, address, size)
4594
4596 """
4597 Clears a page breakpoint set by L{stalk_buffer}.
4598
4599 @type bw: L{BufferWatch}
4600 @param bw:
4601 Buffer watch identifier returned by L{stalk_buffer}.
4602 """
4603 self.dont_watch_buffer(bw, *argv, **argd)
4604
4605
4606
4607
4608
4609
4610
4611
4613 """
4614 @type thread: L{Thread}
4615 @param thread: Thread to start tracing.
4616 """
4617 tid = thread.get_tid()
4618 if not tid in self.__tracing:
4619 thread.set_tf()
4620 self.__tracing.add(tid)
4621
4632
4634 """
4635 @type tid: int
4636 @param tid: Thread global ID.
4637
4638 @rtype: bool
4639 @return: C{True} if the thread is being traced, C{False} otherwise.
4640 """
4641 return tid in self.__tracing
4642
4644 """
4645 Retrieves the list of global IDs of all threads being traced.
4646
4647 @rtype: list( int... )
4648 @return: List of thread global IDs.
4649 """
4650 tids = list(self.__tracing)
4651 tids.sort()
4652 return tids
4653
4664
4675
4685
4695
4702
4709
4710
4711
4712
4713
4715 """
4716 Sets or clears the system breakpoint for a given Win32 error code.
4717
4718 Use L{Process.is_system_defined_breakpoint} to tell if a breakpoint
4719 exception was caused by a system breakpoint or by the application
4720 itself (for example because of a failed assertion in the code).
4721
4722 @note: This functionality is only available since Windows Server 2003.
4723 In 2003 it only breaks on error values set externally to the
4724 kernel32.dll library, but this was fixed in Windows Vista.
4725
4726 @warn: This method will fail if the debug symbols for ntdll (kernel32
4727 in Windows 2003) are not present. For more information see:
4728 L{System.fix_symbol_store_path}.
4729
4730 @see: U{http://www.nynaeve.net/?p=147}
4731
4732 @type pid: int
4733 @param pid: Process ID.
4734
4735 @type errorCode: int
4736 @param errorCode: Win32 error code to stop on. Set to C{0} or
4737 C{ERROR_SUCCESS} to clear the breakpoint instead.
4738
4739 @raise NotImplementedError:
4740 The functionality is not supported in this system.
4741
4742 @raise WindowsError:
4743 An error occurred while processing this request.
4744 """
4745 aProcess = self.system.get_process(pid)
4746 address = aProcess.get_break_on_error_ptr()
4747 if not address:
4748 raise NotImplementedError(
4749 "The functionality is not supported in this system.")
4750 aProcess.write_dword(address, errorCode)
4751
4753 """
4754 Alias to L{break_on_error}C{(pid, ERROR_SUCCESS)}.
4755
4756 @type pid: int
4757 @param pid: Process ID.
4758
4759 @raise NotImplementedError:
4760 The functionality is not supported in this system.
4761
4762 @raise WindowsError:
4763 An error occurred while processing this request.
4764 """
4765 self.break_on_error(pid, 0)
4766
4767
4768
4769
4770
4772 """
4773 Resolves the exported DLL function for the given process.
4774
4775 @type pid: int
4776 @param pid: Process global ID.
4777
4778 @type modName: str
4779 @param modName: Name of the module that exports the function.
4780
4781 @type procName: str
4782 @param procName: Name of the exported function to resolve.
4783
4784 @rtype: int, None
4785 @return: On success, the address of the exported function.
4786 On failure, returns C{None}.
4787 """
4788 aProcess = self.system.get_process(pid)
4789 aModule = aProcess.get_module_by_name(modName)
4790 if not aModule:
4791 aProcess.scan_modules()
4792 aModule = aProcess.get_module_by_name(modName)
4793 if aModule:
4794 address = aModule.resolve(procName)
4795 return address
4796 return None
4797
4799 """
4800 Resolves a label for the given process.
4801
4802 @type pid: int
4803 @param pid: Process global ID.
4804
4805 @type label: str
4806 @param label: Label to resolve.
4807
4808 @rtype: int
4809 @return: Memory address pointed to by the label.
4810
4811 @raise ValueError: The label is malformed or impossible to resolve.
4812 @raise RuntimeError: Cannot resolve the module or function.
4813 """
4814 return self.get_process(pid).resolve_label(label)
4815