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 Event handling module.
30
31 @see: U{http://apps.sourceforge.net/trac/winappdbg/wiki/Debugging}
32
33 @group Event objects:
34 Event,
35 NoEvent,
36 CreateProcessEvent,
37 CreateThreadEvent,
38 ExitProcessEvent,
39 ExitThreadEvent,
40 LoadDLLEvent,
41 UnloadDLLEvent,
42 OutputDebugStringEvent,
43 RIPEvent,
44 ExceptionEvent
45 """
46
47 __revision__ = "$Id: event.py 415 2009-09-29 15:38:12Z QvasiModo $"
48
49 __all__ = [
50
51
52 'EventFactory',
53
54
55 'EventHandler',
56
57
58
59 'NoEvent',
60 ]
61
62 import win32
63 from win32 import FileHandle, ProcessHandle, ThreadHandle
64 from breakpoint import ApiHook
65 from system import Module, Thread, Process, PathOperations
66 from textio import HexDump
67
68 import ctypes
69
70
71
72 -class Event (object):
73 """
74 Event object.
75
76 @type eventMethod: str
77 @cvar eventMethod:
78 Method name to call when using L{EventHandler} subclasses.
79
80 @type eventName: str
81 @cvar eventName:
82 User-friendly name of the event.
83
84 @type eventDescription: str
85 @cvar eventDescription:
86 User-friendly description of the event.
87
88 @type debug: L{Debug}
89 @ivar debug:
90 Debug object that received the event.
91
92 @type raw: L{DEBUG_EVENT}
93 @ivar raw:
94 Raw DEBUG_EVENT structure as used by the Win32 API.
95
96 @type continueStatus: int
97 @ivar continueStatus:
98 Continue status to pass to L{win32.ContinueDebugEvent}.
99 """
100
101 eventMethod = 'unknown_event'
102 eventName = 'Unknown event'
103 eventDescription = 'A debug event of an unknown type has occured.'
104
106 """
107 @type debug: L{Debug}
108 @param debug: Debug object that received the event.
109
110 @type raw: L{DEBUG_EVENT}
111 @param raw: Raw DEBUG_EVENT structure as used by the Win32 API.
112 """
113 self.debug = debug
114 self.raw = raw
115 self.continueStatus = win32.DBG_EXCEPTION_NOT_HANDLED
116
118 """
119 @rtype: str
120 @return: User-friendly name of the event.
121 """
122 return self.eventName
123
125 """
126 @rtype: str
127 @return: User-friendly description of the event.
128 """
129 return self.eventDescription
130
132 """
133 @rtype: int
134 @return: Debug event code as defined in the Win32 API.
135 """
136 return self.raw.dwDebugEventCode
137
138
139
141 """
142 Alias of L{get_event_code} for backwards compatibility
143 with WinAppDbg version 1.0.
144 Will be phased out in the next version.
145
146 @rtype: int
147 @return: Debug event code as defined in the Win32 API.
148 """
149 return self.get_event_code()
150
152 """
153 @see: L{get_process}
154
155 @rtype: int
156 @return: Process global ID where the event occured.
157 """
158 return self.raw.dwProcessId
159
161 """
162 @see: L{get_thread}
163
164 @rtype: int
165 @return: Thread global ID where the event occured.
166 """
167 return self.raw.dwThreadId
168
190
192 """
193 @see: L{get_tid}
194
195 @rtype: L{Thread}
196 @return: Thread where the event occured.
197 """
198
199
200 tid = self.get_tid()
201 process = self.get_process()
202 if process.has_thread(tid):
203 thread = process.get_thread(tid)
204 else:
205
206 thread = Thread(tid)
207 process._ThreadContainer__add_thread(thread)
208 return thread
209
213 """
214 No event.
215
216 Dummy L{Event} object that can be used as a placeholder when no debug
217 event has occured yet. It's never returned by the L{EventFactory}.
218 """
219
220 eventMethod = 'no_event'
221 eventName = 'No event'
222 eventDescription = 'No debug event has occured.'
223
226
228 """
229 Always returns C{0}, so when evaluating the object as a boolean it's
230 always C{False}. This prevents L{Debug.cont} from trying to continue
231 a dummy event.
232 """
233 return 0
234
237
240
243
246
249
253 """
254 Exception event.
255
256 @type exceptionName: dict( int S{->} str )
257 @cvar exceptionName:
258 Mapping of exception constants to their names.
259
260 @type exceptionDescription: dict( int S{->} str )
261 @cvar exceptionDescription:
262 Mapping of exception constants to user-friendly strings.
263
264 @type breakpoint: L{Breakpoint}
265 @ivar breakpoint:
266 If the exception was caused by one of our breakpoints, this member
267 contains a reference to the breakpoint object. Otherwise it's not
268 defined. It should only be used from the condition or action callback
269 routines, instead of the event handler.
270
271 @type hook: L{Hook}
272 @ivar hook:
273 If the exception was caused by a function hook, this member contains a
274 reference to the hook object. Otherwise it's not defined. It should
275 only be used from the hook callback routines, instead of the event
276 handler.
277 """
278
279 eventName = 'Exception event'
280 eventDescription = 'An exception was raised by the debugee.'
281
282 __exceptionMethod = {
283 win32.EXCEPTION_ACCESS_VIOLATION : 'access_violation',
284 win32.EXCEPTION_ARRAY_BOUNDS_EXCEEDED : 'array_bounds_exceeded',
285 win32.EXCEPTION_BREAKPOINT : 'breakpoint',
286 win32.EXCEPTION_DATATYPE_MISALIGNMENT : 'datatype_misalignment',
287 win32.EXCEPTION_FLT_DENORMAL_OPERAND : 'float_denormal_operand',
288 win32.EXCEPTION_FLT_DIVIDE_BY_ZERO : 'float_divide_by_zero',
289 win32.EXCEPTION_FLT_INEXACT_RESULT : 'float_inexact_result',
290 win32.EXCEPTION_FLT_INVALID_OPERATION : 'float_invalid_operation',
291 win32.EXCEPTION_FLT_OVERFLOW : 'float_overflow',
292 win32.EXCEPTION_FLT_STACK_CHECK : 'float_stack_check',
293 win32.EXCEPTION_FLT_UNDERFLOW : 'float_underflow',
294 win32.EXCEPTION_ILLEGAL_INSTRUCTION : 'illegal_instruction',
295 win32.EXCEPTION_IN_PAGE_ERROR : 'in_page_error',
296 win32.EXCEPTION_INT_DIVIDE_BY_ZERO : 'integer_divide_by_zero',
297 win32.EXCEPTION_INT_OVERFLOW : 'integer_overflow',
298 win32.EXCEPTION_INVALID_DISPOSITION : 'invalid_disposition',
299 win32.EXCEPTION_NONCONTINUABLE_EXCEPTION : 'noncontinuable_exception',
300 win32.EXCEPTION_PRIV_INSTRUCTION : 'privileged_instruction',
301 win32.EXCEPTION_SINGLE_STEP : 'single_step',
302 win32.EXCEPTION_STACK_OVERFLOW : 'stack_overflow',
303 win32.EXCEPTION_GUARD_PAGE : 'guard_page',
304 win32.EXCEPTION_INVALID_HANDLE : 'invalid_handle',
305 win32.EXCEPTION_POSSIBLE_DEADLOCK : 'possible_deadlock',
306 win32.EXCEPTION_WX86_BREAKPOINT : 'wow64_breakpoint',
307 win32.CONTROL_C_EXIT : 'control_c_exit',
308 win32.DBG_CONTROL_C : 'debug_control_c',
309 win32.MS_VC_EXCEPTION : 'ms_vc_exception',
310 }
311
312 __exceptionName = {
313 win32.EXCEPTION_ACCESS_VIOLATION : 'EXCEPTION_ACCESS_VIOLATION',
314 win32.EXCEPTION_ARRAY_BOUNDS_EXCEEDED : 'EXCEPTION_ARRAY_BOUNDS_EXCEEDED',
315 win32.EXCEPTION_BREAKPOINT : 'EXCEPTION_BREAKPOINT',
316 win32.EXCEPTION_DATATYPE_MISALIGNMENT : 'EXCEPTION_DATATYPE_MISALIGNMENT',
317 win32.EXCEPTION_FLT_DENORMAL_OPERAND : 'EXCEPTION_FLT_DENORMAL_OPERAND',
318 win32.EXCEPTION_FLT_DIVIDE_BY_ZERO : 'EXCEPTION_FLT_DIVIDE_BY_ZERO',
319 win32.EXCEPTION_FLT_INEXACT_RESULT : 'EXCEPTION_FLT_INEXACT_RESULT',
320 win32.EXCEPTION_FLT_INVALID_OPERATION : 'EXCEPTION_FLT_INVALID_OPERATION',
321 win32.EXCEPTION_FLT_OVERFLOW : 'EXCEPTION_FLT_OVERFLOW',
322 win32.EXCEPTION_FLT_STACK_CHECK : 'EXCEPTION_FLT_STACK_CHECK',
323 win32.EXCEPTION_FLT_UNDERFLOW : 'EXCEPTION_FLT_UNDERFLOW',
324 win32.EXCEPTION_ILLEGAL_INSTRUCTION : 'EXCEPTION_ILLEGAL_INSTRUCTION',
325 win32.EXCEPTION_IN_PAGE_ERROR : 'EXCEPTION_IN_PAGE_ERROR',
326 win32.EXCEPTION_INT_DIVIDE_BY_ZERO : 'EXCEPTION_INT_DIVIDE_BY_ZERO',
327 win32.EXCEPTION_INT_OVERFLOW : 'EXCEPTION_INT_OVERFLOW',
328 win32.EXCEPTION_INVALID_DISPOSITION : 'EXCEPTION_INVALID_DISPOSITION',
329 win32.EXCEPTION_NONCONTINUABLE_EXCEPTION : 'EXCEPTION_NONCONTINUABLE_EXCEPTION',
330 win32.EXCEPTION_PRIV_INSTRUCTION : 'EXCEPTION_PRIV_INSTRUCTION',
331 win32.EXCEPTION_SINGLE_STEP : 'EXCEPTION_SINGLE_STEP',
332 win32.EXCEPTION_STACK_OVERFLOW : 'EXCEPTION_STACK_OVERFLOW',
333 win32.EXCEPTION_GUARD_PAGE : 'EXCEPTION_GUARD_PAGE',
334 win32.EXCEPTION_INVALID_HANDLE : 'EXCEPTION_INVALID_HANDLE',
335 win32.EXCEPTION_POSSIBLE_DEADLOCK : 'EXCEPTION_POSSIBLE_DEADLOCK',
336 win32.EXCEPTION_WX86_BREAKPOINT : 'EXCEPTION_WX86_BREAKPOINT',
337 win32.CONTROL_C_EXIT : 'CONTROL_C_EXIT',
338 win32.DBG_CONTROL_C : 'DBG_CONTROL_C',
339 win32.MS_VC_EXCEPTION : 'MS_VC_EXCEPTION',
340 }
341
342 __exceptionDescription = {
343 win32.EXCEPTION_ACCESS_VIOLATION : 'Access violation',
344 win32.EXCEPTION_ARRAY_BOUNDS_EXCEEDED : 'Array bounds exceeded',
345 win32.EXCEPTION_BREAKPOINT : 'Breakpoint',
346 win32.EXCEPTION_DATATYPE_MISALIGNMENT : 'Datatype misalignment',
347 win32.EXCEPTION_FLT_DENORMAL_OPERAND : 'Float denormal operand',
348 win32.EXCEPTION_FLT_DIVIDE_BY_ZERO : 'Float divide by zero',
349 win32.EXCEPTION_FLT_INEXACT_RESULT : 'Float inexact result',
350 win32.EXCEPTION_FLT_INVALID_OPERATION : 'Float invalid operation',
351 win32.EXCEPTION_FLT_OVERFLOW : 'Float overflow',
352 win32.EXCEPTION_FLT_STACK_CHECK : 'Float stack check',
353 win32.EXCEPTION_FLT_UNDERFLOW : 'Float underflow',
354 win32.EXCEPTION_ILLEGAL_INSTRUCTION : 'Illegal instruction',
355 win32.EXCEPTION_IN_PAGE_ERROR : 'In-page error',
356 win32.EXCEPTION_INT_DIVIDE_BY_ZERO : 'Integer divide by zero',
357 win32.EXCEPTION_INT_OVERFLOW : 'Integer overflow',
358 win32.EXCEPTION_INVALID_DISPOSITION : 'Invalid disposition',
359 win32.EXCEPTION_NONCONTINUABLE_EXCEPTION : 'Noncontinuable exception',
360 win32.EXCEPTION_PRIV_INSTRUCTION : 'Privileged instruction',
361 win32.EXCEPTION_SINGLE_STEP : 'Single step event',
362 win32.EXCEPTION_STACK_OVERFLOW : 'Stack limits overflow',
363 win32.EXCEPTION_GUARD_PAGE : 'Guard page hit',
364 win32.EXCEPTION_INVALID_HANDLE : 'Invalid handle',
365 win32.EXCEPTION_POSSIBLE_DEADLOCK : 'Possible deadlock',
366 win32.EXCEPTION_WX86_BREAKPOINT : 'WOW64 breakpoint',
367 win32.CONTROL_C_EXIT : 'Control-C exit',
368 win32.DBG_CONTROL_C : 'Debug Control-C',
369 win32.MS_VC_EXCEPTION : 'Microsoft Visual C exception',
370 }
371
372 @property
376
385
394
401
403 """
404 @rtype: bool
405 @return: The opposite of L{is_first_chance}.
406 """
407 return not self.is_first_chance()
408
410 """
411 @see: U{http://msdn.microsoft.com/en-us/library/aa363082(VS.85).aspx}
412
413 @rtype: bool
414 @return: True if the exception is noncontinuable.
415
416 Attempting to continue a noncontinuable exception results in an
417 EXCEPTION_NONCONTINUABLE_EXCEPTION exception to be raised.
418 """
419 return bool( self.raw.u.Exception.ExceptionRecord.ExceptionFlags & \
420 win32.EXCEPTION_NONCONTINUABLE )
421
423 """
424 @rtype: bool
425 @return: The opposite of L{is_noncontinuable}.
426 """
427 return not self.is_noncontinuable()
428
435
442
455
464
466 """
467 @rtype: int
468 @return: Access violation type.
469 Should be one of the following constants:
470
471 - L{win32.EXCEPTION_READ_FAULT}
472 - L{win32.EXCEPTION_WRITE_FAULT}
473 - L{win32.EXCEPTION_EXECUTE_FAULT}
474
475 @note: This method is only meaningful for access violation exceptions,
476 in-page memory error exceptions and guard page exceptions.
477
478 @raise NotImplementedError: Wrong kind of exception.
479 """
480 if self.get_exception_code() not in (win32.EXCEPTION_ACCESS_VIOLATION,
481 win32.EXCEPTION_IN_PAGE_ERROR, win32.EXCEPTION_GUARD_PAGE):
482 msg = "This method is not meaningful for %s."
483 raise NotImplementedError, msg % self.get_exception_name()
484 return self.get_exception_information(0)
485
501
503 """
504 @rtype: int
505 @return: NTSTATUS status code that caused the exception.
506
507 @note: This method is only meaningful for in-page memory error
508 exceptions.
509
510 @raise NotImplementedError: Not an in-page memory error.
511 """
512 if self.get_exception_code() != win32.EXCEPTION_IN_PAGE_ERROR:
513 msg = "This method is only meaningful "\
514 "for in-page memory error exceptions."
515 raise NotImplementedError, msg
516 return self.get_exception_information(2)
517
519 """
520 Traverses the exception record linked list and builds a Python list.
521
522 Nested exception records are received for nested exceptions. This
523 happens when an exception is raised in the debugee while trying to
524 handle a previous exception.
525
526 @rtype: list( L{win32.EXCEPTION_RECORD} )
527 @return:
528 List of raw exception record structures as used by the Win32 API.
529
530 There is always at least one exception record, so the list is
531 never empty. All other methods of this class read from the first
532 exception record only, that is, the most recent exception.
533 """
534
535
536 record = self.raw.u.Exception.ExceptionRecord
537 nested = [ record ]
538
539
540 while record.ExceptionRecord:
541 record = record.ExceptionRecord.contents
542 nested.append(record)
543
544
545 return nested
546
560 """
561 Thread creation event.
562 """
563
564 eventMethod = 'create_thread'
565 eventName = 'Thread creation event'
566 eventDescription = 'A new thread has started.'
567
584
591
593 """
594 @rtype: int
595 @return: Pointer to the first instruction to execute in this thread.
596
597 Returns C{NULL} when the debugger attached to a process
598 and the thread already existed.
599
600 See U{http://msdn.microsoft.com/en-us/library/ms679295(VS.85).aspx}
601 """
602 return self.raw.u.CreateThread.lpStartAddress
603
607 """
608 Process creation event.
609 """
610
611 eventMethod = 'create_process'
612 eventName = 'Process creation event'
613 eventDescription = 'A new process has started.'
614
636
653
670
672 """
673 @rtype: int
674 @return: Pointer to the first instruction to execute in this process.
675
676 Returns C{NULL} when the debugger attaches to a process.
677
678 See U{http://msdn.microsoft.com/en-us/library/ms679295(VS.85).aspx}
679 """
680 return self.raw.u.CreateProcessInfo.lpStartAddress
681
688
695
708
710 """
711 @rtype: str, None
712 @return: This method does it's best to retrieve the filename to
713 the main module of the process. However, sometimes that's not
714 possible, and C{None} is returned instead.
715 """
716
717
718 szFilename = self.get_file_handle().get_filename()
719 if not szFilename:
720
721
722
723
724 aProcess = self.get_process()
725 lpRemoteFilenamePtr = self.raw.u.CreateProcessInfo.lpImageName
726 if lpRemoteFilenamePtr:
727 lpFilename = aProcess.peek_uint(lpRemoteFilenamePtr)
728 fUnicode = bool( self.raw.u.CreateProcessInfo.fUnicode )
729 szFilename = aProcess.peek_string(lpFilename, fUnicode)
730
731
732 if not szFilename:
733 szFilename = aProcess.get_image_name()
734
735
736 return szFilename
737
739 """
740 @rtype: int
741 @return: Base address of the main module.
742 """
743 return self.get_image_base()
744
751
755 """
756 Thread termination event.
757 """
758
759 eventMethod = 'exit_thread'
760 eventName = 'Thread termination event'
761 eventDescription = 'A thread has finished executing.'
762
764 """
765 @rtype: int
766 @return: Exit code of the thread.
767 """
768 return self.raw.u.ExitThread.dwExitCode
769
773 """
774 Process termination event.
775 """
776
777 eventMethod = 'exit_process'
778 eventName = 'Process termination event'
779 eventDescription = 'A process has finished executing.'
780
782 """
783 @rtype: int
784 @return: Exit code of the process.
785 """
786 return self.raw.u.ExitProcess.dwExitCode
787
789 """
790 @rtype: None or str
791 @return: Filename of the main module.
792 C{None} if the filename is unknown.
793 """
794 return self.get_module().get_filename()
795
797 """
798 @rtype: int
799 @return: Base address of the main module.
800 """
801 return self.get_module_base()
802
804 """
805 @rtype: int
806 @return: Base address of the main module.
807 """
808 return self.get_module().get_base()
809
816
820 """
821 Module load event.
822 """
823
824 eventMethod = 'load_dll'
825 eventName = 'Module load event'
826 eventDescription = 'A new DLL library was loaded by the debugee.'
827
829 """
830 @rtype: int
831 @return: Base address for the newly loaded DLL.
832 """
833 return self.raw.u.LoadDll.lpBaseOfDll
834
851
873
875 """
876 @rtype: str, None
877 @return: This method does it's best to retrieve the filename to
878 the newly loaded module. However, sometimes that's not
879 possible, and C{None} is returned instead.
880 """
881
882
883 szFilename = self.get_file_handle().get_filename()
884 if not szFilename:
885
886
887
888
889 aProcess = self.get_process()
890 lpRemoteFilenamePtr = self.raw.u.LoadDll.lpImageName
891 if lpRemoteFilenamePtr:
892 lpFilename = aProcess.peek_uint(lpRemoteFilenamePtr)
893 fUnicode = bool( self.raw.u.LoadDll.fUnicode )
894 szFilename = aProcess.peek_string(lpFilename, fUnicode)
895 if not szFilename:
896 szFilename = None
897
898
899 return szFilename
900
904 """
905 Module unload event.
906 """
907
908 eventMethod = 'unload_dll'
909 eventName = 'Module unload event'
910 eventDescription = 'A DLL library was unloaded by the debugee.'
911
913 """
914 @rtype: int
915 @return: Base address for the recently unloaded DLL.
916 """
917 return self.raw.u.UnloadDll.lpBaseOfDll
918
932
943
945 """
946 @rtype: None or str
947 @return: Filename of the recently unloaded DLL.
948 C{None} if the filename is unknown.
949 """
950 return self.get_module().get_filename()
951
955 """
956 Debug string output event.
957 """
958
959 eventMethod = 'output_string'
960 eventName = 'Debug string output event'
961 eventDescription = 'The debugee sent a message to the debugger.'
962
973
977 """
978 RIP event.
979 """
980
981 eventMethod = 'rip'
982 eventName = 'RIP event'
983 eventDescription = 'An error has occured and the process ' \
984 'can no longer be debugged.'
985
987 """
988 @rtype: int
989 @return: RIP error code as defined by the Win32 API.
990 """
991 return self.raw.u.RipInfo.dwError
992
994 """
995 @rtype: int
996 @return: RIP type code as defined by the Win32 API.
997 """
998 return self.raw.u.RipInfo.dwType
999
1003 """
1004 Factory of L{Event} objects.
1005
1006 @type baseEvent: L{Event}
1007 @cvar baseEvent:
1008 Base class for Event objects.
1009 It's used for unknown event codes.
1010
1011 @type eventClasses: dict( int S{->} L{Event} )
1012 @cvar eventClasses:
1013 Dictionary that maps event codes to L{Event} subclasses.
1014 """
1015
1016 baseEvent = Event
1017 eventClasses = {
1018 win32.EXCEPTION_DEBUG_EVENT : ExceptionEvent,
1019 win32.CREATE_THREAD_DEBUG_EVENT : CreateThreadEvent,
1020 win32.CREATE_PROCESS_DEBUG_EVENT : CreateProcessEvent,
1021 win32.EXIT_THREAD_DEBUG_EVENT : ExitThreadEvent,
1022 win32.EXIT_PROCESS_DEBUG_EVENT : ExitProcessEvent,
1023 win32.LOAD_DLL_DEBUG_EVENT : LoadDLLEvent,
1024 win32.UNLOAD_DLL_DEBUG_EVENT : UnloadDLLEvent,
1025 win32.OUTPUT_DEBUG_STRING_EVENT : OutputDebugStringEvent,
1026 win32.RIP_EVENT : RIPEvent,
1027 }
1028
1029 @classmethod
1030 - def get(cls, debug, raw):
1031 """
1032 @type debug: L{Debug}
1033 @param debug: Debug object that received the event.
1034
1035 @type raw: L{DEBUG_EVENT}
1036 @param raw: Raw DEBUG_EVENT structure as used by the Win32 API.
1037
1038 @rtype: L{Event}
1039 @returns: An Event object or one of it's subclasses,
1040 depending on the event type.
1041 """
1042 eventClass = cls.eventClasses.get(raw.dwDebugEventCode, cls.baseEvent)
1043 return eventClass(debug, raw)
1044
1045 - def __new__(typ, *args, **kwargs):
1046 """
1047 C{EventFactory} is a singleton, you can't really have multiple
1048 instances of it. To create this effect, the C{__new__} operator
1049 was overriden to return always the I{class} object instead
1050 of new I{instances}.
1051
1052 @rtype: L{EventFactory}
1053 @return: C{EventFactory} class (NOT an instance)
1054 """
1055 return EventFactory
1056
1060 """
1061 Base class for debug event handlers.
1062
1063 Your program should subclass it to implement it's own event handling.
1064
1065 The signature for event handlers is the following::
1066
1067 def event_handler(self, event):
1068
1069 Where B{event} is an L{Event} object.
1070
1071 Each event handler is named after the event they handle.
1072 This is the list of all valid event handler names:
1073
1074 - I{event}
1075
1076 Receives an L{Event} object or an object of any of it's subclasses,
1077 and handles any event for which no handler was defined.
1078
1079 - I{unknown_event}
1080
1081 Receives an L{Event} object or an object of any of it's subclasses,
1082 and handles any event unknown to the debugging engine. (This is not
1083 likely to happen unless the Win32 debugging API is changed in future
1084 versions of Windows).
1085
1086 - I{exception}
1087
1088 Receives an L{ExceptionEvent} object and handles any exception for
1089 which no handler was defined. See above for exception handlers.
1090
1091 - I{unknown_exception}
1092
1093 Receives an L{ExceptionEvent} object and handles any exception unknown
1094 to the debugging engine. This usually happens for C++ exceptions, which
1095 are not standardized and may change from one compiler to the next.
1096
1097 Currently we have partial support for C++ exceptions thrown by Microsoft
1098 compilers.
1099
1100 Also see: U{RaiseException()
1101 <http://msdn.microsoft.com/en-us/library/ms680552(VS.85).aspx>}
1102
1103 - I{create_thread}
1104
1105 Receives a L{CreateThreadEvent} object.
1106
1107 - I{create_process}
1108
1109 Receives a L{CreateProcessEvent} object.
1110
1111 - I{exit_thread}
1112
1113 Receives a L{ExitThreadEvent} object.
1114
1115 - I{exit_process}
1116
1117 Receives a L{ExitProcessEvent} object.
1118
1119 - I{load_dll}
1120
1121 Receives a L{LoadDLLEvent} object.
1122
1123 - I{unload_dll}
1124
1125 Receives an L{UnloadDLLEvent} object.
1126
1127 - I{output_string}
1128
1129 Receives an L{OutputDebugStringEvent} object.
1130
1131 - I{rip}
1132
1133 Receives a L{RIPEvent} object.
1134
1135 This is the list of all valid exception handler names
1136 (they all receive an L{ExceptionEvent} object):
1137
1138 - I{access_violation}
1139 - I{array_bounds_exceeded}
1140 - I{breakpoint}
1141 - I{control_c_exit}
1142 - I{datatype_misalignment}
1143 - I{debug_control_c}
1144 - I{float_denormal_operand}
1145 - I{float_divide_by_zero}
1146 - I{float_inexact_result}
1147 - I{float_invalid_operation}
1148 - I{float_overflow}
1149 - I{float_stack_check}
1150 - I{float_underflow}
1151 - I{guard_page}
1152 - I{illegal_instruction}
1153 - I{in_page_error}
1154 - I{integer_divide_by_zero}
1155 - I{integer_overflow}
1156 - I{invalid_disposition}
1157 - I{invalid_handle}
1158 - I{ms_vc_exception}
1159 - I{noncontinuable_exception}
1160 - I{possible_deadlock}
1161 - I{privileged_instruction}
1162 - I{single_step}
1163 - I{stack_overflow}
1164
1165
1166
1167 @type apiHooks: dict( str S{->} tuple( str, int ) )
1168 @cvar apiHooks:
1169 Dictionary that maps module names to
1170 tuples of ( procedure name, parameter count ).
1171
1172 All procedures listed here will be hooked for calls from the debuguee.
1173 When this happens, the corresponding event handler is notified both
1174 when the procedure is entered and when it's left by the debugee.
1175
1176 For example, if the procedure name is "LoadLibraryEx" the event handler
1177 routines must be defined as "pre_LoadLibraryEx" and "post_LoadLibraryEx"
1178 in your class.
1179
1180 The signature for the routines can be something like this::
1181
1182 def pre_LoadLibraryEx(event, *params):
1183 ra = params[0] # return address
1184 argv = params[1:] # function parameters
1185
1186 # (...)
1187
1188 def post_LoadLibrary(event, return_value):
1189
1190 # (...)
1191
1192 But since you can also specify the number of arguments, this signature
1193 works too (four arguments in this case)::
1194
1195 def pre_LoadLibraryEx(event, ra, lpFilename, hFile, dwFlags):
1196 szFilename = event.get_process().peek_string(lpFilename)
1197
1198 # (...)
1199
1200 Note that the number of parameters to pull from the stack includes the
1201 return address. The apiHooks dictionary for the example above would
1202 look like this::
1203
1204 apiHook = {
1205
1206 "kernel32.dll" : (
1207
1208 # Procedure name Parameter count
1209 ( "LoadLibraryEx", 4 ),
1210
1211 # (more procedures can go here...)
1212 ),
1213
1214 # (more libraries can go here...)
1215 }
1216
1217 For a more complete support of API hooking, you can also check out
1218 Universal Hooker at U{http://oss.coresecurity.com/projects/uhooker.htm}
1219 """
1220
1221
1222
1223
1224 apiHooks = {}
1225
1227
1228
1229 if self.apiHooks and win32.CONTEXT.arch != 'i386':
1230 raise NotImplementedError, "Hooks are not yet implemented in 64 bits"
1231
1232
1233
1234
1235 self.__apiHooks = dict()
1236 for lib, hooks in self.apiHooks.iteritems():
1237 self.__apiHooks[lib] = [ ApiHook(self, *h) for h in hooks ]
1238
1240 """
1241 Hook the requested API calls (in self.apiHooks).
1242
1243 This method is called automatically whenever a DLL is loaded.
1244 """
1245 if self.__apiHooks:
1246 fileName = event.get_module().get_filename()
1247 if fileName:
1248 lib_name = PathOperations.pathname_to_filename(fileName).lower()
1249 for hook_lib, hook_api_list in self.__apiHooks.iteritems():
1250 if hook_lib == lib_name:
1251 for hook_api_stub in hook_api_list:
1252 hook_api_stub.hook(event.debug, event.get_pid(),
1253 lib_name)
1254
1273
1274 - def event(self, event):
1275 """
1276 Handler for events not handled by any other defined method.
1277
1278 @type event: L{Event}
1279 @param event: Event object.
1280 """
1281 pass
1282
1286 """
1287 Implements debug event dispatching capabilities.
1288 """
1289
1290
1291
1292
1293 __preEventNotifyCallbackName = {
1294 win32.CREATE_THREAD_DEBUG_EVENT : 'notify_create_thread',
1295 win32.CREATE_PROCESS_DEBUG_EVENT : 'notify_create_process',
1296 win32.LOAD_DLL_DEBUG_EVENT : 'notify_load_dll',
1297 }
1298
1299
1300
1301
1302 __postEventNotifyCallbackName = {
1303 win32.EXIT_THREAD_DEBUG_EVENT : 'notify_exit_thread',
1304 win32.EXIT_PROCESS_DEBUG_EVENT : 'notify_exit_process',
1305 win32.UNLOAD_DLL_DEBUG_EVENT : 'notify_unload_dll',
1306 win32.RIP_EVENT : 'notify_rip',
1307 }
1308
1309
1310
1311
1312 __preExceptionNotifyCallbackName = {
1313 win32.EXCEPTION_BREAKPOINT : 'notify_breakpoint',
1314 win32.EXCEPTION_SINGLE_STEP : 'notify_single_step',
1315 win32.EXCEPTION_GUARD_PAGE : 'notify_guard_page',
1316 win32.DBG_CONTROL_C : 'notify_debug_control_c',
1317 win32.MS_VC_EXCEPTION : 'notify_ms_vc_exception',
1318 }
1319
1320
1321
1322
1323 __postExceptionNotifyCallbackName = {
1324 }
1325
1326 - def __init__(self, eventHandler = None):
1327 """
1328 Event dispatcher.
1329
1330 @type eventHandler: L{EventHandler}
1331 @param eventHandler: (Optional) Event handler object.
1332
1333 @note: The L{eventHandler} parameter may be any callable Python object
1334 (for example a function, or an instance method).
1335 However you'll probably find it more convenient to use an instance
1336 of a subclass of L{EventHandler} here.
1337 """
1338 if eventHandler is not None and not callable(eventHandler):
1339 raise TypeError, "Invalid event handler"
1340 self.__eventHandler = eventHandler
1341
1343 """
1344 Sends event notifications to the L{Debug} object and
1345 the L{EventHandler} object provided by the user.
1346
1347 The L{Debug} object will forward the notifications to it's contained
1348 snapshot objects (L{System}, L{Process}, L{Thread} and L{Module}) when
1349 appropriate.
1350
1351 @warning: This method is called automatically from L{Debug.dispatch}.
1352
1353 @see: L{Debug.cont}, L{Debug.loop}, L{Debug.wait}
1354
1355 @type event: L{Event}
1356 @param event: Event object passed to L{Debug.dispatch}.
1357
1358 @raise WindowsError: Raises an exception on error.
1359 """
1360 returnValue = None
1361 bCallHandler = True
1362 pre_handler = None
1363 post_handler = None
1364 eventCode = event.get_code()
1365
1366
1367
1368 if eventCode == win32.EXCEPTION_DEBUG_EVENT:
1369 exceptionCode = event.get_exception_code()
1370 pre_name = self.__preExceptionNotifyCallbackName.get(
1371 exceptionCode, None)
1372 post_name = self.__postExceptionNotifyCallbackName.get(
1373 exceptionCode, None)
1374 if pre_name is not None:
1375 pre_handler = getattr(self, pre_name, None)
1376 if post_name is not None:
1377 post_handler = getattr(self, post_name, None)
1378
1379
1380
1381
1382 if pre_handler is None:
1383 pre_name = self.__preEventNotifyCallbackName.get(eventCode, None)
1384 if pre_name is not None:
1385 pre_handler = getattr(self, pre_name, pre_handler)
1386
1387
1388
1389
1390 if post_handler is None:
1391 post_name = self.__postEventNotifyCallbackName.get(eventCode, None)
1392 if post_name is not None:
1393 post_handler = getattr(self, post_name, post_handler)
1394
1395
1396
1397 if pre_handler is not None:
1398 bCallHandler = pre_handler(event)
1399
1400
1401
1402 try:
1403 if bCallHandler and self.__eventHandler is not None:
1404 returnValue = self.__eventHandler(event)
1405
1406
1407
1408 finally:
1409 if post_handler is not None:
1410 post_handler(event)
1411
1412
1413
1414 return returnValue
1415