1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 """
29 Breakpoints module.
30
31 @see: U{http://apps.sourceforge.net/trac/winappdbg/wiki/wiki/HowBreakpointsWork}
32
33 @group Breakpoints: Breakpoint, CodeBreakpoint, PageBreakpoint, HardwareBreakpoint
34 @group Breakpoint wrappers: Hook, ApiHook, BufferWatch
35 @group Debug registers manipulation: DebugRegister
36 @group Breakpoint container capabilities: BreakpointContainer
37 """
38
39 __revision__ = "$Id: breakpoint.py 626 2010-02-12 21:54:30Z qvasimodo $"
40
41 __all__ = [
42
43
44 'Breakpoint',
45
46
47 'CodeBreakpoint',
48 'PageBreakpoint',
49 'HardwareBreakpoint',
50
51
52 'DebugRegister',
53
54
55 'Hook',
56 'ApiHook',
57 'BufferWatch',
58
59
60 'BreakpointContainer',
61
62 ]
63
64 from system import Process, System, MemoryAddresses
65 from textio import HexDump
66 import win32
71 """
72 Class to manipulate debug registers.
73 Used by L{HardwareBreakpoint}.
74
75 @group Trigger flags used by HardwareBreakpoint:
76 BREAK_ON_EXECUTION, BREAK_ON_WRITE, BREAK_ON_ACCESS, BREAK_ON_IO_ACCESS
77 @group Size flags used by HardwareBreakpoint:
78 WATCH_BYTE, WATCH_WORD, WATCH_DWORD, WATCH_QWORD
79 @group Bitwise masks for Dr7:
80 enableMask, disableMask, triggerMask, watchMask, clearMask
81 @group Bitwise masks for Dr6:
82 hitMask
83
84 @type BREAK_ON_EXECUTION: int
85 @cvar BREAK_ON_EXECUTION: Break on execution.
86
87 @type BREAK_ON_WRITE: int
88 @cvar BREAK_ON_WRITE: Break on write.
89
90 @type BREAK_ON_ACCESS: int
91 @cvar BREAK_ON_ACCESS: Break on read or write.
92
93 @type BREAK_ON_IO_ACCESS: int
94 @cvar BREAK_ON_IO_ACCESS: Break on I/O port access.
95
96 @type WATCH_BYTE: int
97 @cvar WATCH_BYTE: Watch a byte.
98
99 @type WATCH_WORD: int
100 @cvar WATCH_WORD: Watch a word.
101
102 @type WATCH_DWORD: int
103 @cvar WATCH_DWORD: Watch a double word.
104
105 @type WATCH_QWORD: int
106 @cvar WATCH_QWORD: Watch one quad word.
107
108 @type enableMask: 4-tuple of integers
109 @cvar enableMask:
110 Enable bit on Dr7 for each slot.
111 Works as a bitwise-OR mask.
112
113 @type disableMask: 4-tuple of integers
114 @cvar disableMask:
115 Mask of the enable bit on Dr7 for each slot.
116 Works as a bitwise-AND mask.
117
118 @type triggerMask: 4-tuple of 2-tuples of integers
119 @cvar triggerMask:
120 Trigger bits on Dr7 for each trigger flag value.
121 Each 2-tuple has the bitwise-OR mask and the bitwise-AND mask.
122
123 @type watchMask: 4-tuple of 2-tuples of integers
124 @cvar watchMask:
125 Watch bits on Dr7 for each watch flag value.
126 Each 2-tuple has the bitwise-OR mask and the bitwise-AND mask.
127
128 @type clearMask: 4-tuple of integers
129 @cvar clearMask:
130 Mask of all important bits on Dr7 for each slot.
131 Works as a bitwise-AND mask.
132
133 @type hitMask: 4-tuple of integers
134 @cvar hitMask:
135 Hit bit on Dr6 for each slot.
136 Works as a bitwise-AND mask.
137 """
138
139 BREAK_ON_EXECUTION = 0
140 BREAK_ON_WRITE = 1
141 BREAK_ON_ACCESS = 3
142 BREAK_ON_IO_ACCESS = 2
143
144 WATCH_BYTE = 0
145 WATCH_WORD = 1
146 WATCH_DWORD = 3
147 WATCH_QWORD = 2
148
149 registerMask = win32.SIZE_T(-1).value
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178 enableMask = (
179 1 << 0,
180 1 << 2,
181 1 << 4,
182 1 << 6,
183 )
184
185
186 disableMask = tuple( [registerMask ^ x for x in enableMask] )
187 del x
188
189
190
191
192 triggerMask = (
193
194 (
195 ((0 << 16), (3 << 16) ^ registerMask),
196 ((1 << 16), (3 << 16) ^ registerMask),
197 ((2 << 16), (3 << 16) ^ registerMask),
198 ((3 << 16), (3 << 16) ^ registerMask),
199 ),
200
201 (
202 ((0 << 20), (3 << 20) ^ registerMask),
203 ((1 << 20), (3 << 20) ^ registerMask),
204 ((2 << 20), (3 << 20) ^ registerMask),
205 ((3 << 20), (3 << 20) ^ registerMask),
206 ),
207
208 (
209 ((0 << 24), (3 << 24) ^ registerMask),
210 ((1 << 24), (3 << 24) ^ registerMask),
211 ((2 << 24), (3 << 24) ^ registerMask),
212 ((3 << 24), (3 << 24) ^ registerMask),
213 ),
214
215 (
216 ((0 << 28), (3 << 28) ^ registerMask),
217 ((1 << 28), (3 << 28) ^ registerMask),
218 ((2 << 28), (3 << 28) ^ registerMask),
219 ((3 << 28), (3 << 28) ^ registerMask),
220 ),
221 )
222
223
224
225
226 watchMask = (
227
228 (
229 ((0 << 18), (3 << 18) ^ registerMask),
230 ((1 << 18), (3 << 18) ^ registerMask),
231 ((2 << 18), (3 << 18) ^ registerMask),
232 ((3 << 18), (3 << 18) ^ registerMask),
233 ),
234
235 (
236 ((0 << 23), (3 << 23) ^ registerMask),
237 ((1 << 23), (3 << 23) ^ registerMask),
238 ((2 << 23), (3 << 23) ^ registerMask),
239 ((3 << 23), (3 << 23) ^ registerMask),
240 ),
241
242 (
243 ((0 << 26), (3 << 26) ^ registerMask),
244 ((1 << 26), (3 << 26) ^ registerMask),
245 ((2 << 26), (3 << 26) ^ registerMask),
246 ((3 << 26), (3 << 26) ^ registerMask),
247 ),
248
249 (
250 ((0 << 30), (3 << 31) ^ registerMask),
251 ((1 << 30), (3 << 31) ^ registerMask),
252 ((2 << 30), (3 << 31) ^ registerMask),
253 ((3 << 30), (3 << 31) ^ registerMask),
254 ),
255 )
256
257
258 clearMask = (
259 registerMask ^ ( (1 << 0) + (3 << 16) + (3 << 18) ),
260 registerMask ^ ( (1 << 2) + (3 << 20) + (3 << 22) ),
261 registerMask ^ ( (1 << 4) + (3 << 24) + (3 << 26) ),
262 registerMask ^ ( (1 << 6) + (3 << 28) + (3 << 30) ),
263 )
264
265
266
267
268
269
270
271
272
273
274
275
276
277 hitMask = (
278 (1 << 0),
279 (1 << 1),
280 (1 << 2),
281 (1 << 3),
282 )
283
284
285
286 @classmethod
288 """
289 Clears a hardware breakpoint.
290
291 @see: find_slot, set_bp
292
293 @type ctx: dict( str S{->} int )
294 @param ctx: Thread context dictionary.
295
296 @type register: int
297 @param register: Slot (debug register) for hardware breakpoint.
298 """
299 ctx['Dr7'] &= cls.clearMask[register]
300 ctx['Dr%d' % register] = 0
301
302 @classmethod
303 - def set_bp(cls, ctx, register, address, trigger, watch):
304 """
305 Sets a hardware breakpoint.
306
307 @see: clear_bp, find_slot
308
309 @type ctx: dict( str S{->} int )
310 @param ctx: Thread context dictionary.
311
312 @type register: int
313 @param register: Slot (debug register).
314
315 @type address: int
316 @param address: Memory address.
317
318 @type trigger: int
319 @param trigger: Trigger flag. See L{HardwareBreakpoint.validTriggers}.
320
321 @type watch: int
322 @param watch: Watch flag. See L{HardwareBreakpoint.validWatchSizes}.
323 """
324 Dr7 = ctx['Dr7']
325 Dr7 |= cls.enableMask[register]
326 orMask, andMask = cls.triggerMask[register][trigger]
327 Dr7 &= andMask
328 Dr7 |= orMask
329 orMask, andMask = cls.watchMask[register][watch]
330 Dr7 &= andMask
331 Dr7 |= orMask
332 ctx['Dr7'] = Dr7
333 ctx['Dr%d' % register] = address
334
335 @classmethod
337 """
338 Finds an empty slot to set a hardware breakpoint.
339
340 @see: clear_bp, set_bp
341
342 @type ctx: dict( str S{->} int )
343 @param ctx: Thread context dictionary.
344
345 @rtype: int
346 @return: Slot (debug register) for hardware breakpoint.
347 """
348 Dr7 = ctx['Dr7']
349 slot = 0
350 for m in cls.enableMask:
351 if (Dr7 & m) == 0:
352 return slot
353 slot += 1
354 return None
355
359 """
360 Base class for breakpoints.
361 Here's the breakpoints state machine.
362
363 @see: L{CodeBreakpoint}, L{PageBreakpoint}, L{HardwareBreakpoint}
364
365 @group Breakpoint states:
366 DISABLED, ENABLED, ONESHOT, RUNNING
367 @group State machine:
368 hit, disable, enable, one_shot, running,
369 is_disabled, is_enabled, is_one_shot, is_running,
370 get_state, get_state_name
371 @group Information:
372 get_address, get_size, is_here
373 @group Conditional breakpoints:
374 is_conditional, is_unconditional,
375 get_condition, set_condition, eval_condition
376 @group Automatic breakpoints:
377 is_automatic, is_interactive,
378 get_action, set_action, run_action
379
380 @cvar DISABLED: I{Disabled} S{->} Enabled, OneShot
381 @cvar ENABLED: I{Enabled} S{->} I{Running}, Disabled
382 @cvar ONESHOT: I{OneShot} S{->} I{Disabled}
383 @cvar RUNNING: I{Running} S{->} I{Enabled}, Disabled
384
385 @type DISABLED: int
386 @type ENABLED: int
387 @type ONESHOT: int
388 @type RUNNING: int
389
390 @type stateNames: dict E{lb} int S{->} str E{rb}
391 @cvar stateNames: User-friendly names for each breakpoint state.
392
393 @type typeName: str
394 @cvar typeName: User friendly breakpoint type string.
395 """
396
397
398
399
400 DISABLED = 0
401 ENABLED = 1
402 ONESHOT = 2
403 RUNNING = 3
404
405 typeName = 'breakpoint'
406
407 stateNames = {
408 DISABLED : 'disabled',
409 ENABLED : 'enabled',
410 ONESHOT : 'one shot',
411 RUNNING : 'running',
412 }
413
414 - def __init__(self, address, size = 1, condition = True, action = None):
415 """
416 Breakpoint object.
417
418 @type address: int
419 @param address: Memory address for breakpoint.
420
421 @type size: int
422 @param size: Size of breakpoint in bytes (defaults to 1).
423
424 @type condition: function
425 @param condition: (Optional) Condition callback function.
426
427 The callback signature is::
428
429 def condition_callback(event):
430 return True # returns True or False
431
432 Where B{event} is an L{Event} object,
433 and the return value is a boolean
434 (C{True} to dispatch the event, C{False} otherwise).
435
436 @type action: function
437 @param action: (Optional) Action callback function.
438 If specified, the event is handled by this callback instead of
439 being dispatched normally.
440
441 The callback signature is::
442
443 def action_callback(event):
444 pass # no return value
445
446 Where B{event} is an L{Event} object.
447 """
448 self.__address = address
449 self.__size = size
450 self.__state = self.DISABLED
451
452 self.set_condition(condition)
453 self.set_action(action)
454
477
478
479
481 """
482 @rtype: bool
483 @return: C{True} if the breakpoint is in L{DISABLED} state.
484 """
485 return self.get_state() == self.DISABLED
486
488 """
489 @rtype: bool
490 @return: C{True} if the breakpoint is in L{ENABLED} state.
491 """
492 return self.get_state() == self.ENABLED
493
495 """
496 @rtype: bool
497 @return: C{True} if the breakpoint is in L{ONESHOT} state.
498 """
499 return self.get_state() == self.ONESHOT
500
502 """
503 @rtype: bool
504 @return: C{True} if the breakpoint is in L{RUNNING} state.
505 """
506 return self.get_state() == self.RUNNING
507
509 """
510 @rtype: bool
511 @return: C{True} if the address is within the range of the breakpoint.
512 """
513 begin = self.get_address()
514 end = begin + self.get_size()
515 return begin <= address < end
516
518 """
519 @rtype: int
520 @return: The target memory address for the breakpoint.
521 """
522 return self.__address
523
525 """
526 @rtype: int
527 @return: The size in bytes of the breakpoint.
528 """
529 return self.__size
530
532 """
533 @rtype: tuple( int, int )
534 @return:
535 Starting and ending address of the memory range
536 covered by the breakpoint.
537 """
538 address = self.get_address()
539 size = self.get_size()
540 return ( address, address + size )
541
543 """
544 @rtype: int
545 @return: The current state of the breakpoint
546 (L{DISABLED}, L{ENABLED}, L{ONESHOT}, L{RUNNING}).
547 """
548 return self.__state
549
551 """
552 @rtype: str
553 @return: The name of the current state of the breakpoint.
554 """
555 return self.stateNames[ self.get_state() ]
556
557
558
560 """
561 @see: L{__init__}
562 @rtype: bool
563 @return: C{True} if the breakpoint has a condition callback defined.
564 """
565 return self.__condition is not True
566
568 """
569 @rtype: bool
570 @return: C{True} if the breakpoint doesn't have a condition callback defined.
571 """
572 return self.__condition is True
573
575 """
576 @rtype: bool, function
577 @return: Returns the condition callback for conditional breakpoints.
578 Returns C{True} for unconditional breakpoints.
579 """
580 return self.__condition
581
583 """
584 Sets a new condition callback for the breakpoint.
585
586 @see: L{__init__}
587
588 @type condition: function
589 @param condition: (Optional) Condition callback function.
590 """
591 if condition in (False, None):
592 condition = True
593 self.__condition = condition
594
596 """
597 Evaluates the breakpoint condition, if any was set.
598
599 @type event: L{Event}
600 @param event: Debug event triggered by the breakpoint.
601
602 @rtype: bool
603 @return: C{True} to dispatch the event, C{False} otherwise.
604 """
605 if self.__condition in (True, False, None):
606 return self.__condition
607 return self.__condition(event)
608
609
610
612 """
613 @rtype: bool
614 @return: C{True} if the breakpoint has an action callback defined.
615 """
616 return self.__action is not None
617
619 """
620 @rtype: bool
621 @return:
622 C{True} if the breakpoint doesn't have an action callback defined.
623 """
624 return self.__action is None
625
627 """
628 @rtype: bool, function
629 @return: Returns the action callback for automatic breakpoints.
630 Returns C{None} for interactive breakpoints.
631 """
632 return self.__action
633
635 """
636 Sets a new action callback for the breakpoint.
637
638 @type action: function
639 @param action: (Optional) Action callback function.
640 """
641 self.__action = action
642
644 """
645 Executes the breakpoint action callback, if any was set.
646
647 @type event: L{Event}
648 @param event: Debug event triggered by the breakpoint.
649 """
650 if self.__action is not None:
651 return bool( self.__action(event) )
652 return True
653
654
655
657 """
658 Raises an C{AssertionError} exception for an invalid state transition.
659
660 @see: L{stateNames}
661
662 @type state: int
663 @param state: Intended breakpoint state.
664
665 @raise Exception: Always.
666 """
667 statemsg = ""
668 oldState = self.stateNames[ self.get_state() ]
669 newState = self.stateNames[ state ]
670 msg = "Invalid state transition (%s -> %s)" \
671 " for breakpoint at address %s"
672 msg = msg % (oldState, newState, HexDump.address(self.get_address()))
673 raise AssertionError, msg
674
675 - def disable(self, aProcess, aThread):
676 """
677 Transition to L{DISABLED} state.
678 - When hit: OneShot S{->} Disabled
679 - Forced by user: Enabled, OneShot, Running S{->} Disabled
680 - Transition from running state may require special handling
681 by the breakpoint implementation class.
682
683 @type aProcess: L{Process}
684 @param aProcess: Process object.
685
686 @type aThread: L{Thread}
687 @param aThread: Thread object.
688 """
689
690
691 self.__state = self.DISABLED
692
693 - def enable(self, aProcess, aThread):
694 """
695 Transition to L{ENABLED} state.
696 - When hit: Running S{->} Enabled
697 - Forced by user: Disabled, Running S{->} Enabled
698 - Transition from running state may require special handling
699 by the breakpoint implementation class.
700
701 @type aProcess: L{Process}
702 @param aProcess: Process object.
703
704 @type aThread: L{Thread}
705 @param aThread: Thread object.
706 """
707
708
709 self.__state = self.ENABLED
710
712 """
713 Transition to L{ONESHOT} state.
714 - Forced by user: Disabled S{->} OneShot
715
716 @type aProcess: L{Process}
717 @param aProcess: Process object.
718
719 @type aThread: L{Thread}
720 @param aThread: Thread object.
721 """
722
723
724 self.__state = self.ONESHOT
725
726 - def running(self, aProcess, aThread):
727 """
728 Transition to L{RUNNING} state.
729 - When hit: Enabled S{->} Running
730
731 @type aProcess: L{Process}
732 @param aProcess: Process object.
733
734 @type aThread: L{Thread}
735 @param aThread: Thread object.
736 """
737 if self.__state != self.ENABLED:
738 self.__bad_transition(self.RUNNING)
739 self.__state = self.RUNNING
740
741 - def hit(self, event):
742 """
743 Notify a breakpoint that it's been hit.
744 This triggers the corresponding state transition.
745
746 @see: L{disable}, L{enable}, L{one_shot}, L{running}
747
748 @type event: L{Event}
749 @param event: Debug event to handle (depends on the breakpoint type).
750
751 @raise AssertionError: Disabled breakpoints can't be hit.
752 """
753 aProcess = event.get_process()
754 aThread = event.get_thread()
755 state = self.get_state()
756
757 if state == self.ENABLED:
758 self.running(aProcess, aThread)
759
760 elif state == self.RUNNING:
761 self.enable(aProcess, aThread)
762
763 elif state == self.ONESHOT:
764 self.disable(aProcess, aThread)
765
766 elif state == self.DISABLED:
767
768 msg = "Hit a disabled breakpoint at address %s"
769 msg = msg % HexDump.address( self.get_address() )
770 raise AssertionError, msg
771
780 """
781 Code execution breakpoints (using an int3 opcode).
782
783 @see: L{Debug.break_at}
784
785 @type bpInstruction: str
786 @cvar bpInstruction: Breakpoint instruction for the current processor.
787 """
788
789 typeName = 'code breakpoint'
790
791 if System.arch in ('i386', 'amd64'):
792 bpInstruction = '\xCC'
793
794 - def __init__(self, address, condition = True, action = None):
795 """
796 Code breakpoint object.
797
798 @see: L{Breakpoint.__init__}
799
800 @type address: int
801 @param address: Memory address for breakpoint.
802
803 @type condition: function
804 @param condition: (Optional) Condition callback function.
805
806 @type action: function
807 @param action: (Optional) Action callback function.
808 """
809 if System.arch not in ('i386', 'amd64'):
810 msg = "Code breakpoints not supported for %s" % System.arch
811 raise NotImplementedError, msg
812 Breakpoint.__init__(self, address, len(self.bpInstruction),
813 condition, action)
814 self.__previousValue = self.bpInstruction
815
837
839 """
840 Restores the original byte at the target address.
841
842 @type aProcess: L{Process}
843 @param aProcess: Process object.
844 """
845
846 address = self.get_address()
847 currentValue = aProcess.read(address, len(self.bpInstruction))
848 if currentValue == self.bpInstruction:
849 aProcess.write(self.get_address(), self.__previousValue)
850 else:
851 self.__previousValue = currentValue
852
853 - def disable(self, aProcess, aThread):
857
858 - def enable(self, aProcess, aThread):
862
867
868
869
870
871
872
873 - def running(self, aProcess, aThread):
877
878
879
880
881
882
883
884
885
886
887
888
889
890 -class PageBreakpoint (Breakpoint):
891 """
892 Page access breakpoint (using guard pages).
893
894 @see: L{Debug.watch_buffer}
895 """
896
897 typeName = 'page breakpoint'
898
899
900
901 - def __init__(self, address, pages = 1, condition = True, action = None):
902 """
903 Page breakpoint object.
904
905 @see: L{Breakpoint.__init__}
906
907 @type address: int
908 @param address: Memory address for breakpoint.
909
910 @type pages: int
911 @param address: Size of breakpoint in pages.
912
913 @type condition: function
914 @param condition: (Optional) Condition callback function.
915
916 @type action: function
917 @param action: (Optional) Action callback function.
918 """
919 Breakpoint.__init__(self, address, pages * System.pageSize, condition,
920 action)
921
922 floordiv_align = long(address) // long(System.pageSize)
923 truediv_align = float(address) / float(System.pageSize)
924 if floordiv_align != truediv_align:
925 msg = "Address of page breakpoint " \
926 "must be aligned to a page size boundary " \
927 "(value %s received)" % HexDump.address(address)
928 raise ValueError, msg
929
931 """
932 @rtype: int
933 @return: The size in pages of the breakpoint.
934 """
935
936 return self.get_size() // System.pageSize
937
938 - def __set_bp(self, aProcess):
939 """
940 Sets the target pages as guard pages.
941
942 @type aProcess: L{Process}
943 @param aProcess: Process object.
944 """
945 lpAddress = self.get_address()
946 dwSize = self.get_size()
947 flNewProtect = aProcess.mquery(lpAddress).Protect
948 flNewProtect = flNewProtect | win32.PAGE_GUARD
949 aProcess.mprotect(lpAddress, dwSize, flNewProtect)
950
951 - def __clear_bp(self, aProcess):
952 """
953 Restores the original permissions of the target pages.
954
955 @type aProcess: L{Process}
956 @param aProcess: Process object.
957 """
958 lpAddress = self.get_address()
959 flNewProtect = aProcess.mquery(lpAddress).Protect
960 flNewProtect = flNewProtect & (0xFFFFFFFF ^ win32.PAGE_GUARD)
961 aProcess.mprotect(lpAddress, self.get_size(), flNewProtect)
962
963 - def disable(self, aProcess, aThread):
964 if not self.is_disabled():
965 self.__clear_bp(aProcess)
966 super(PageBreakpoint, self).disable(aProcess, aThread)
967
968 - def enable(self, aProcess, aThread):
969 if System.arch not in ('i386', 'amd64'):
970 msg = "Only one-shot page breakpoints are supported for %s"
971 raise NotImplementedError, msg % System.arch
972 if not self.is_enabled() and not self.is_one_shot():
973 self.__set_bp(aProcess)
974 super(PageBreakpoint, self).enable(aProcess, aThread)
975
976 - def one_shot(self, aProcess, aThread):
977 if not self.is_enabled() and not self.is_one_shot():
978 self.__set_bp(aProcess)
979 super(PageBreakpoint, self).one_shot(aProcess, aThread)
980
981 - def running(self, aProcess, aThread):
982 aThread.set_tf()
983 super(PageBreakpoint, self).running(aProcess, aThread)
984
988 """
989 Hardware breakpoint (using debug registers).
990
991 @see: L{Debug.watch_variable}
992 @group Trigger flags:
993 BREAK_ON_EXECUTION, BREAK_ON_WRITE, BREAK_ON_ACCESS, BREAK_ON_IO_ACCESS
994 @group Watch size flags:
995 WATCH_BYTE, WATCH_WORD, WATCH_DWORD, WATCH_QWORD
996
997 @type BREAK_ON_EXECUTION: int
998 @cvar BREAK_ON_EXECUTION: Break on execution.
999
1000 @type BREAK_ON_WRITE: int
1001 @cvar BREAK_ON_WRITE: Break on write.
1002
1003 @type BREAK_ON_ACCESS: int
1004 @cvar BREAK_ON_ACCESS: Break on read or write.
1005
1006 @type BREAK_ON_IO_ACCESS: int
1007 @cvar BREAK_ON_IO_ACCESS: Break on I/O port access.
1008
1009 @type WATCH_BYTE: int
1010 @cvar WATCH_BYTE: Watch a byte.
1011
1012 @type WATCH_WORD: int
1013 @cvar WATCH_WORD: Watch a word.
1014
1015 @type WATCH_DWORD: int
1016 @cvar WATCH_DWORD: Watch a double word.
1017
1018 @type WATCH_QWORD: int
1019 @cvar WATCH_QWORD: Watch one quad word.
1020
1021 @type validTriggers: tuple
1022 @cvar validTriggers: Valid trigger flag values.
1023
1024 @type validWatchSizes: tuple
1025 @cvar validWatchSizes: Valid watch flag values.
1026 """
1027
1028 typeName = 'hardware breakpoint'
1029
1030 BREAK_ON_EXECUTION = DebugRegister.BREAK_ON_EXECUTION
1031 BREAK_ON_WRITE = DebugRegister.BREAK_ON_WRITE
1032 BREAK_ON_ACCESS = DebugRegister.BREAK_ON_ACCESS
1033 BREAK_ON_IO_ACCESS = DebugRegister.BREAK_ON_IO_ACCESS
1034
1035 WATCH_BYTE = DebugRegister.WATCH_BYTE
1036 WATCH_WORD = DebugRegister.WATCH_WORD
1037 WATCH_DWORD = DebugRegister.WATCH_DWORD
1038 WATCH_QWORD = DebugRegister.WATCH_QWORD
1039
1040 validTriggers = (
1041 BREAK_ON_EXECUTION,
1042 BREAK_ON_WRITE,
1043 BREAK_ON_ACCESS,
1044 BREAK_ON_IO_ACCESS,
1045 )
1046
1047 validWatchSizes = (
1048 WATCH_BYTE,
1049 WATCH_WORD,
1050 WATCH_DWORD,
1051 WATCH_QWORD,
1052 )
1053
1058 """
1059 Hardware breakpoint object.
1060
1061 @see: L{Breakpoint.__init__}
1062
1063 @type address: int
1064 @param address: Memory address for breakpoint.
1065
1066 @type triggerFlag: int
1067 @param triggerFlag: Trigger of breakpoint. Must be one of the following:
1068
1069 - L{BREAK_ON_EXECUTION}
1070
1071 Break on code execution.
1072
1073 - L{BREAK_ON_WRITE}
1074
1075 Break on memory read or write.
1076
1077 - L{BREAK_ON_ACCESS}
1078
1079 Break on memory write.
1080
1081 @type sizeFlag: int
1082 @param sizeFlag: Size of breakpoint. Must be one of the following:
1083
1084 - L{WATCH_BYTE}
1085
1086 One (1) byte in size.
1087
1088 - L{WATCH_WORD}
1089
1090 Two (2) bytes in size.
1091
1092 - L{WATCH_DWORD}
1093
1094 Four (4) bytes in size.
1095
1096 - L{WATCH_QWORD}
1097
1098 Eight (8) bytes in size.
1099
1100 @type condition: function
1101 @param condition: (Optional) Condition callback function.
1102
1103 @type action: function
1104 @param action: (Optional) Action callback function.
1105 """
1106 if System.arch not in ('i386', 'amd64'):
1107 msg = "Hardware breakpoints not supported for %s" % System.arch
1108 raise NotImplementedError, msg
1109 if sizeFlag == self.WATCH_BYTE:
1110 size = 1
1111 elif sizeFlag == self.WATCH_WORD:
1112 size = 2
1113 elif sizeFlag == self.WATCH_DWORD:
1114 size = 4
1115 elif sizeFlag == self.WATCH_QWORD:
1116 size = 8
1117 else:
1118 msg = "Invalid size flag for hardware breakpoint (%s)"
1119 msg = msg % repr(sizeFlag)
1120 raise ValueError, msg
1121
1122 if triggerFlag not in self.validTriggers:
1123 msg = "Invalid trigger flag for hardware breakpoint (%s)"
1124 msg = msg % repr(triggerFlag)
1125 raise ValueError, msg
1126
1127 Breakpoint.__init__(self, address, size, condition, action)
1128 self.__trigger = triggerFlag
1129 self.__watch = sizeFlag
1130 self.__slot = None
1131
1148
1150 """
1151 Sets this breakpoint in the debug registers.
1152
1153 @type aThread: L{Thread}
1154 @param aThread: Thread object.
1155 """
1156 if self.__slot is None:
1157 aThread.suspend()
1158 try:
1159 ctx = aThread.get_context(win32.CONTEXT_DEBUG_REGISTERS)
1160 self.__slot = DebugRegister.find_slot(ctx)
1161 if self.__slot is None:
1162 msg = "No available hardware breakpoint slots for thread ID %d"
1163 msg = msg % aThread.get_tid()
1164 raise RuntimeError, msg
1165 DebugRegister.set_bp(ctx, self.__slot, self.get_address(),
1166 self.__trigger, self.__watch)
1167 aThread.set_context(ctx)
1168 finally:
1169 aThread.resume()
1170
1172 """
1173 @rtype: int
1174 @return: The debug register number used by this breakpoint,
1175 or C{None} if the breakpoint is not active.
1176 """
1177 return self.__slot
1178
1180 """
1181 @see: L{validTriggers}
1182 @rtype: int
1183 @return: The breakpoint trigger flag.
1184 """
1185 return self.__trigger
1186
1188 """
1189 @see: L{validWatchSizes}
1190 @rtype: int
1191 @return: The breakpoint watch flag.
1192 """
1193 return self.__watch
1194
1195 - def disable(self, aProcess, aThread):
1199
1200 - def enable(self, aProcess, aThread):
1204
1205 - def one_shot(self, aProcess, aThread):
1209
1210 - def running(self, aProcess, aThread):
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248 -class Hook (object):
1249 """
1250 Used by L{Debug.hook_function}.
1251
1252 This class acts as an action callback for code breakpoints set at the
1253 beginning of a function. It automatically retrieves the parameters from
1254 the stack, sets a breakpoint at the return address and retrieves the
1255 return value from the function call.
1256
1257 @type useHardwareBreakpoints: bool
1258 @cvar useHardwareBreakpoints: C{True} to try to use hardware breakpoints,
1259 C{False} otherwise.
1260 """
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273 useHardwareBreakpoints = False
1274
1275 - def __init__(self, preCB = None, postCB = None, paramCount = 0):
1276 """
1277 @type preCB: function
1278 @param preCB: (Optional) Callback triggered on function entry.
1279
1280 The signature for the callback can be something like this::
1281
1282 def pre_LoadLibraryEx(event, *params):
1283 ra = params[0] # return address
1284 argv = params[1:] # function parameters
1285
1286 # (...)
1287
1288 But if you passed the right number of arguments, you can also
1289 use a signature like this::
1290
1291 def pre_LoadLibraryEx(event, ra, lpFilename, hFile, dwFlags):
1292 szFilename = event.get_process().peek_string(lpFilename)
1293
1294 # (...)
1295
1296 In the above example, the value for C{paramCount} would be C{3}.
1297
1298 Note that the second example assumes all parameters are DWORDs.
1299 This may not always be so, especially in 64 bits Windows.
1300
1301 @type postCB: function
1302 @param postCB: (Optional) Callback triggered on function exit.
1303
1304 The signature for the callback would be something like this::
1305
1306 def post_LoadLibraryEx(event, return_value):
1307
1308 # (...)
1309
1310 @type paramCount: int
1311 @param paramCount:
1312 (Optional) Number of parameters for the C{preCB} callback,
1313 not counting the return address. Parameters are read from
1314 the stack and assumed to be DWORDs.
1315 """
1316 self.__paramCount = paramCount
1317 self.__preCB = preCB
1318 self.__postCB = postCB
1319 self.__paramStack = dict()
1320
1321
1322
1323
1324
1325
1326
1327
1329 """
1330 Handles the breakpoint event on entry of the function.
1331
1332 @type event: L{ExceptionEvent}
1333 @param event: Breakpoint hit event.
1334
1335 @raise WindowsError: An error occured.
1336 """
1337 debug = event.debug
1338
1339
1340 dwProcessId = event.get_pid()
1341 dwThreadId = event.get_tid()
1342 aProcess = event.get_process()
1343 aThread = event.get_thread()
1344 ra = aProcess.read_pointer( aThread.get_sp() )
1345 params = aThread.read_stack_dwords(self.__paramCount,
1346 offset = win32.sizeof(win32.LPVOID))
1347
1348
1349 self.__push_params(dwThreadId, params)
1350
1351
1352 if self.__postCB is not None:
1353
1354
1355 useHardwareBreakpoints = self.useHardwareBreakpoints
1356 if useHardwareBreakpoints:
1357 try:
1358 debug.define_hardware_breakpoint(
1359 dwThreadId,
1360 ra,
1361 event.debug.BP_BREAK_ON_EXECUTION,
1362 event.debug.BP_WATCH_BYTE,
1363 True,
1364 self.__postCallAction_hwbp
1365 )
1366 debug.enable_one_shot_hardware_breakpoint(dwThreadId, ra)
1367 except Exception, e:
1368
1369
1370 useHardwareBreakpoints = False
1371
1372
1373 if not useHardwareBreakpoints:
1374 debug.break_at(dwProcessId, ra, self.__postCallAction_codebp)
1375
1376
1377 try:
1378 self.__callHandler(self.__preCB, event, ra, *params)
1379
1380
1381 finally:
1382 if self.__postCB is None:
1383 self.__pop_params(dwThreadId)
1384
1385 - def __postCallAction_hwbp(self, event):
1386 """
1387 Handles hardware breakpoint events on return from the function.
1388
1389 @type event: L{ExceptionEvent}
1390 @param event: Single step event.
1391 """
1392
1393
1394
1395 tid = event.get_tid()
1396 address = event.breakpoint.get_address()
1397 event.debug.erase_hardware_breakpoint(tid, address)
1398
1399
1400 try:
1401 self.__postCallAction(event)
1402
1403
1404 finally:
1405 self.__pop_params(tid)
1406
1407 - def __postCallAction_codebp(self, event):
1408 """
1409 Handles code breakpoint events on return from the function.
1410
1411 @type event: L{ExceptionEvent}
1412 @param event: Breakpoint hit event.
1413 """
1414
1415
1416
1417
1418
1419
1420
1421 tid = event.get_tid()
1422 if not self.__paramStack.has_key(tid):
1423 return True
1424
1425
1426 pid = event.get_pid()
1427 address = event.breakpoint.get_address()
1428 event.debug.dont_break_at(pid, address)
1429
1430
1431 try:
1432 self.__postCallAction(event)
1433
1434
1435 finally:
1436 self.__pop_params(tid)
1437
1438 - def __postCallAction(self, event):
1439 """
1440 Calls the "post" callback.
1441
1442 @type event: L{ExceptionEvent}
1443 @param event: Breakpoint hit event.
1444 """
1445 aThread = event.get_thread()
1446 ctx = aThread.get_context(win32.CONTEXT_INTEGER)
1447 if win32.CONTEXT.arch == 'i386':
1448 retval = ctx['Eax']
1449 elif win32.CONTEXT.arch == 'amd64':
1450 retval = ctx['Rax']
1451
1452
1453 else:
1454 retval = None
1455 self.__callHandler(self.__postCB, event, retval)
1456
1458 """
1459 Calls a "pre" or "post" handler, if set.
1460
1461 @type callback: function
1462 @param callback: Callback function to call.
1463
1464 @type event: L{ExceptionEvent}
1465 @param event: Breakpoint hit event.
1466
1467 @type params: tuple
1468 @param params: Parameters for the callback function.
1469 """
1470 event.hook = self
1471 if callback is not None:
1472 callback(event, *params)
1473
1475 """
1476 Remembers the arguments tuple for the last call to the hooked function
1477 from this thread.
1478
1479 @type tid: int
1480 @param tid: Thread global ID.
1481
1482 @type params: tuple( arg, arg, arg... )
1483 @param params: Tuple of arguments.
1484 """
1485 stack = self.__paramStack.get( tid, [] )
1486 stack.append(params)
1487 self.__paramStack[tid] = stack
1488
1490 """
1491 Forgets the arguments tuple for the last call to the hooked function
1492 from this thread.
1493
1494 @type tid: int
1495 @param tid: Thread global ID.
1496 """
1497 stack = self.__paramStack[tid]
1498 stack.pop()
1499 if not stack:
1500 del self.__paramStack[tid]
1501
1503 """
1504 Returns the parameters found in the stack when the hooked function
1505 was last called by this thread.
1506
1507 @type tid: int
1508 @param tid: Thread global ID.
1509
1510 @rtype: tuple( arg, arg, arg... )
1511 @return: Tuple of arguments.
1512 """
1513 try:
1514 params = self.get_params_stack(tid)[-1]
1515 except IndexError:
1516 msg = "Hooked function called from thread %d already returned"
1517 raise IndexError, msg % tid
1518 return params
1519
1521 """
1522 Returns the parameters found in the stack each time the hooked function
1523 was called by this thread and haven't returned yet.
1524
1525 @type tid: int
1526 @param tid: Thread global ID.
1527
1528 @rtype: list of tuple( arg, arg, arg... )
1529 @return: List of argument tuples.
1530 """
1531 try:
1532 stack = self.__paramStack[tid]
1533 except KeyError:
1534 msg = "Hooked function was not called from thread %d"
1535 raise KeyError, msg % tid
1536 return stack
1537
1538 - def hook(self, debug, pid, address):
1539 """
1540 Installs the function hook at a given process and address.
1541
1542 @see: L{unhook}
1543
1544 @warning: Do not call from an function hook callback.
1545
1546 @type debug: L{Debug}
1547 @param debug: Debug object.
1548
1549 @type pid: int
1550 @param pid: Process ID.
1551
1552 @type address: int
1553 @param address: Function address.
1554 """
1555 return debug.break_at(pid, address, self)
1556
1557 - def unhook(self, debug, pid, address):
1558 """
1559 Removes the function hook at a given process and address.
1560
1561 @see: L{hook}
1562
1563 @warning: Do not call from an function hook callback.
1564
1565 @type debug: L{Debug}
1566 @param debug: Debug object.
1567
1568 @type pid: int
1569 @param pid: Process ID.
1570
1571 @type address: int
1572 @param address: Function address.
1573 """
1574 return debug.dont_break_at(pid, address)
1575
1579 """
1580 Used by L{EventHandler}.
1581
1582 This class acts as an action callback for code breakpoints set at the
1583 beginning of a function. It automatically retrieves the parameters from
1584 the stack, sets a breakpoint at the return address and retrieves the
1585 return value from the function call.
1586
1587 @see: L{EventHandler.apiHooks}
1588 """
1589
1590 - def __init__(self, eventHandler, procName, paramCount = 0):
1591 """
1592 @type eventHandler: L{EventHandler}
1593 @param eventHandler: Event handler instance.
1594
1595 @type procName: str
1596 @param procName: Procedure name.
1597 The pre and post callbacks will be deduced from it.
1598
1599 For example, if the procedure is "LoadLibraryEx" the callback
1600 routines will be "pre_LoadLibraryEx" and "post_LoadLibraryEx".
1601
1602 The signature for the callbacks can be something like this::
1603
1604 def pre_LoadLibraryEx(event, *params):
1605 ra = params[0] # return address
1606 argv = params[1:] # function parameters
1607
1608 # (...)
1609
1610 def post_LoadLibraryEx(event, return_value):
1611
1612 # (...)
1613
1614 But if you passed the right number of arguments, you can also
1615 use a signature like this::
1616
1617 def pre_LoadLibraryEx(event, ra, lpFilename, hFile, dwFlags):
1618 szFilename = event.get_process().peek_string(lpFilename)
1619
1620 # (...)
1621
1622 Note that the second example assumes all parameters are DWORDs.
1623 This may not always be so, especially in 64 bits Windows.
1624
1625 @type paramCount: int
1626 @param paramCount: (Optional) Number of parameters for the callback.
1627 Parameters are read from the stack and assumed to be DWORDs.
1628 The first parameter of the pre callback is always the return address.
1629 """
1630 self.__procName = procName
1631
1632 preCB = getattr(eventHandler, 'pre_%s' % procName, None)
1633 postCB = getattr(eventHandler, 'post_%s' % procName, None)
1634 Hook.__init__(self, preCB, postCB, paramCount)
1635
1636 - def hook(self, debug, pid, modName):
1637 """
1638 Installs the API hook on a given process and module.
1639
1640 @warning: Do not call from an API hook callback.
1641
1642 @type debug: L{Debug}
1643 @param debug: Debug object.
1644
1645 @type pid: int
1646 @param pid: Process ID.
1647
1648 @type modName: str
1649 @param modName: Module name.
1650 """
1651 address = debug.resolve_exported_function(pid, modName, self.__procName)
1652 Hook.hook(self, debug, pid, address)
1653
1654 - def unhook(self, debug, pid, modName):
1655 """
1656 Removes the API hook from the given process and module.
1657
1658 @warning: Do not call from an API hook callback.
1659
1660 @type debug: L{Debug}
1661 @param debug: Debug object.
1662
1663 @type pid: int
1664 @param pid: Process ID.
1665
1666 @type modName: str
1667 @param modName: Module name.
1668 """
1669 address = debug.resolve_exported_function(pid, modName, self.__procName)
1670 Hook.unhook(self, debug, pid, address)
1671
1675 """
1676 Used by L{Debug.watch_buffer}.
1677
1678 This class acts as a condition callback for page breakpoints.
1679 It emulates page breakpoints that can overlap and/or take up less
1680 than a page's size.
1681 """
1682
1684 self.__ranges = dict()
1685
1686 - def add(self, address, size, action = None):
1687 """
1688 Adds a buffer to the watch object.
1689
1690 @type address: int
1691 @param address: Memory address of buffer to watch.
1692
1693 @type size: int
1694 @param size: Size in bytes of buffer to watch.
1695
1696 @type action: function
1697 @param action: (Optional) Action callback function.
1698
1699 See L{Debug.define_page_breakpoint} for more details.
1700 """
1701 key = (address, address + size)
1702 if key in self.__ranges:
1703 msg = "Buffer from %s to %s is already being watched"
1704 begin = HexDump.address(key[0])
1705 end = HexDump.address(key[1])
1706 raise RuntimeError, msg % (begin, end)
1707 self.__ranges[key] = action
1708
1709 - def remove(self, address, size):
1710 """
1711 Removes a buffer from the watch object.
1712
1713 @type address: int
1714 @param address: Memory address of buffer to stop watching.
1715
1716 @type size: int
1717 @param size: Size in bytes of buffer to stop watching.
1718 """
1719 key = (address, address + size)
1720 if key not in self.__ranges:
1721 msg = "No buffer watch set at %s-%s"
1722 begin = HexDump.address(key[0])
1723 end = HexDump.address(key[1])
1724 raise RuntimeError, msg % (begin, end)
1725 del self.__ranges[key]
1726
1727 - def exists(self, address, size):
1728 """
1729 @type address: int
1730 @param address: Memory address of buffer being watched.
1731
1732 @type size: int
1733 @param size: Size in bytes of buffer being watched.
1734
1735 @rtype: bool
1736 @return: C{True} if the buffer is being watched, C{False} otherwise.
1737 """
1738 key = (address, address + size)
1739 return key in self.__ranges
1740
1742 """
1743 @rtype: tuple( int, int )
1744 @return:
1745 Base address and size in pages required to watch all the buffers.
1746 """
1747 min_start = 0
1748 max_end = 0
1749 for ((start, end), action) in self.__ranges.iteritems():
1750 if start < min_start:
1751 min_start = start
1752 if end > max_end:
1753 max_end = end
1754 base = MemoryAddresses.align_address_to_page_start(min_start)
1755 size = max_end - min_start
1756 pages = MemoryAddresses.get_buffer_size_in_pages(min_start, size)
1757 return ( base, pages )
1758
1760 """
1761 @rtype: int
1762 @return: Number of buffers being watched.
1763 """
1764 return len(self.__ranges)
1765
1767 """
1768 Breakpoint condition callback.
1769
1770 This method will also call the action callbacks for each
1771 buffer being watched.
1772
1773 @type event: L{ExceptionEvent}
1774 @param event: Guard page exception event.
1775
1776 @rtype: bool
1777 @return: C{True} if the address being accessed belongs
1778 to at least one of the buffers that was being watched
1779 and had no action callback.
1780 """
1781 address = event.get_exception_information(1)
1782 bCondition = False
1783 for ((start, end), action) in self.__ranges.iteritems():
1784 bMatched = ( start <= address < end )
1785 if bMatched and action is not None:
1786 action(event)
1787 else:
1788 bCondition = bCondition or bMatched
1789 return bCondition
1790
1794 """
1795 Encapsulates the capability to contain Breakpoint objects.
1796
1797 @group Simple breakpoint use:
1798 break_at, watch_variable, watch_buffer, hook_function,
1799 dont_break_at, dont_watch_variable, dont_watch_buffer,
1800 dont_hook_function, unhook_function
1801
1802 @group Stalking:
1803 stalk_at, stalk_variable, stalk_buffer, stalk_function,
1804 dont_stalk_at, dont_stalk_variable, dont_stalk_buffer,
1805 dont_stalk_function
1806
1807 @group Tracing:
1808 is_tracing, get_traced_tids,
1809 start_tracing, stop_tracing,
1810 start_tracing_process, stop_tracing_process,
1811 start_tracing_all, stop_tracing_all
1812
1813 @group Symbols:
1814 resolve_label, resolve_exported_function
1815
1816 @group Advanced breakpoint use:
1817 define_code_breakpoint,
1818 define_page_breakpoint,
1819 define_hardware_breakpoint,
1820 has_code_breakpoint,
1821 has_page_breakpoint,
1822 has_hardware_breakpoint,
1823 get_code_breakpoint,
1824 get_page_breakpoint,
1825 get_hardware_breakpoint,
1826 erase_code_breakpoint,
1827 erase_page_breakpoint,
1828 erase_hardware_breakpoint,
1829 enable_code_breakpoint,
1830 enable_page_breakpoint,
1831 enable_hardware_breakpoint,
1832 enable_one_shot_code_breakpoint,
1833 enable_one_shot_page_breakpoint,
1834 enable_one_shot_hardware_breakpoint,
1835 disable_code_breakpoint,
1836 disable_page_breakpoint,
1837 disable_hardware_breakpoint
1838
1839 @group Listing breakpoints:
1840 get_all_breakpoints,
1841 get_all_code_breakpoints,
1842 get_all_page_breakpoints,
1843 get_all_hardware_breakpoints,
1844 get_process_breakpoints,
1845 get_process_code_breakpoints,
1846 get_process_page_breakpoints,
1847 get_process_hardware_breakpoints,
1848 get_thread_hardware_breakpoints
1849
1850 @group Batch operations on breakpoints:
1851 enable_all_breakpoints,
1852 enable_one_shot_all_breakpoints,
1853 disable_all_breakpoints,
1854 erase_all_breakpoints,
1855 enable_process_breakpoints,
1856 enable_one_shot_process_breakpoints,
1857 disable_process_breakpoints,
1858 erase_process_breakpoints
1859
1860 @group Event notifications (private):
1861 notify_guard_page,
1862 notify_breakpoint,
1863 notify_single_step,
1864 notify_exit_thread,
1865 notify_exit_process
1866
1867 @group Breakpoint types:
1868 BP_TYPE_ANY, BP_TYPE_CODE, BP_TYPE_PAGE, BP_TYPE_HARDWARE
1869 @group Breakpoint states:
1870 BP_STATE_DISABLED, BP_STATE_ENABLED, BP_STATE_ONESHOT, BP_STATE_RUNNING
1871 @group Memory breakpoint trigger flags:
1872 BP_BREAK_ON_EXECUTION, BP_BREAK_ON_WRITE, BP_BREAK_ON_ACCESS
1873 @group Memory breakpoint size flags:
1874 BP_WATCH_BYTE, BP_WATCH_WORD, BP_WATCH_DWORD, BP_WATCH_QWORD
1875
1876 @type BP_TYPE_ANY: int
1877 @cvar BP_TYPE_ANY: To get all breakpoints
1878 @type BP_TYPE_CODE: int
1879 @cvar BP_TYPE_CODE: To get code breakpoints only
1880 @type BP_TYPE_PAGE: int
1881 @cvar BP_TYPE_PAGE: To get page breakpoints only
1882 @type BP_TYPE_HARDWARE: int
1883 @cvar BP_TYPE_HARDWARE: To get hardware breakpoints only
1884
1885 @type BP_STATE_DISABLED: int
1886 @cvar BP_STATE_DISABLED: Breakpoint is disabled.
1887 @type BP_STATE_ENABLED: int
1888 @cvar BP_STATE_ENABLED: Breakpoint is enabled.
1889 @type BP_STATE_ONESHOT: int
1890 @cvar BP_STATE_ONESHOT: Breakpoint is enabled for one shot.
1891 @type BP_STATE_RUNNING: int
1892 @cvar BP_STATE_RUNNING: Breakpoint is running (recently hit).
1893
1894 @type BP_BREAK_ON_EXECUTION: int
1895 @cvar BP_BREAK_ON_EXECUTION: Break on code execution.
1896 @type BP_BREAK_ON_WRITE: int
1897 @cvar BP_BREAK_ON_WRITE: Break on memory write.
1898 @type BP_BREAK_ON_ACCESS: int
1899 @cvar BP_BREAK_ON_ACCESS: Break on memory read or write.
1900 """
1901
1902
1903 BP_TYPE_ANY = 0
1904 BP_TYPE_CODE = 1
1905 BP_TYPE_PAGE = 2
1906 BP_TYPE_HARDWARE = 3
1907
1908
1909 BP_STATE_DISABLED = Breakpoint.DISABLED
1910 BP_STATE_ENABLED = Breakpoint.ENABLED
1911 BP_STATE_ONESHOT = Breakpoint.ONESHOT
1912 BP_STATE_RUNNING = Breakpoint.RUNNING
1913
1914
1915 BP_BREAK_ON_EXECUTION = HardwareBreakpoint.BREAK_ON_EXECUTION
1916 BP_BREAK_ON_WRITE = HardwareBreakpoint.BREAK_ON_WRITE
1917 BP_BREAK_ON_IO_ACCESS = HardwareBreakpoint.BREAK_ON_IO_ACCESS
1918 BP_BREAK_ON_ACCESS = HardwareBreakpoint.BREAK_ON_ACCESS
1919
1920
1921 BP_WATCH_BYTE = HardwareBreakpoint.WATCH_BYTE
1922 BP_WATCH_WORD = HardwareBreakpoint.WATCH_WORD
1923 BP_WATCH_QWORD = HardwareBreakpoint.WATCH_QWORD
1924 BP_WATCH_DWORD = HardwareBreakpoint.WATCH_DWORD
1925
1927 self.__codeBP = dict()
1928 self.__pageBP = dict()
1929 self.__hardwareBP = dict()
1930 self.__runningBP = dict()
1931 self.__tracing = set()
1932
1933
1934
1936 return tid in self.__runningBP and self.__runningBP[tid]
1937
1939 return self.__runningBP[tid].pop()
1940
1942 if tid not in self.__runningBP:
1943 self.__runningBP[tid] = set()
1944 self.__runningBP[tid].add(bp)
1945
1947 self.__runningBP[tid].remove(bp)
1948 if not self.__runningBP[tid]:
1949 del self.__runningBP[tid]
1950
1956
1958 """
1959 Auxiliary method for L{notify_exit_thread} and L{notify_exit_process}.
1960 """
1961 tid = event.get_tid()
1962 if tid in list(self.__runningBP):
1963 del self.__runningBP[tid]
1964 if tid in list(self.__hardwareBP):
1965 del self.__hardwareBP[tid]
1966 if tid in self.__tracing:
1967 self.__tracing.remove(tid)
1968
1970 """
1971 Auxiliary method for L{notify_exit_process}.
1972 """
1973 pid = event.get_pid()
1974 process = event.get_process()
1975 for (bp_pid, bp_address) in self.__codeBP.items():
1976 if bp_pid == pid:
1977 del self.__codeBP[(bp_pid, bp_address)]
1978 for (bp_pid, bp_address) in self.__pageBP.items():
1979 if bp_pid == pid:
1980 del self.__pageBP[(bp_pid, bp_address)]
1981
1983 """
1984 Auxiliary method for L{notify_unload_dll}.
1985 """
1986 pid = event.get_pid()
1987 process = event.get_process()
1988 module = event.get_module()
1989 for tid in process.iter_thread_ids():
1990 thread = process.get_thread(tid)
1991 if tid in self.__runningBP:
1992 bplist = list(self.__runningBP[tid])
1993 for bp in bplist:
1994 bp_address = bp.get_address()
1995 if process.get_module_at_address(bp_address) == module:
1996 bp.disable(process, thread)
1997 self.__runningBP[tid].remove(bp)
1998 if tid in self.__hardwareBP:
1999 bplist = list(self.__hardwareBP[tid])
2000 for bp in bplist:
2001 bp_address = bp.get_address()
2002 if process.get_module_at_address(bp_address) == module:
2003 bp.disable(process, thread)
2004 self.__hardwareBP[tid].remove(bp)
2005 for (bp_pid, bp_address) in self.__codeBP.items():
2006 if bp_pid == pid:
2007 if process.get_module_at_address(bp_address) == module:
2008 del self.__codeBP[(bp_pid, bp_address)]
2009 for (bp_pid, bp_address) in self.__pageBP.items():
2010 if bp_pid == pid:
2011 if process.get_module_at_address(bp_address) == module:
2012 del self.__pageBP[(bp_pid, bp_address)]
2013
2014
2015
2018 """
2019 Creates a disabled code breakpoint at the given address.
2020
2021 @see:
2022 L{has_code_breakpoint},
2023 L{get_code_breakpoint},
2024 L{enable_code_breakpoint},
2025 L{enable_one_shot_code_breakpoint},
2026 L{disable_code_breakpoint},
2027 L{erase_code_breakpoint}
2028
2029 @type dwProcessId: int
2030 @param dwProcessId: Process global ID.
2031
2032 @type address: int
2033 @param address: Memory address of the code instruction to break at.
2034
2035 @type condition: function
2036 @param condition: (Optional) Condition callback function.
2037
2038 The callback signature is::
2039
2040 def condition_callback(event):
2041 return True # returns True or False
2042
2043 Where B{event} is an L{Event} object,
2044 and the return value is a boolean
2045 (C{True} to dispatch the event, C{False} otherwise).
2046
2047 @type action: function
2048 @param action: (Optional) Action callback function.
2049 If specified, the event is handled by this callback instead of
2050 being dispatched normally.
2051
2052 The callback signature is::
2053
2054 def action_callback(event):
2055 pass # no return value
2056
2057 Where B{event} is an L{Event} object,
2058 and the return value is a boolean
2059 (C{True} to dispatch the event, C{False} otherwise).
2060
2061 @rtype: L{CodeBreakpoint}
2062 @return: The code breakpoint object.
2063 """
2064 process = self.system.get_process(dwProcessId)
2065 bp = CodeBreakpoint(address, condition, action)
2066
2067 key = (dwProcessId, bp.get_address())
2068 if key in self.__codeBP:
2069 msg = "Already exists (PID %d) : %r"
2070 raise KeyError, msg % (dwProcessId, self.__codeBP[key])
2071 self.__codeBP[key] = bp
2072 return bp
2073
2074 - def define_page_breakpoint(self, dwProcessId, address, pages = 1,
2075 condition = True,
2076 action = None):
2077 """
2078 Creates a disabled page breakpoint at the given address.
2079
2080 @see:
2081 L{has_page_breakpoint},
2082 L{get_page_breakpoint},
2083 L{enable_page_breakpoint},
2084 L{enable_one_shot_page_breakpoint},
2085 L{disable_page_breakpoint},
2086 L{erase_page_breakpoint}
2087
2088 @type dwProcessId: int
2089 @param dwProcessId: Process global ID.
2090
2091 @type address: int
2092 @param address: Memory address of the first page to watch.
2093
2094 @type pages: int
2095 @param pages: Number of pages to watch.
2096
2097 @type condition: function
2098 @param condition: (Optional) Condition callback function.
2099
2100 The callback signature is::
2101
2102 def condition_callback(event):
2103 return True # returns True or False
2104
2105 Where B{event} is an L{Event} object,
2106 and the return value is a boolean
2107 (C{True} to dispatch the event, C{False} otherwise).
2108
2109 @type action: function
2110 @param action: (Optional) Action callback function.
2111 If specified, the event is handled by this callback instead of
2112 being dispatched normally.
2113
2114 The callback signature is::
2115
2116 def action_callback(event):
2117 pass # no return value
2118
2119 Where B{event} is an L{Event} object,
2120 and the return value is a boolean
2121 (C{True} to dispatch the event, C{False} otherwise).
2122
2123 @rtype: L{PageBreakpoint}
2124 @return: The page breakpoint object.
2125 """
2126 process = self.system.get_process(dwProcessId)
2127 bp = PageBreakpoint(address, pages, condition, action)
2128 begin = bp.get_address()
2129 end = begin + bp.get_size()
2130
2131 for address in xrange(begin, end, System.pageSize):
2132 key = (dwProcessId, address)
2133 if key in self.__pageBP:
2134 msg = "Already exists (PID %d) : %r"
2135 msg = msg % (dwProcessId, self.__pageBP[key])
2136 raise KeyError, msg
2137
2138 for address in xrange(begin, end, System.pageSize):
2139 key = (dwProcessId, address)
2140 self.__pageBP[key] = bp
2141 return bp
2142
2148 """
2149 Creates a disabled hardware breakpoint at the given address.
2150
2151 @see:
2152 L{has_hardware_breakpoint},
2153 L{get_hardware_breakpoint},
2154 L{enable_hardware_breakpoint},
2155 L{enable_one_shot_hardware_breakpoint},
2156 L{disable_hardware_breakpoint},
2157 L{erase_hardware_breakpoint}
2158
2159 @note:
2160 Hardware breakpoints do not seem to work properly on VirtualBox.
2161 See U{http://www.virtualbox.org/ticket/477}.
2162
2163 @type dwThreadId: int
2164 @param dwThreadId: Thread global ID.
2165
2166 @type address: int
2167 @param address: Memory address to watch.
2168
2169 @type triggerFlag: int
2170 @param triggerFlag: Trigger of breakpoint. Must be one of the following:
2171
2172 - L{BP_BREAK_ON_EXECUTION}
2173
2174 Break on code execution.
2175
2176 - L{BP_BREAK_ON_WRITE}
2177
2178 Break on memory read or write.
2179
2180 - L{BP_BREAK_ON_ACCESS}
2181
2182 Break on memory write.
2183
2184 @type sizeFlag: int
2185 @param sizeFlag: Size of breakpoint. Must be one of the following:
2186
2187 - L{BP_WATCH_BYTE}
2188
2189 One (1) byte in size.
2190
2191 - L{BP_WATCH_WORD}
2192
2193 Two (2) bytes in size.
2194
2195 - L{BP_WATCH_DWORD}
2196
2197 Four (4) bytes in size.
2198
2199 - L{BP_WATCH_QWORD}
2200
2201 Eight (8) bytes in size.
2202
2203 @type condition: function
2204 @param condition: (Optional) Condition callback function.
2205
2206 The callback signature is::
2207
2208 def condition_callback(event):
2209 return True # returns True or False
2210
2211 Where B{event} is an L{Event} object,
2212 and the return value is a boolean
2213 (C{True} to dispatch the event, C{False} otherwise).
2214
2215 @type action: function
2216 @param action: (Optional) Action callback function.
2217 If specified, the event is handled by this callback instead of
2218 being dispatched normally.
2219
2220 The callback signature is::
2221
2222 def action_callback(event):
2223 pass # no return value
2224
2225 Where B{event} is an L{Event} object,
2226 and the return value is a boolean
2227 (C{True} to dispatch the event, C{False} otherwise).
2228
2229 @rtype: L{HardwareBreakpoint}
2230 @return: The hardware breakpoint object.
2231 """
2232 thread = self.system.get_thread(dwThreadId)
2233 bp = HardwareBreakpoint(address, triggerFlag, sizeFlag, condition,
2234 action)
2235 begin = bp.get_address()
2236 end = begin + bp.get_size()
2237
2238 if dwThreadId in self.__hardwareBP:
2239 bpSet = self.__hardwareBP[dwThreadId]
2240 for oldbp in bpSet:
2241 old_begin = oldbp.get_address()
2242 old_end = old_begin + oldbp.get_size()
2243 if MemoryAddresses.do_ranges_intersect(begin, end, old_begin,
2244 old_end):
2245 msg = "Already exists (TID %d) : %r" % (dwThreadId, oldbp)
2246 raise KeyError, msg
2247 else:
2248 bpSet = set()
2249 self.__hardwareBP[dwThreadId] = bpSet
2250 bpSet.add(bp)
2251 return bp
2252
2253
2254
2256 """
2257 Checks if a code breakpoint is defined at the given address.
2258
2259 @see:
2260 L{define_code_breakpoint},
2261 L{get_code_breakpoint},
2262 L{erase_code_breakpoint},
2263 L{enable_code_breakpoint},
2264 L{enable_one_shot_code_breakpoint},
2265 L{disable_code_breakpoint}
2266
2267 @type dwProcessId: int
2268 @param dwProcessId: Process global ID.
2269
2270 @type address: int
2271 @param address: Memory address of breakpoint.
2272
2273 @rtype: bool
2274 @return: C{True} if the breakpoint is defined, C{False} otherwise.
2275 """
2276 return (dwProcessId, address) in self.__codeBP
2277
2278 - def has_page_breakpoint(self, dwProcessId, address):
2279 """
2280 Checks if a page breakpoint is defined at the given address.
2281
2282 @see:
2283 L{define_page_breakpoint},
2284 L{get_page_breakpoint},
2285 L{erase_page_breakpoint},
2286 L{enable_page_breakpoint},
2287 L{enable_one_shot_page_breakpoint},
2288 L{disable_page_breakpoint}
2289
2290 @type dwProcessId: int
2291 @param dwProcessId: Process global ID.
2292
2293 @type address: int
2294 @param address: Memory address of breakpoint.
2295
2296 @rtype: bool
2297 @return: C{True} if the breakpoint is defined, C{False} otherwise.
2298 """
2299 return (dwProcessId, address) in self.__pageBP
2300
2302 """
2303 Checks if a hardware breakpoint is defined at the given address.
2304
2305 @see:
2306 L{define_hardware_breakpoint},
2307 L{get_hardware_breakpoint},
2308 L{erase_hardware_breakpoint},
2309 L{enable_hardware_breakpoint},
2310 L{enable_one_shot_hardware_breakpoint},
2311 L{disable_hardware_breakpoint}
2312
2313 @type dwThreadId: int
2314 @param dwThreadId: Thread global ID.
2315
2316 @type address: int
2317 @param address: Memory address of breakpoint.
2318
2319 @rtype: bool
2320 @return: C{True} if the breakpoint is defined, C{False} otherwise.
2321 """
2322 if dwThreadId in self.__hardwareBP:
2323 bpSet = self.__hardwareBP[dwThreadId]
2324 for bp in bpSet:
2325 if bp.get_address() == address:
2326 return True
2327 return False
2328
2329
2330
2332 """
2333 Returns the internally used breakpoint object,
2334 for the code breakpoint defined at the given address.
2335
2336 @warning: It's usually best to call the L{Debug} methods
2337 instead of accessing the breakpoint objects directly.
2338
2339 @see:
2340 L{define_code_breakpoint},
2341 L{has_code_breakpoint},
2342 L{enable_code_breakpoint},
2343 L{enable_one_shot_code_breakpoint},
2344 L{disable_code_breakpoint},
2345 L{erase_code_breakpoint}
2346
2347 @type dwProcessId: int
2348 @param dwProcessId: Process global ID.
2349
2350 @type address: int
2351 @param address: Memory address where the breakpoint is defined.
2352
2353 @rtype: L{CodeBreakpoint}
2354 @return: The code breakpoint object.
2355 """
2356 key = (dwProcessId, address)
2357 if key not in self.__codeBP:
2358 msg = "No breakpoint at process %d, address %s"
2359 address = HexDump.address(address)
2360 raise KeyError, msg % (dwProcessId, address)
2361 return self.__codeBP[key]
2362
2363 - def get_page_breakpoint(self, dwProcessId, address):
2364 """
2365 Returns the internally used breakpoint object,
2366 for the page breakpoint defined at the given address.
2367
2368 @warning: It's usually best to call the L{Debug} methods
2369 instead of accessing the breakpoint objects directly.
2370
2371 @see:
2372 L{define_page_breakpoint},
2373 L{has_page_breakpoint},
2374 L{enable_page_breakpoint},
2375 L{enable_one_shot_page_breakpoint},
2376 L{disable_page_breakpoint},
2377 L{erase_page_breakpoint}
2378
2379 @type dwProcessId: int
2380 @param dwProcessId: Process global ID.
2381
2382 @type address: int
2383 @param address: Memory address where the breakpoint is defined.
2384
2385 @rtype: L{PageBreakpoint}
2386 @return: The page breakpoint object.
2387 """
2388 key = (dwProcessId, address)
2389 if key not in self.__pageBP:
2390 msg = "No breakpoint at process %d, address %s"
2391 address = HexDump.addresS(address)
2392 raise KeyError, msg % (dwProcessId, address)
2393 return self.__pageBP[key]
2394
2396 """
2397 Returns the internally used breakpoint object,
2398 for the code breakpoint defined at the given address.
2399
2400 @warning: It's usually best to call the L{Debug} methods
2401 instead of accessing the breakpoint objects directly.
2402
2403 @see:
2404 L{define_hardware_breakpoint},
2405 L{has_hardware_breakpoint},
2406 L{get_code_breakpoint},
2407 L{enable_hardware_breakpoint},
2408 L{enable_one_shot_hardware_breakpoint},
2409 L{disable_hardware_breakpoint},
2410 L{erase_hardware_breakpoint}
2411
2412 @type dwThreadId: int
2413 @param dwThreadId: Thread global ID.
2414
2415 @type address: int
2416 @param address: Memory address where the breakpoint is defined.
2417
2418 @rtype: L{HardwareBreakpoint}
2419 @return: The hardware breakpoint object.
2420 """
2421 if dwThreadId not in self.__hardwareBP:
2422 msg = "No hardware breakpoints set for thread %d"
2423 raise KeyError, msg % dwThreadId
2424 for bp in self.__hardwareBP[dwThreadId]:
2425 if bp.is_here(address):
2426 return bp
2427 msg = "No hardware breakpoint at thread %d, address %s"
2428 raise KeyError, msg % (dwThreadId, HexDump.address(address))
2429
2430
2431
2433 """
2434 Enables the code breakpoint at the given address.
2435
2436 @see:
2437 L{define_code_breakpoint},
2438 L{has_code_breakpoint},
2439 L{enable_one_shot_code_breakpoint},
2440 L{disable_code_breakpoint}
2441 L{erase_code_breakpoint},
2442
2443 @type dwProcessId: int
2444 @param dwProcessId: Process global ID.
2445
2446 @type address: int
2447 @param address: Memory address of breakpoint.
2448 """
2449 p = self.system.get_process(dwProcessId)
2450 bp = self.get_code_breakpoint(dwProcessId, address)
2451 if bp.is_running():
2452 self.__del_running_bp_from_all_threads(bp)
2453 bp.enable(p, None)
2454
2455 - def enable_page_breakpoint(self, dwProcessId, address):
2456 """
2457 Enables the page breakpoint at the given address.
2458
2459 @see:
2460 L{define_page_breakpoint},
2461 L{has_page_breakpoint},
2462 L{get_page_breakpoint},
2463 L{enable_one_shot_page_breakpoint},
2464 L{disable_page_breakpoint}
2465 L{erase_page_breakpoint},
2466
2467 @type dwProcessId: int
2468 @param dwProcessId: Process global ID.
2469
2470 @type address: int
2471 @param address: Memory address of breakpoint.
2472 """
2473 p = self.system.get_process(dwProcessId)
2474 bp = self.get_page_breakpoint(dwProcessId, address)
2475 if bp.is_running():
2476 self.__del_running_bp_from_all_threads(bp)
2477 bp.enable(p, None)
2478
2480 """
2481 Enables the hardware breakpoint at the given address.
2482
2483 @see:
2484 L{define_hardware_breakpoint},
2485 L{has_hardware_breakpoint},
2486 L{get_hardware_breakpoint},
2487 L{enable_one_shot_hardware_breakpoint},
2488 L{disable_hardware_breakpoint}
2489 L{erase_hardware_breakpoint},
2490
2491 @note: Do not set hardware breakpoints while processing the system
2492 breakpoint event.
2493
2494 @type dwThreadId: int
2495 @param dwThreadId: Thread global ID.
2496
2497 @type address: int
2498 @param address: Memory address of breakpoint.
2499 """
2500 t = self.system.get_thread(dwThreadId)
2501 bp = self.get_hardware_breakpoint(dwThreadId, address)
2502 if bp.is_running():
2503 self.__del_running_bp_from_all_threads(bp)
2504 bp.enable(None, t)
2505
2507 """
2508 Enables the code breakpoint at the given address for only one shot.
2509
2510 @see:
2511 L{define_code_breakpoint},
2512 L{has_code_breakpoint},
2513 L{get_code_breakpoint},
2514 L{enable_code_breakpoint},
2515 L{disable_code_breakpoint}
2516 L{erase_code_breakpoint},
2517
2518 @type dwProcessId: int
2519 @param dwProcessId: Process global ID.
2520
2521 @type address: int
2522 @param address: Memory address of breakpoint.
2523 """
2524 p = self.system.get_process(dwProcessId)
2525 bp = self.get_code_breakpoint(dwProcessId, address)
2526 if bp.is_running():
2527 self.__del_running_bp_from_all_threads(bp)
2528 bp.one_shot(p, None)
2529
2530 - def enable_one_shot_page_breakpoint(self, dwProcessId, address):
2531 """
2532 Enables the page breakpoint at the given address for only one shot.
2533
2534 @see:
2535 L{define_page_breakpoint},
2536 L{has_page_breakpoint},
2537 L{get_page_breakpoint},
2538 L{enable_page_breakpoint},
2539 L{disable_page_breakpoint}
2540 L{erase_page_breakpoint},
2541
2542 @type dwProcessId: int
2543 @param dwProcessId: Process global ID.
2544
2545 @type address: int
2546 @param address: Memory address of breakpoint.
2547 """
2548 p = self.system.get_process(dwProcessId)
2549 bp = self.get_page_breakpoint(dwProcessId, address)
2550 if bp.is_running():
2551 self.__del_running_bp_from_all_threads(bp)
2552 bp.one_shot(p, None)
2553
2555 """
2556 Enables the hardware breakpoint at the given address for only one shot.
2557
2558 @see:
2559 L{define_hardware_breakpoint},
2560 L{has_hardware_breakpoint},
2561 L{get_hardware_breakpoint},
2562 L{enable_hardware_breakpoint},
2563 L{disable_hardware_breakpoint}
2564 L{erase_hardware_breakpoint},
2565
2566 @type dwThreadId: int
2567 @param dwThreadId: Thread global ID.
2568
2569 @type address: int
2570 @param address: Memory address of breakpoint.
2571 """
2572 t = self.system.get_thread(dwThreadId)
2573 bp = self.get_hardware_breakpoint(dwThreadId, address)
2574 if bp.is_running():
2575 self.__del_running_bp_from_all_threads(bp)
2576 bp.one_shot(None, t)
2577
2579 """
2580 Disables the code breakpoint at the given address.
2581
2582 @see:
2583 L{define_code_breakpoint},
2584 L{has_code_breakpoint},
2585 L{get_code_breakpoint},
2586 L{enable_code_breakpoint}
2587 L{enable_one_shot_code_breakpoint},
2588 L{erase_code_breakpoint},
2589
2590 @type dwProcessId: int
2591 @param dwProcessId: Process global ID.
2592
2593 @type address: int
2594 @param address: Memory address of breakpoint.
2595 """
2596 p = self.system.get_process(dwProcessId)
2597 bp = self.get_code_breakpoint(dwProcessId, address)
2598 if bp.is_running():
2599 self.__del_running_bp_from_all_threads(bp)
2600 bp.disable(p, None)
2601
2602 - def disable_page_breakpoint(self, dwProcessId, address):
2603 """
2604 Disables the page breakpoint at the given address.
2605
2606 @see:
2607 L{define_page_breakpoint},
2608 L{has_page_breakpoint},
2609 L{get_page_breakpoint},
2610 L{enable_page_breakpoint}
2611 L{enable_one_shot_page_breakpoint},
2612 L{erase_page_breakpoint},
2613
2614 @type dwProcessId: int
2615 @param dwProcessId: Process global ID.
2616
2617 @type address: int
2618 @param address: Memory address of breakpoint.
2619 """
2620 p = self.system.get_process(dwProcessId)
2621 bp = self.get_page_breakpoint(dwProcessId, address)
2622 if bp.is_running():
2623 self.__del_running_bp_from_all_threads(bp)
2624 bp.disable(p, None)
2625
2627 """
2628 Disables the hardware breakpoint at the given address.
2629
2630 @see:
2631 L{define_hardware_breakpoint},
2632 L{has_hardware_breakpoint},
2633 L{get_hardware_breakpoint},
2634 L{enable_hardware_breakpoint}
2635 L{enable_one_shot_hardware_breakpoint},
2636 L{erase_hardware_breakpoint},
2637
2638 @type dwThreadId: int
2639 @param dwThreadId: Thread global ID.
2640
2641 @type address: int
2642 @param address: Memory address of breakpoint.
2643 """
2644 t = self.system.get_thread(dwThreadId)
2645 p = t.get_process()
2646 bp = self.get_hardware_breakpoint(dwThreadId, address)
2647 if bp.is_running():
2648 self.__del_running_bp(dwThreadId, bp)
2649 bp.disable(p, t)
2650
2651
2652
2654 """
2655 Erases the code breakpoint at the given address.
2656
2657 @see:
2658 L{define_code_breakpoint},
2659 L{has_code_breakpoint},
2660 L{get_code_breakpoint},
2661 L{enable_code_breakpoint},
2662 L{enable_one_shot_code_breakpoint},
2663 L{disable_code_breakpoint}
2664
2665 @type dwProcessId: int
2666 @param dwProcessId: Process global ID.
2667
2668 @type address: int
2669 @param address: Memory address of breakpoint.
2670 """
2671 bp = self.get_code_breakpoint(dwProcessId, address)
2672 if not bp.is_disabled():
2673 self.disable_code_breakpoint(dwProcessId, address)
2674 del self.__codeBP[ (dwProcessId, address) ]
2675
2676 - def erase_page_breakpoint(self, dwProcessId, address):
2677 """
2678 Erases the page breakpoint at the given address.
2679
2680 @see:
2681 L{define_page_breakpoint},
2682 L{has_page_breakpoint},
2683 L{get_page_breakpoint},
2684 L{enable_page_breakpoint},
2685 L{enable_one_shot_page_breakpoint},
2686 L{disable_page_breakpoint}
2687
2688 @type dwProcessId: int
2689 @param dwProcessId: Process global ID.
2690
2691 @type address: int
2692 @param address: Memory address of breakpoint.
2693 """
2694 bp = self.get_page_breakpoint(dwProcessId, address)
2695 begin = bp.get_address()
2696 end = begin + bp.get_size()
2697 if not bp.is_disabled():
2698 self.disable_page_breakpoint(dwProcessId, address)
2699 for address in xrange(begin, end, System.pageSize):
2700 del self.__pageBP[ (dwProcessId, address) ]
2701
2703 """
2704 Erases the hardware breakpoint at the given address.
2705
2706 @see:
2707 L{define_hardware_breakpoint},
2708 L{has_hardware_breakpoint},
2709 L{get_hardware_breakpoint},
2710 L{enable_hardware_breakpoint},
2711 L{enable_one_shot_hardware_breakpoint},
2712 L{disable_hardware_breakpoint}
2713
2714 @type dwThreadId: int
2715 @param dwThreadId: Thread global ID.
2716
2717 @type address: int
2718 @param address: Memory address of breakpoint.
2719 """
2720 bp = self.get_hardware_breakpoint(dwThreadId, address)
2721 if not bp.is_disabled():
2722 self.disable_hardware_breakpoint(dwThreadId, address)
2723 bpSet = self.__hardwareBP[dwThreadId]
2724 bpSet.remove(bp)
2725 if not bpSet:
2726 del self.__hardwareBP[dwThreadId]
2727
2728
2729
2731 """
2732 Returns all breakpoint objects as a list of tuples.
2733
2734 Each tuple contains:
2735 - Process global ID to which the breakpoint applies.
2736 - Thread global ID to which the breakpoint applies, or C{None}.
2737 - The L{Breakpoint} object itself.
2738
2739 @note: If you're only interested in a specific breakpoint type, or in
2740 breakpoints for a specific process or thread, it's probably faster
2741 to call one of the following methods:
2742 - L{get_all_code_breakpoints}
2743 - L{get_all_page_breakpoints}
2744 - L{get_all_hardware_breakpoints}
2745 - L{get_process_code_breakpoints}
2746 - L{get_process_page_breakpoints}
2747 - L{get_process_hardware_breakpoints}
2748 - L{get_thread_hardware_breakpoints}
2749
2750 @rtype: list of tuple( pid, tid, bp )
2751 @return: List of all breakpoints.
2752 """
2753 bplist = list()
2754
2755
2756 for (pid, bp) in self.get_all_code_breakpoints():
2757 bplist.append( (pid, None, bp) )
2758
2759
2760 for (pid, bp) in self.get_all_page_breakpoints():
2761 bplist.append( (pid, None, bp) )
2762
2763
2764 for (tid, bp) in self.get_all_hardware_breakpoints():
2765 pid = self.system.get_thread(tid).get_pid()
2766 bplist.append( (pid, tid, bp) )
2767
2768
2769 return bplist
2770
2772 """
2773 @rtype: list of tuple( int, L{CodeBreakpoint} )
2774 @return: All code breakpoints as a list of tuples (pid, bp).
2775 """
2776 return [ (pid, bp) for ((pid, address), bp) in self.__codeBP.iteritems() ]
2777
2779 """
2780 @rtype: list of tuple( int, L{PageBreakpoint} )
2781 @return: All page breakpoints as a list of tuples (pid, bp).
2782 """
2783
2784 result = set()
2785 for ((pid, address), bp) in self.__pageBP.itervalues():
2786 result.add( (pid, bp) )
2787 return list(result)
2788
2790 """
2791 @rtype: list of tuple( int, L{HardwareBreakpoint} )
2792 @return: All hardware breakpoints as a list of tuples (tid, bp).
2793 """
2794 result = list()
2795 for (tid, bplist) in self.__hardwareBP.iteritems():
2796 for bp in bplist:
2797 result.append( (tid, bp) )
2798 return result
2799
2801 """
2802 Returns all breakpoint objects for the given process as a list of tuples.
2803
2804 Each tuple contains:
2805 - Process global ID to which the breakpoint applies.
2806 - Thread global ID to which the breakpoint applies, or C{None}.
2807 - The L{Breakpoint} object itself.
2808
2809 @note: If you're only interested in a specific breakpoint type, or in
2810 breakpoints for a specific process or thread, it's probably faster
2811 to call one of the following methods:
2812 - L{get_all_code_breakpoints}
2813 - L{get_all_page_breakpoints}
2814 - L{get_all_hardware_breakpoints}
2815 - L{get_process_code_breakpoints}
2816 - L{get_process_page_breakpoints}
2817 - L{get_process_hardware_breakpoints}
2818 - L{get_thread_hardware_breakpoints}
2819
2820 @type dwProcessId: int
2821 @param dwProcessId: Process global ID.
2822
2823 @rtype: list of tuple( pid, tid, bp )
2824 @return: List of all breakpoints for the given process.
2825 """
2826 bplist = list()
2827
2828
2829 for bp in self.get_process_code_breakpoints(dwProcessId):
2830 bplist.append( (dwProcessId, None, bp) )
2831
2832
2833 for bp in self.get_process_page_breakpoints(dwProcessId):
2834 bplist.append( (dwProcessId, None, bp) )
2835
2836
2837 for (tid, bp) in self.get_process_hardware_breakpoints(dwProcessId):
2838 pid = self.system.get_thread(tid).get_pid()
2839 bplist.append( (dwProcessId, tid, bp) )
2840
2841
2842 return bplist
2843
2845 """
2846 @type dwProcessId: int
2847 @param dwProcessId: Process global ID.
2848
2849 @rtype: list of L{CodeBreakpoint}
2850 @return: All code breakpoints for the given process.
2851 """
2852 result = list()
2853 for ((pid, address), bp) in self.__codeBP.iteritems():
2854 if pid == dwProcessId:
2855 result.append(bp)
2856 return result
2857
2858 - def get_process_page_breakpoints(self, dwProcessId):
2859 """
2860 @type dwProcessId: int
2861 @param dwProcessId: Process global ID.
2862
2863 @rtype: list of L{PageBreakpoint}
2864 @return: All page breakpoints for the given process.
2865 """
2866 result = list()
2867 for ((pid, address), bp) in self.__pageBP.itervalues():
2868 if pid == dwProcessId:
2869 result.append(bp)
2870 return result
2871
2873 """
2874 @see: L{get_process_hardware_breakpoints}
2875
2876 @type dwThreadId: int
2877 @param dwThreadId: Thread global ID.
2878
2879 @rtype: list of L{HardwareBreakpoint}
2880 @return: All hardware breakpoints for the given thread.
2881 """
2882 result = list()
2883 for (tid, bplist) in self.__hardwareBP.iteritems():
2884 if tid == dwThreadId:
2885 for bp in bplist:
2886 result.append(bp)
2887 return result
2888
2890 """
2891 @see: L{get_thread_hardware_breakpoints}
2892
2893 @type dwProcessId: int
2894 @param dwProcessId: Process global ID.
2895
2896 @rtype: list of tuple( int, L{HardwareBreakpoint} )
2897 @return: All hardware breakpoints for each thread in the given process
2898 as a list of tuples (tid, bp).
2899 """
2900 result = list()
2901 aProcess = self.system.get_process(dwProcessId)
2902 for dwThreadId in aProcess.iter_thread_ids():
2903 if dwThreadId in self.__hardwareBP:
2904 bplist = self.__hardwareBP[dwThreadId]
2905 for bp in bplist:
2906 result.append( (dwThreadId, bp) )
2907 return result
2908
2909
2910
2935
2960
2982
2984 """
2985 Erases all breakpoints in all processes.
2986
2987 @see:
2988 erase_code_breakpoint,
2989 erase_page_breakpoint,
2990 erase_hardware_breakpoint
2991 """
2992
2993
2994
2995
2996
2997 self.disable_all_breakpoints()
2998 self.__codeBP = dict()
2999 self.__pageBP = dict()
3000 self.__hardwareBP = dict()
3001 self.__runningBP = dict()
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3046
3076
3103
3134
3135
3136
3137 - def notify_guard_page(self, event):
3138 """
3139 Notify breakpoints of a guard page exception event.
3140
3141 @type event: L{ExceptionEvent}
3142 @param event: Guard page exception event.
3143 """
3144 address = event.get_fault_address()
3145 pid = event.get_pid()
3146 bCallHandler = True
3147
3148
3149 address = address & 0xFFFFF000
3150
3151
3152 key = (pid, address)
3153 if key in self.__pageBP:
3154 bp = self.__pageBP[key]
3155
3156
3157 event.continueStatus = win32.DBG_EXCEPTION_HANDLED
3158
3159
3160 event.breakpoint = bp
3161
3162
3163
3164 if bp.is_enabled() or bp.is_one_shot():
3165
3166
3167 bp.hit(event)
3168
3169
3170 if bp.is_running():
3171 tid = event.get_tid()
3172 self.__add_running_bp(tid, bp)
3173
3174
3175 bCondition = bp.eval_condition(event)
3176
3177
3178
3179 if bCondition and bp.is_automatic():
3180 bp.run_action(event)
3181 bCallHandler = False
3182 else:
3183 bCallHandler = bCondition
3184
3185 return bCallHandler
3186
3242
3304
3306 """
3307 Notify the termination of a thread.
3308
3309 @type event: L{ExitThreadEvent}
3310 @param event: Exit thread event.
3311 """
3312 self.__cleanup_thread(event)
3313 return True
3314
3316 """
3317 Notify the termination of a process.
3318
3319 @type event: L{ExitProcessEvent}
3320 @param event: Exit process event.
3321 """
3322 self.__cleanup_process(event)
3323 self.__cleanup_thread(event)
3324 return True
3325
3327 """
3328 Notify the unloading of a DLL.
3329
3330 @type event: L{UnloadDLLEvent}
3331 @param event: Unload DLL event.
3332 """
3333 self.__cleanup_module(event)
3334 return True
3335
3336
3337
3339 """
3340 Used by L{break_at} and L{stalk_at}.
3341
3342 @type pid: int
3343 @param pid: Process global ID.
3344
3345 @type address: int
3346 @param address: Memory address of code instruction to break at.
3347
3348 @type action: function
3349 @param action: (Optional) Action callback function.
3350
3351 See L{define_code_breakpoint} for more details.
3352 """
3353 if self.has_code_breakpoint(pid, address):
3354 bp = self.get_code_breakpoint(pid, address)
3355 if bp.get_action() != action:
3356 bp.set_action(action)
3357 else:
3358 self.define_code_breakpoint(pid, address, True, action)
3359 bp = self.get_code_breakpoint(pid, address)
3360 return bp
3361
3363 """
3364 Used by L{dont_break_at} and L{dont_stalk_at}.
3365
3366 @type pid: int
3367 @param pid: Process global ID.
3368
3369 @type address: int
3370 @param address: Memory address of code breakpoint.
3371 """
3372 if self.has_code_breakpoint(pid, address):
3373 self.erase_code_breakpoint(pid, address)
3374
3375 - def stalk_at(self, pid, address, action = None):
3376 """
3377 Sets a one shot code breakpoint at the given process and address.
3378
3379 @see: L{break_at}, L{dont_stalk_at}
3380
3381 @type pid: int
3382 @param pid: Process global ID.
3383
3384 @type address: int
3385 @param address: Memory address of code instruction to break at.
3386
3387 @type action: function
3388 @param action: (Optional) Action callback function.
3389
3390 See L{define_code_breakpoint} for more details.
3391 """
3392 bp = self.__set_break(pid, address, action)
3393 if not bp.is_one_shot():
3394 self.enable_one_shot_code_breakpoint(pid, address)
3395
3396 - def break_at(self, pid, address, action = None):
3397 """
3398 Sets a code breakpoint at the given process and address.
3399
3400 @see: L{stalk_at}, L{dont_break_at}
3401
3402 @type pid: int
3403 @param pid: Process global ID.
3404
3405 @type address: int
3406 @param address: Memory address of code instruction to break at.
3407
3408 @type action: function
3409 @param action: (Optional) Action callback function.
3410
3411 See L{define_code_breakpoint} for more details.
3412 """
3413 bp = self.__set_break(pid, address, action)
3414 if not bp.is_enabled():
3415 self.enable_code_breakpoint(pid, address)
3416
3418 """
3419 Clears a code breakpoint set by L{break_at}.
3420
3421 @type pid: int
3422 @param pid: Process global ID.
3423
3424 @type address: int
3425 @param address: Memory address of code instruction to break at.
3426 """
3427 self.__clear_break(pid, address)
3428
3430 """
3431 Clears a code breakpoint set by L{stalk_at}.
3432
3433 @type pid: int
3434 @param pid: Process global ID.
3435
3436 @type address: int
3437 @param address: Memory address of code instruction to break at.
3438 """
3439 self.__clear_break(pid, address)
3440
3441
3442
3443 - def hook_function(self, pid, address, preCB = None, postCB = None,
3444 paramCount = 0):
3445 """
3446 Sets a function hook at the given address.
3447
3448 @type pid: int
3449 @param pid: Process global ID.
3450
3451 @type address: int
3452 @param address: Function address.
3453
3454 @type preCB: function
3455 @param preCB: (Optional) Callback triggered on function entry.
3456
3457 The signature for the callback can be something like this::
3458
3459 def pre_LoadLibraryEx(event, *params):
3460 ra = params[0] # return address
3461 argv = params[1:] # function parameters
3462
3463 # (...)
3464
3465 But if you passed the right number of arguments, you can also
3466 use a signature like this::
3467
3468 def pre_LoadLibraryEx(event, ra, lpFilename, hFile, dwFlags):
3469 szFilename = event.get_process().peek_string(lpFilename)
3470
3471 # (...)
3472
3473 In the above example, the value for C{paramCount} would be C{3}.
3474
3475 @type postCB: function
3476 @param postCB: (Optional) Callback triggered on function exit.
3477
3478 The signature for the callback would be something like this::
3479
3480 def post_LoadLibraryEx(event, return_value):
3481
3482 # (...)
3483
3484 @type paramCount: int
3485 @param paramCount:
3486 (Optional) Number of parameters for the C{preCB} callback,
3487 not counting the return address. Parameters are read from
3488 the stack and assumed to be DWORDs.
3489 """
3490
3491
3492 if System.arch != 'i386':
3493 raise NotImplementedError
3494
3495 hookObj = Hook(preCB, postCB, paramCount)
3496 self.break_at(pid, address, hookObj)
3497
3498 - def stalk_function(self, pid, address, preCB = None, postCB = None,
3499 paramCount = 0):
3500 """
3501 Sets a one-shot function hook at the given address.
3502
3503 @type pid: int
3504 @param pid: Process global ID.
3505
3506 @type address: int
3507 @param address: Function address.
3508
3509 @type preCB: function
3510 @param preCB: (Optional) Callback triggered on function entry.
3511
3512 The signature for the callback can be something like this::
3513
3514 def pre_LoadLibraryEx(event, *params):
3515 ra = params[0] # return address
3516 argv = params[1:] # function parameters
3517
3518 # (...)
3519
3520 But if you passed the right number of arguments, you can also
3521 use a signature like this::
3522
3523 def pre_LoadLibraryEx(event, ra, lpFilename, hFile, dwFlags):
3524 szFilename = event.get_process().peek_string(lpFilename)
3525
3526 # (...)
3527
3528 In the above example, the value for C{paramCount} would be C{3}.
3529
3530 @type postCB: function
3531 @param postCB: (Optional) Callback triggered on function exit.
3532
3533 The signature for the callback would be something like this::
3534
3535 def post_LoadLibraryEx(event, return_value):
3536
3537 # (...)
3538
3539 @type paramCount: int
3540 @param paramCount:
3541 (Optional) Number of parameters for the C{preCB} callback,
3542 not counting the return address. Parameters are read from
3543 the stack and assumed to be DWORDs.
3544 """
3545
3546
3547 if System.arch != 'i386':
3548 raise NotImplementedError
3549
3550 hookObj = Hook(preCB, postCB, paramCount)
3551 self.stalk_at(pid, address, hookObj)
3552
3554 """
3555 Removes a function hook set by L{hook_function}.
3556
3557 @type pid: int
3558 @param pid: Process global ID.
3559
3560 @type address: int
3561 @param address: Function address.
3562 """
3563 self.dont_break_at(pid, address)
3564
3565
3566 unhook_function = dont_hook_function
3567
3569 """
3570 Removes a function hook set by L{stalk_function}.
3571
3572 @type pid: int
3573 @param pid: Process global ID.
3574
3575 @type address: int
3576 @param address: Function address.
3577 """
3578 self.dont_stalk_at(pid, address)
3579
3580
3581
3583 """
3584 Used by L{watch_variable} and L{stalk_variable}.
3585
3586 @type tid: int
3587 @param tid: Thread global ID.
3588
3589 @type address: int
3590 @param address: Memory address of variable to watch.
3591
3592 @type size: int
3593 @param size: Size of variable to watch. The only supported sizes are:
3594 byte (1), word (2), dword (4) and qword (8).
3595
3596 @type action: function
3597 @param action: (Optional) Action callback function.
3598
3599 See L{define_hardware_breakpoint} for more details.
3600
3601 @rtype: L{HardwareBreakpoint}
3602 @return: Hardware breakpoint at the requested address.
3603 """
3604
3605
3606
3607
3608 if size == 1:
3609 sizeFlag = self.BP_WATCH_BYTE
3610 elif size == 2:
3611 sizeFlag = self.BP_WATCH_WORD
3612 elif size == 4:
3613 sizeFlag = self.BP_WATCH_DWORD
3614 elif size == 8:
3615 sizeFlag = self.BP_WATCH_QWORD
3616 else:
3617 raise ValueError, "Bad size for variable watch: %r" % size
3618 if self.has_hardware_breakpoint(tid, address):
3619 bp = self.get_hardware_breakpoint(tid, address)
3620 if bp.get_trigger() != self.BP_BREAK_ON_ACCESS or \
3621 bp.get_watch() != sizeFlag:
3622 self.erase_hardware_breakpoint(tid, address)
3623 self.define_hardware_breakpoint(tid, address,
3624 self.BP_BREAK_ON_ACCESS, sizeFlag, True, action)
3625 bp = self.get_hardware_breakpoint(tid, address)
3626 else:
3627 self.define_hardware_breakpoint(tid, address,
3628 self.BP_BREAK_ON_ACCESS, sizeFlag, True, action)
3629 bp = self.get_hardware_breakpoint(tid, address)
3630 return bp
3631
3633 """
3634 Used by L{dont_watch_variable} and L{dont_stalk_variable}.
3635
3636 @type tid: int
3637 @param tid: Thread global ID.
3638
3639 @type address: int
3640 @param address: Memory address of variable to stop watching.
3641 """
3642 if self.has_hardware_breakpoint(tid, address):
3643 self.erase_hardware_breakpoint(tid, address)
3644
3646 """
3647 Sets a hardware breakpoint at the given thread, address and size.
3648
3649 @see: L{dont_watch_variable}
3650
3651 @type tid: int
3652 @param tid: Thread global ID.
3653
3654 @type address: int
3655 @param address: Memory address of variable to watch.
3656
3657 @type size: int
3658 @param size: Size of variable to watch. The only supported sizes are:
3659 byte (1), word (2), dword (4) and qword (8).
3660
3661 @type action: function
3662 @param action: (Optional) Action callback function.
3663
3664 See L{define_hardware_breakpoint} for more details.
3665 """
3666 bp = self.__set_variable_watch(tid, address, size, action)
3667 if not bp.is_enabled():
3668 self.enable_hardware_breakpoint(tid, address)
3669
3671 """
3672 Sets a one-shot hardware breakpoint at the given thread,
3673 address and size.
3674
3675 @see: L{dont_watch_variable}
3676
3677 @type tid: int
3678 @param tid: Thread global ID.
3679
3680 @type address: int
3681 @param address: Memory address of variable to watch.
3682
3683 @type size: int
3684 @param size: Size of variable to watch. The only supported sizes are:
3685 byte (1), word (2), dword (4) and qword (8).
3686
3687 @type action: function
3688 @param action: (Optional) Action callback function.
3689
3690 See L{define_hardware_breakpoint} for more details.
3691 """
3692 bp = self.__set_variable_watch(tid, address, size, action)
3693 if not bp.is_one_shot():
3694 self.enable_one_shot_hardware_breakpoint(tid, address)
3695
3697 """
3698 Clears a hardware breakpoint set by L{watch_variable}.
3699
3700 @type tid: int
3701 @param tid: Thread global ID.
3702
3703 @type address: int
3704 @param address: Memory address of variable to stop watching.
3705 """
3706 self.__clear_variable_watch(tid, address)
3707
3709 """
3710 Clears a hardware breakpoint set by L{stalk_variable}.
3711
3712 @type tid: int
3713 @param tid: Thread global ID.
3714
3715 @type address: int
3716 @param address: Memory address of variable to stop watching.
3717 """
3718 self.__clear_variable_watch(tid, address)
3719
3720
3721
3723 """
3724 Used by L{watch_buffer} and L{stalk_buffer}.
3725
3726 @type pid: int
3727 @param pid: Process global ID.
3728
3729 @type address: int
3730 @param address: Memory address of buffer to watch.
3731
3732 @type size: int
3733 @param size: Size in bytes of buffer to watch.
3734
3735 @type action: function
3736 @param action: (Optional) Action callback function.
3737
3738 See L{define_page_breakpoint} for more details.
3739
3740 @type bOneShot: bool
3741 @param bOneShot:
3742 C{True} to set a one-shot breakpoint,
3743 C{False} to set a normal breakpoint.
3744 """
3745
3746
3747
3748
3749
3750 if size < 1:
3751 raise ValueError, "Bad size for buffer watch: %r" % size
3752
3753
3754 aProcess = self.system.get_process(pid)
3755
3756
3757 base = MemoryAddresses.align_address_to_page_start(address)
3758 limit = MemoryAddresses.align_address_to_page_end(address + size)
3759 pages = MemoryAddresses.get_buffer_size_in_pages(address, size)
3760
3761 try:
3762
3763
3764
3765
3766
3767 bset = set()
3768 nset = set()
3769 cset = set()
3770 for page_addr in xrange(base, limit, System.pageSize):
3771
3772
3773 if self.has_page_breakpoint(pid, page_addr):
3774 bp = self.get_page_breakpoint(pid, page_addr)
3775 if bp not in bset:
3776 condition = bp.get_condition()
3777 if not condition in cset:
3778 if not isinstance(condition, BufferWatch):
3779
3780
3781 msg = "Can't watch buffer at page %s"
3782 msg = msg % HexDump.address(page_addr)
3783 raise RuntimeError, msg
3784 cset.add(condition)
3785 bset.add(bp)
3786
3787
3788 else:
3789 condition = BufferWatch()
3790 bp = self.define_page_breakpoint(pid, page_addr, 1,
3791 condition = condition)
3792 bset.add(bp)
3793 nset.add(bp)
3794 cset.add(condition)
3795
3796
3797 if bOneShot:
3798 for bp in bset:
3799 if not bp.is_one_shot():
3800 bp.one_shot(aProcess, None)
3801 else:
3802 for bp in bset:
3803 if not bp.is_enabled():
3804 bp.enable(aProcess, None)
3805
3806
3807 except:
3808
3809
3810 for bp in nset:
3811 try:
3812 self.erase_page_breakpoint(pid, bp.get_address())
3813 except:
3814 pass
3815
3816
3817 raise
3818
3819
3820 for condition in cset:
3821 condition.add(address, size, action)
3822
3824 """
3825 Used by L{dont_watch_buffer} and L{dont_stalk_buffer}.
3826
3827 @type pid: int
3828 @param pid: Process global ID.
3829
3830 @type address: int
3831 @param address: Memory address of buffer to stop watching.
3832
3833 @type size: int
3834 @param size: Size in bytes of buffer to stop watching.
3835 """
3836
3837
3838 if size < 1:
3839 raise ValueError, "Bad size for buffer watch: %r" % size
3840
3841
3842 base = MemoryAddresses.align_address_to_page_start(address)
3843 limit = MemoryAddresses.align_address_to_page_end(address + size)
3844 pages = MemoryAddresses.get_buffer_size_in_pages(address, size)
3845
3846
3847
3848
3849 cset = set()
3850 for page_addr in xrange(base, limit, System.pageSize):
3851 if self.has_page_breakpoint(pid, page_addr):
3852 bp = self.get_page_breakpoint(pid, page_addr)
3853 condition = bp.get_condition()
3854 if condition not in cset:
3855 if not isinstance(condition, BufferWatch):
3856
3857
3858 continue
3859 cset.add(condition)
3860 if condition.exists(address, size):
3861 condition.remove(address, size)
3862 if condition.count() == 0:
3863 try:
3864 self.erase_page_breakpoint(pid, bp.get_address())
3865 except WindowsError:
3866 pass
3867
3868 - def watch_buffer(self, pid, address, size, action = None):
3869 """
3870 Sets a page breakpoint and notifies when the given buffer is accessed.
3871
3872 @see: L{dont_watch_variable}
3873
3874 @type pid: int
3875 @param pid: Process global ID.
3876
3877 @type address: int
3878 @param address: Memory address of buffer to watch.
3879
3880 @type size: int
3881 @param size: Size in bytes of buffer to watch.
3882
3883 @type action: function
3884 @param action: (Optional) Action callback function.
3885
3886 See L{define_page_breakpoint} for more details.
3887 """
3888 self.__set_buffer_watch(pid, address, size, action, False)
3889
3890 - def stalk_buffer(self, pid, address, size, action = None):
3891 """
3892 Sets a one-shot page breakpoint and notifies
3893 when the given buffer is accessed.
3894
3895 @see: L{dont_watch_variable}
3896
3897 @type pid: int
3898 @param pid: Process global ID.
3899
3900 @type address: int
3901 @param address: Memory address of buffer to watch.
3902
3903 @type size: int
3904 @param size: Size in bytes of buffer to watch.
3905
3906 @type action: function
3907 @param action: (Optional) Action callback function.
3908
3909 See L{define_page_breakpoint} for more details.
3910 """
3911 self.__set_buffer_watch(pid, address, size, action, True)
3912
3914 """
3915 Clears a page breakpoint set by L{watch_buffer}.
3916
3917 @type pid: int
3918 @param pid: Process global ID.
3919
3920 @type address: int
3921 @param address: Memory address of buffer to stop watching.
3922
3923 @type size: int
3924 @param size: Size in bytes of buffer to stop watching.
3925 """
3926 self.__clear_buffer_watch(pid, address, size)
3927
3929 """
3930 Clears a page breakpoint set by L{stalk_buffer}.
3931
3932 @type pid: int
3933 @param pid: Process global ID.
3934
3935 @type address: int
3936 @param address: Memory address of buffer to stop watching.
3937
3938 @type size: int
3939 @param size: Size in bytes of buffer to stop watching.
3940 """
3941 self.__clear_buffer_watch(pid, address, size)
3942
3943
3944
3945
3946
3947
3949 """
3950 @type thread: L{Thread}
3951 @param thread: Thread to start tracing.
3952 """
3953 tid = thread.get_tid()
3954 if not tid in self.__tracing:
3955 thread.set_tf()
3956 self.__tracing.add(tid)
3957
3959 """
3960 @type thread: L{Thread}
3961 @param thread: Thread to stop tracing.
3962 """
3963 tid = thread.get_tid()
3964 if tid in self.__tracing:
3965 self.__tracing.remove(tid)
3966 thread.clear_tf()
3967
3969 """
3970 @type tid: int
3971 @param tid: Thread global ID.
3972
3973 @rtype: bool
3974 @return: C{True} if the thread is being traced, C{False} otherwise.
3975 """
3976 return tid in self.__tracing
3977
3979 """
3980 Retrieves the list of global IDs of all threads being traced.
3981
3982 @rtype: list( int... )
3983 @return: List of thread global IDs.
3984 """
3985 tids = list(self.__tracing)
3986 tids.sort()
3987 return tids
3988
3990 """
3991 Start tracing mode in the given thread.
3992
3993 @type tid: int
3994 @param tid: Global ID of thread to start tracing.
3995 """
3996 if not self.is_tracing(tid):
3997 thread = self.system.get_thread(tid)
3998 self.__start_tracing(thread)
3999
4001 """
4002 Stop tracing mode in the given thread.
4003
4004 @type tid: int
4005 @param tid: Global ID of thread to stop tracing.
4006 """
4007 if self.is_tracing(tid):
4008 thread = self.system.get_thread(tid)
4009 self.__stop_tracing(thread)
4010
4012 """
4013 Start tracing mode for all threads in the given process.
4014
4015 @type pid: int
4016 @param pid: Global ID of process to start tracing.
4017 """
4018 for thread in self.system.get_process(pid).iter_threads():
4019 self.__start_tracing(thread)
4020
4022 """
4023 Stop tracing mode for all threads in the given process.
4024
4025 @type pid: int
4026 @param pid: Global ID of process to stop tracing.
4027 """
4028 for thread in self.system.get_process(pid).iter_threads():
4029 self.__stop_tracing(thread)
4030
4037
4044
4045
4046
4048 """
4049 Resolves the exported DLL function for the given process.
4050
4051 @type pid: int
4052 @param pid: Process global ID.
4053
4054 @type modName: str
4055 @param modName: Name of the module that exports the function.
4056
4057 @type procName: str
4058 @param procName: Name of the exported function to resolve.
4059
4060 @rtype: int, None
4061 @return: On success, the address of the exported function.
4062 On failure, returns C{None}.
4063 """
4064 aProcess = self.system.get_process(pid)
4065 aModule = aProcess.get_module_by_name(modName)
4066 if not aModule:
4067 aProcess.scan_modules()
4068 aModule = aProcess.get_module_by_name(modName)
4069 if aModule:
4070 address = aModule.resolve(procName)
4071 return address
4072 return None
4073
4075 """
4076 Resolves a label for the given process.
4077
4078 @type pid: int
4079 @param pid: Process global ID.
4080
4081 @type label: str
4082 @param label: Label to resolve.
4083
4084 @rtype: int
4085 @return: Memory address pointed to by the label.
4086
4087 @raise ValueError: The label is malformed or impossible to resolve.
4088 @raise RuntimeError: Cannot resolve the module or function.
4089 """
4090 return self.get_process(pid).resolve_label(label)
4091