1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 """
32 Event handling module.
33
34 @see: U{http://apps.sourceforge.net/trac/winappdbg/wiki/Debugging}
35
36 @group Debugging:
37 EventHandler, EventSift
38
39 @group Debug events:
40 EventFactory,
41 EventDispatcher,
42 Event,
43 NoEvent,
44 CreateProcessEvent,
45 CreateThreadEvent,
46 ExitProcessEvent,
47 ExitThreadEvent,
48 LoadDLLEvent,
49 UnloadDLLEvent,
50 OutputDebugStringEvent,
51 RIPEvent,
52 ExceptionEvent
53
54 @group Warnings:
55 EventCallbackWarning
56 """
57
58 __revision__ = "$Id: event.py 1299 2013-12-20 09:30:55Z qvasimodo $"
59
60 __all__ = [
61
62
63 'EventFactory',
64
65
66 'EventDispatcher',
67
68
69 'EventHandler',
70 'EventSift',
71
72
73 'EventCallbackWarning',
74
75
76
77 'NoEvent',
78
79
80 'Event',
81
82
83 'CreateProcessEvent',
84 'CreateThreadEvent',
85 'ExitProcessEvent',
86 'ExitThreadEvent',
87 'LoadDLLEvent',
88 'UnloadDLLEvent',
89 'OutputDebugStringEvent',
90 'RIPEvent',
91 'ExceptionEvent'
92 ]
93
94 import win32
95 from win32 import FileHandle, ProcessHandle, ThreadHandle
96 from breakpoint import ApiHook
97 from module import Module
98 from thread import Thread
99 from process import Process
100 from textio import HexDump
101 from util import StaticClass, PathOperations
102
103 import ctypes
104 import warnings
105 import traceback
110 """
111 This warning is issued when an uncaught exception was raised by a
112 user-defined event handler.
113 """
114
115
116
117 -class Event (object):
118 """
119 Event object.
120
121 @type eventMethod: str
122 @cvar eventMethod:
123 Method name to call when using L{EventHandler} subclasses.
124 Used internally.
125
126 @type eventName: str
127 @cvar eventName:
128 User-friendly name of the event.
129
130 @type eventDescription: str
131 @cvar eventDescription:
132 User-friendly description of the event.
133
134 @type debug: L{Debug}
135 @ivar debug:
136 Debug object that received the event.
137
138 @type raw: L{DEBUG_EVENT}
139 @ivar raw:
140 Raw DEBUG_EVENT structure as used by the Win32 API.
141
142 @type continueStatus: int
143 @ivar continueStatus:
144 Continue status to pass to L{win32.ContinueDebugEvent}.
145 """
146
147 eventMethod = 'unknown_event'
148 eventName = 'Unknown event'
149 eventDescription = 'A debug event of an unknown type has occured.'
150
152 """
153 @type debug: L{Debug}
154 @param debug: Debug object that received the event.
155
156 @type raw: L{DEBUG_EVENT}
157 @param raw: Raw DEBUG_EVENT structure as used by the Win32 API.
158 """
159 self.debug = debug
160 self.raw = raw
161 self.continueStatus = win32.DBG_EXCEPTION_NOT_HANDLED
162
163
164
165
166
167
168
169
170
171
173 """
174 @rtype: str
175 @return: User-friendly name of the event.
176 """
177 return self.eventName
178
180 """
181 @rtype: str
182 @return: User-friendly description of the event.
183 """
184 return self.eventDescription
185
187 """
188 @rtype: int
189 @return: Debug event code as defined in the Win32 API.
190 """
191 return self.raw.dwDebugEventCode
192
193
194
195
196
197
198
199
200
201
202
203
204
205
207 """
208 @see: L{get_process}
209
210 @rtype: int
211 @return: Process global ID where the event occured.
212 """
213 return self.raw.dwProcessId
214
216 """
217 @see: L{get_thread}
218
219 @rtype: int
220 @return: Thread global ID where the event occured.
221 """
222 return self.raw.dwThreadId
223
243
261
265 """
266 No event.
267
268 Dummy L{Event} object that can be used as a placeholder when no debug
269 event has occured yet. It's never returned by the L{EventFactory}.
270 """
271
272 eventMethod = 'no_event'
273 eventName = 'No event'
274 eventDescription = 'No debug event has occured.'
275
278
280 """
281 Always returns C{0}, so when evaluating the object as a boolean it's
282 always C{False}. This prevents L{Debug.cont} from trying to continue
283 a dummy event.
284 """
285 return 0
286
289
292
295
298
301
305 """
306 Exception event.
307
308 @type exceptionName: dict( int S{->} str )
309 @cvar exceptionName:
310 Mapping of exception constants to their names.
311
312 @type exceptionDescription: dict( int S{->} str )
313 @cvar exceptionDescription:
314 Mapping of exception constants to user-friendly strings.
315
316 @type breakpoint: L{Breakpoint}
317 @ivar breakpoint:
318 If the exception was caused by one of our breakpoints, this member
319 contains a reference to the breakpoint object. Otherwise it's not
320 defined. It should only be used from the condition or action callback
321 routines, instead of the event handler.
322
323 @type hook: L{Hook}
324 @ivar hook:
325 If the exception was caused by a function hook, this member contains a
326 reference to the hook object. Otherwise it's not defined. It should
327 only be used from the hook callback routines, instead of the event
328 handler.
329 """
330
331 eventName = 'Exception event'
332 eventDescription = 'An exception was raised by the debugee.'
333
334 __exceptionMethod = {
335 win32.EXCEPTION_ACCESS_VIOLATION : 'access_violation',
336 win32.EXCEPTION_ARRAY_BOUNDS_EXCEEDED : 'array_bounds_exceeded',
337 win32.EXCEPTION_BREAKPOINT : 'breakpoint',
338 win32.EXCEPTION_DATATYPE_MISALIGNMENT : 'datatype_misalignment',
339 win32.EXCEPTION_FLT_DENORMAL_OPERAND : 'float_denormal_operand',
340 win32.EXCEPTION_FLT_DIVIDE_BY_ZERO : 'float_divide_by_zero',
341 win32.EXCEPTION_FLT_INEXACT_RESULT : 'float_inexact_result',
342 win32.EXCEPTION_FLT_INVALID_OPERATION : 'float_invalid_operation',
343 win32.EXCEPTION_FLT_OVERFLOW : 'float_overflow',
344 win32.EXCEPTION_FLT_STACK_CHECK : 'float_stack_check',
345 win32.EXCEPTION_FLT_UNDERFLOW : 'float_underflow',
346 win32.EXCEPTION_ILLEGAL_INSTRUCTION : 'illegal_instruction',
347 win32.EXCEPTION_IN_PAGE_ERROR : 'in_page_error',
348 win32.EXCEPTION_INT_DIVIDE_BY_ZERO : 'integer_divide_by_zero',
349 win32.EXCEPTION_INT_OVERFLOW : 'integer_overflow',
350 win32.EXCEPTION_INVALID_DISPOSITION : 'invalid_disposition',
351 win32.EXCEPTION_NONCONTINUABLE_EXCEPTION : 'noncontinuable_exception',
352 win32.EXCEPTION_PRIV_INSTRUCTION : 'privileged_instruction',
353 win32.EXCEPTION_SINGLE_STEP : 'single_step',
354 win32.EXCEPTION_STACK_OVERFLOW : 'stack_overflow',
355 win32.EXCEPTION_GUARD_PAGE : 'guard_page',
356 win32.EXCEPTION_INVALID_HANDLE : 'invalid_handle',
357 win32.EXCEPTION_POSSIBLE_DEADLOCK : 'possible_deadlock',
358 win32.EXCEPTION_WX86_BREAKPOINT : 'wow64_breakpoint',
359 win32.CONTROL_C_EXIT : 'control_c_exit',
360 win32.DBG_CONTROL_C : 'debug_control_c',
361 win32.MS_VC_EXCEPTION : 'ms_vc_exception',
362 }
363
364 __exceptionName = {
365 win32.EXCEPTION_ACCESS_VIOLATION : 'EXCEPTION_ACCESS_VIOLATION',
366 win32.EXCEPTION_ARRAY_BOUNDS_EXCEEDED : 'EXCEPTION_ARRAY_BOUNDS_EXCEEDED',
367 win32.EXCEPTION_BREAKPOINT : 'EXCEPTION_BREAKPOINT',
368 win32.EXCEPTION_DATATYPE_MISALIGNMENT : 'EXCEPTION_DATATYPE_MISALIGNMENT',
369 win32.EXCEPTION_FLT_DENORMAL_OPERAND : 'EXCEPTION_FLT_DENORMAL_OPERAND',
370 win32.EXCEPTION_FLT_DIVIDE_BY_ZERO : 'EXCEPTION_FLT_DIVIDE_BY_ZERO',
371 win32.EXCEPTION_FLT_INEXACT_RESULT : 'EXCEPTION_FLT_INEXACT_RESULT',
372 win32.EXCEPTION_FLT_INVALID_OPERATION : 'EXCEPTION_FLT_INVALID_OPERATION',
373 win32.EXCEPTION_FLT_OVERFLOW : 'EXCEPTION_FLT_OVERFLOW',
374 win32.EXCEPTION_FLT_STACK_CHECK : 'EXCEPTION_FLT_STACK_CHECK',
375 win32.EXCEPTION_FLT_UNDERFLOW : 'EXCEPTION_FLT_UNDERFLOW',
376 win32.EXCEPTION_ILLEGAL_INSTRUCTION : 'EXCEPTION_ILLEGAL_INSTRUCTION',
377 win32.EXCEPTION_IN_PAGE_ERROR : 'EXCEPTION_IN_PAGE_ERROR',
378 win32.EXCEPTION_INT_DIVIDE_BY_ZERO : 'EXCEPTION_INT_DIVIDE_BY_ZERO',
379 win32.EXCEPTION_INT_OVERFLOW : 'EXCEPTION_INT_OVERFLOW',
380 win32.EXCEPTION_INVALID_DISPOSITION : 'EXCEPTION_INVALID_DISPOSITION',
381 win32.EXCEPTION_NONCONTINUABLE_EXCEPTION : 'EXCEPTION_NONCONTINUABLE_EXCEPTION',
382 win32.EXCEPTION_PRIV_INSTRUCTION : 'EXCEPTION_PRIV_INSTRUCTION',
383 win32.EXCEPTION_SINGLE_STEP : 'EXCEPTION_SINGLE_STEP',
384 win32.EXCEPTION_STACK_OVERFLOW : 'EXCEPTION_STACK_OVERFLOW',
385 win32.EXCEPTION_GUARD_PAGE : 'EXCEPTION_GUARD_PAGE',
386 win32.EXCEPTION_INVALID_HANDLE : 'EXCEPTION_INVALID_HANDLE',
387 win32.EXCEPTION_POSSIBLE_DEADLOCK : 'EXCEPTION_POSSIBLE_DEADLOCK',
388 win32.EXCEPTION_WX86_BREAKPOINT : 'EXCEPTION_WX86_BREAKPOINT',
389 win32.CONTROL_C_EXIT : 'CONTROL_C_EXIT',
390 win32.DBG_CONTROL_C : 'DBG_CONTROL_C',
391 win32.MS_VC_EXCEPTION : 'MS_VC_EXCEPTION',
392 }
393
394 __exceptionDescription = {
395 win32.EXCEPTION_ACCESS_VIOLATION : 'Access violation',
396 win32.EXCEPTION_ARRAY_BOUNDS_EXCEEDED : 'Array bounds exceeded',
397 win32.EXCEPTION_BREAKPOINT : 'Breakpoint',
398 win32.EXCEPTION_DATATYPE_MISALIGNMENT : 'Datatype misalignment',
399 win32.EXCEPTION_FLT_DENORMAL_OPERAND : 'Float denormal operand',
400 win32.EXCEPTION_FLT_DIVIDE_BY_ZERO : 'Float divide by zero',
401 win32.EXCEPTION_FLT_INEXACT_RESULT : 'Float inexact result',
402 win32.EXCEPTION_FLT_INVALID_OPERATION : 'Float invalid operation',
403 win32.EXCEPTION_FLT_OVERFLOW : 'Float overflow',
404 win32.EXCEPTION_FLT_STACK_CHECK : 'Float stack check',
405 win32.EXCEPTION_FLT_UNDERFLOW : 'Float underflow',
406 win32.EXCEPTION_ILLEGAL_INSTRUCTION : 'Illegal instruction',
407 win32.EXCEPTION_IN_PAGE_ERROR : 'In-page error',
408 win32.EXCEPTION_INT_DIVIDE_BY_ZERO : 'Integer divide by zero',
409 win32.EXCEPTION_INT_OVERFLOW : 'Integer overflow',
410 win32.EXCEPTION_INVALID_DISPOSITION : 'Invalid disposition',
411 win32.EXCEPTION_NONCONTINUABLE_EXCEPTION : 'Noncontinuable exception',
412 win32.EXCEPTION_PRIV_INSTRUCTION : 'Privileged instruction',
413 win32.EXCEPTION_SINGLE_STEP : 'Single step event',
414 win32.EXCEPTION_STACK_OVERFLOW : 'Stack limits overflow',
415 win32.EXCEPTION_GUARD_PAGE : 'Guard page hit',
416 win32.EXCEPTION_INVALID_HANDLE : 'Invalid handle',
417 win32.EXCEPTION_POSSIBLE_DEADLOCK : 'Possible deadlock',
418 win32.EXCEPTION_WX86_BREAKPOINT : 'WOW64 breakpoint',
419 win32.CONTROL_C_EXIT : 'Control-C exit',
420 win32.DBG_CONTROL_C : 'Debug Control-C',
421 win32.MS_VC_EXCEPTION : 'Microsoft Visual C++ exception',
422 }
423
424 @property
428
437
439 """
440 @rtype: str
441 @return: User-friendly name of the exception.
442 """
443 code = self.get_exception_code()
444 description = self.__exceptionDescription.get(code, None)
445 if description is None:
446 try:
447 description = 'Exception code %s (%s)'
448 description = description % (HexDump.integer(code),
449 ctypes.FormatError(code))
450 except OverflowError:
451 description = 'Exception code %s' % HexDump.integer(code)
452 return description
453
455 """
456 @rtype: bool
457 @return: C{True} for first chance exceptions, C{False} for last chance.
458 """
459 return self.raw.u.Exception.dwFirstChance != 0
460
462 """
463 @rtype: bool
464 @return: The opposite of L{is_first_chance}.
465 """
466 return not self.is_first_chance()
467
469 """
470 @see: U{http://msdn.microsoft.com/en-us/library/aa363082(VS.85).aspx}
471
472 @rtype: bool
473 @return: C{True} if the exception is noncontinuable,
474 C{False} otherwise.
475
476 Attempting to continue a noncontinuable exception results in an
477 EXCEPTION_NONCONTINUABLE_EXCEPTION exception to be raised.
478 """
479 return bool( self.raw.u.Exception.ExceptionRecord.ExceptionFlags & \
480 win32.EXCEPTION_NONCONTINUABLE )
481
483 """
484 @rtype: bool
485 @return: The opposite of L{is_noncontinuable}.
486 """
487 return not self.is_noncontinuable()
488
490 """
491 Determines if this is an user-defined exception. User-defined
492 exceptions may contain any exception code that is not system reserved.
493
494 Often the exception code is also a valid Win32 error code, but that's
495 up to the debugged application.
496
497 @rtype: bool
498 @return: C{True} if the exception is user-defined, C{False} otherwise.
499 """
500 return self.get_exception_code() & 0x10000000 == 0
501
503 """
504 @rtype: bool
505 @return: The opposite of L{is_user_defined_exception}.
506 """
507 return not self.is_user_defined_exception()
508
515
525
541
555
557 """
558 @rtype: int
559 @return: Access violation type.
560 Should be one of the following constants:
561
562 - L{win32.EXCEPTION_READ_FAULT}
563 - L{win32.EXCEPTION_WRITE_FAULT}
564 - L{win32.EXCEPTION_EXECUTE_FAULT}
565
566 @note: This method is only meaningful for access violation exceptions,
567 in-page memory error exceptions and guard page exceptions.
568
569 @raise NotImplementedError: Wrong kind of exception.
570 """
571 if self.get_exception_code() not in (win32.EXCEPTION_ACCESS_VIOLATION,
572 win32.EXCEPTION_IN_PAGE_ERROR, win32.EXCEPTION_GUARD_PAGE):
573 msg = "This method is not meaningful for %s."
574 raise NotImplementedError(msg % self.get_exception_name())
575 return self.get_exception_information(0)
576
592
594 """
595 @rtype: int
596 @return: NTSTATUS status code that caused the exception.
597
598 @note: This method is only meaningful for in-page memory error
599 exceptions.
600
601 @raise NotImplementedError: Not an in-page memory error.
602 """
603 if self.get_exception_code() != win32.EXCEPTION_IN_PAGE_ERROR:
604 msg = "This method is only meaningful "\
605 "for in-page memory error exceptions."
606 raise NotImplementedError(msg)
607 return self.get_exception_information(2)
608
610 """
611 @rtype: bool
612 @return: Returns C{True} if there are additional exception records
613 associated with this exception. This would mean the exception
614 is nested, that is, it was triggered while trying to handle
615 at least one previous exception.
616 """
617 return bool(self.raw.u.Exception.ExceptionRecord.ExceptionRecord)
618
620 """
621 Traverses the exception record linked list and builds a Python list.
622
623 Nested exception records are received for nested exceptions. This
624 happens when an exception is raised in the debugee while trying to
625 handle a previous exception.
626
627 @rtype: list( L{win32.EXCEPTION_RECORD} )
628 @return:
629 List of raw exception record structures as used by the Win32 API.
630
631 There is always at least one exception record, so the list is
632 never empty. All other methods of this class read from the first
633 exception record only, that is, the most recent exception.
634 """
635
636
637 nested = list()
638 record = self.raw.u.Exception
639 while True:
640 record = record.ExceptionRecord
641 if not record:
642 break
643 nested.append(record)
644 return nested
645
686
690 """
691 Thread creation event.
692 """
693
694 eventMethod = 'create_thread'
695 eventName = 'Thread creation event'
696 eventDescription = 'A new thread has started.'
697
712
719
721 """
722 @rtype: int
723 @return: Pointer to the first instruction to execute in this thread.
724
725 Returns C{NULL} when the debugger attached to a process
726 and the thread already existed.
727
728 See U{http://msdn.microsoft.com/en-us/library/ms679295(VS.85).aspx}
729 """
730 return self.raw.u.CreateThread.lpStartAddress
731
735 """
736 Process creation event.
737 """
738
739 eventMethod = 'create_process'
740 eventName = 'Process creation event'
741 eventDescription = 'A new process has started.'
742
762
777
792
794 """
795 @rtype: int
796 @return: Pointer to the first instruction to execute in this process.
797
798 Returns C{NULL} when the debugger attaches to a process.
799
800 See U{http://msdn.microsoft.com/en-us/library/ms679295(VS.85).aspx}
801 """
802 return self.raw.u.CreateProcessInfo.lpStartAddress
803
805 """
806 @rtype: int
807 @return: Base address of the main module.
808 @warn: This value is taken from the PE file
809 and may be incorrect because of ASLR!
810 """
811
812 return self.raw.u.CreateProcessInfo.lpBaseOfImage
813
820
833
835 """
836 @rtype: str, None
837 @return: This method does it's best to retrieve the filename to
838 the main module of the process. However, sometimes that's not
839 possible, and C{None} is returned instead.
840 """
841
842
843 szFilename = None
844 hFile = self.get_file_handle()
845 if hFile:
846 szFilename = hFile.get_filename()
847 if not szFilename:
848
849
850
851
852 aProcess = self.get_process()
853 lpRemoteFilenamePtr = self.raw.u.CreateProcessInfo.lpImageName
854 if lpRemoteFilenamePtr:
855 lpFilename = aProcess.peek_uint(lpRemoteFilenamePtr)
856 fUnicode = bool( self.raw.u.CreateProcessInfo.fUnicode )
857 szFilename = aProcess.peek_string(lpFilename, fUnicode)
858
859
860
861
862
863
864 if not szFilename:
865 szFilename = aProcess.get_image_name()
866
867
868 return szFilename
869
871 """
872 @rtype: int
873 @return: Base address of the main module.
874 """
875 return self.get_image_base()
876
883
887 """
888 Thread termination event.
889 """
890
891 eventMethod = 'exit_thread'
892 eventName = 'Thread termination event'
893 eventDescription = 'A thread has finished executing.'
894
896 """
897 @rtype: int
898 @return: Exit code of the thread.
899 """
900 return self.raw.u.ExitThread.dwExitCode
901
905 """
906 Process termination event.
907 """
908
909 eventMethod = 'exit_process'
910 eventName = 'Process termination event'
911 eventDescription = 'A process has finished executing.'
912
914 """
915 @rtype: int
916 @return: Exit code of the process.
917 """
918 return self.raw.u.ExitProcess.dwExitCode
919
921 """
922 @rtype: None or str
923 @return: Filename of the main module.
924 C{None} if the filename is unknown.
925 """
926 return self.get_module().get_filename()
927
929 """
930 @rtype: int
931 @return: Base address of the main module.
932 """
933 return self.get_module_base()
934
936 """
937 @rtype: int
938 @return: Base address of the main module.
939 """
940 return self.get_module().get_base()
941
948
952 """
953 Module load event.
954 """
955
956 eventMethod = 'load_dll'
957 eventName = 'Module load event'
958 eventDescription = 'A new DLL library was loaded by the debugee.'
959
961 """
962 @rtype: int
963 @return: Base address for the newly loaded DLL.
964 """
965 return self.raw.u.LoadDll.lpBaseOfDll
966
985
1005
1007 """
1008 @rtype: str, None
1009 @return: This method does it's best to retrieve the filename to
1010 the newly loaded module. However, sometimes that's not
1011 possible, and C{None} is returned instead.
1012 """
1013 szFilename = None
1014
1015
1016
1017
1018 aProcess = self.get_process()
1019 lpRemoteFilenamePtr = self.raw.u.LoadDll.lpImageName
1020 if lpRemoteFilenamePtr:
1021 lpFilename = aProcess.peek_uint(lpRemoteFilenamePtr)
1022 fUnicode = bool( self.raw.u.LoadDll.fUnicode )
1023 szFilename = aProcess.peek_string(lpFilename, fUnicode)
1024 if not szFilename:
1025 szFilename = None
1026
1027
1028 if not szFilename:
1029 hFile = self.get_file_handle()
1030 if hFile:
1031 szFilename = hFile.get_filename()
1032
1033
1034 return szFilename
1035
1039 """
1040 Module unload event.
1041 """
1042
1043 eventMethod = 'unload_dll'
1044 eventName = 'Module unload event'
1045 eventDescription = 'A DLL library was unloaded by the debugee.'
1046
1048 """
1049 @rtype: int
1050 @return: Base address for the recently unloaded DLL.
1051 """
1052 return self.raw.u.UnloadDll.lpBaseOfDll
1053
1067
1078
1080 """
1081 @rtype: None or str
1082 @return: Filename of the recently unloaded DLL.
1083 C{None} if the filename is unknown.
1084 """
1085 return self.get_module().get_filename()
1086
1090 """
1091 Debug string output event.
1092 """
1093
1094 eventMethod = 'output_string'
1095 eventName = 'Debug string output event'
1096 eventDescription = 'The debugee sent a message to the debugger.'
1097
1108
1112 """
1113 RIP event.
1114 """
1115
1116 eventMethod = 'rip'
1117 eventName = 'RIP event'
1118 eventDescription = 'An error has occured and the process ' \
1119 'can no longer be debugged.'
1120
1122 """
1123 @rtype: int
1124 @return: RIP error code as defined by the Win32 API.
1125 """
1126 return self.raw.u.RipInfo.dwError
1127
1129 """
1130 @rtype: int
1131 @return: RIP type code as defined by the Win32 API.
1132 May be C{0} or one of the following:
1133 - L{win32.SLE_ERROR}
1134 - L{win32.SLE_MINORERROR}
1135 - L{win32.SLE_WARNING}
1136 """
1137 return self.raw.u.RipInfo.dwType
1138
1142 """
1143 Factory of L{Event} objects.
1144
1145 @type baseEvent: L{Event}
1146 @cvar baseEvent:
1147 Base class for Event objects.
1148 It's used for unknown event codes.
1149
1150 @type eventClasses: dict( int S{->} L{Event} )
1151 @cvar eventClasses:
1152 Dictionary that maps event codes to L{Event} subclasses.
1153 """
1154
1155 baseEvent = Event
1156 eventClasses = {
1157 win32.EXCEPTION_DEBUG_EVENT : ExceptionEvent,
1158 win32.CREATE_THREAD_DEBUG_EVENT : CreateThreadEvent,
1159 win32.CREATE_PROCESS_DEBUG_EVENT : CreateProcessEvent,
1160 win32.EXIT_THREAD_DEBUG_EVENT : ExitThreadEvent,
1161 win32.EXIT_PROCESS_DEBUG_EVENT : ExitProcessEvent,
1162 win32.LOAD_DLL_DEBUG_EVENT : LoadDLLEvent,
1163 win32.UNLOAD_DLL_DEBUG_EVENT : UnloadDLLEvent,
1164 win32.OUTPUT_DEBUG_STRING_EVENT : OutputDebugStringEvent,
1165 win32.RIP_EVENT : RIPEvent,
1166 }
1167
1168 @classmethod
1169 - def get(cls, debug, raw):
1170 """
1171 @type debug: L{Debug}
1172 @param debug: Debug object that received the event.
1173
1174 @type raw: L{DEBUG_EVENT}
1175 @param raw: Raw DEBUG_EVENT structure as used by the Win32 API.
1176
1177 @rtype: L{Event}
1178 @returns: An Event object or one of it's subclasses,
1179 depending on the event type.
1180 """
1181 eventClass = cls.eventClasses.get(raw.dwDebugEventCode, cls.baseEvent)
1182 return eventClass(debug, raw)
1183
1187 """
1188 Base class for debug event handlers.
1189
1190 Your program should subclass it to implement it's own event handling.
1191
1192 The constructor can be overriden as long as you call the superclass
1193 constructor. The special method L{__call__} B{MUST NOT} be overriden.
1194
1195 The signature for event handlers is the following::
1196
1197 def event_handler(self, event):
1198
1199 Where B{event} is an L{Event} object.
1200
1201 Each event handler is named after the event they handle.
1202 This is the list of all valid event handler names:
1203
1204 - I{event}
1205
1206 Receives an L{Event} object or an object of any of it's subclasses,
1207 and handles any event for which no handler was defined.
1208
1209 - I{unknown_event}
1210
1211 Receives an L{Event} object or an object of any of it's subclasses,
1212 and handles any event unknown to the debugging engine. (This is not
1213 likely to happen unless the Win32 debugging API is changed in future
1214 versions of Windows).
1215
1216 - I{exception}
1217
1218 Receives an L{ExceptionEvent} object and handles any exception for
1219 which no handler was defined. See above for exception handlers.
1220
1221 - I{unknown_exception}
1222
1223 Receives an L{ExceptionEvent} object and handles any exception unknown
1224 to the debugging engine. This usually happens for C++ exceptions, which
1225 are not standardized and may change from one compiler to the next.
1226
1227 Currently we have partial support for C++ exceptions thrown by Microsoft
1228 compilers.
1229
1230 Also see: U{RaiseException()
1231 <http://msdn.microsoft.com/en-us/library/ms680552(VS.85).aspx>}
1232
1233 - I{create_thread}
1234
1235 Receives a L{CreateThreadEvent} object.
1236
1237 - I{create_process}
1238
1239 Receives a L{CreateProcessEvent} object.
1240
1241 - I{exit_thread}
1242
1243 Receives a L{ExitThreadEvent} object.
1244
1245 - I{exit_process}
1246
1247 Receives a L{ExitProcessEvent} object.
1248
1249 - I{load_dll}
1250
1251 Receives a L{LoadDLLEvent} object.
1252
1253 - I{unload_dll}
1254
1255 Receives an L{UnloadDLLEvent} object.
1256
1257 - I{output_string}
1258
1259 Receives an L{OutputDebugStringEvent} object.
1260
1261 - I{rip}
1262
1263 Receives a L{RIPEvent} object.
1264
1265 This is the list of all valid exception handler names
1266 (they all receive an L{ExceptionEvent} object):
1267
1268 - I{access_violation}
1269 - I{array_bounds_exceeded}
1270 - I{breakpoint}
1271 - I{control_c_exit}
1272 - I{datatype_misalignment}
1273 - I{debug_control_c}
1274 - I{float_denormal_operand}
1275 - I{float_divide_by_zero}
1276 - I{float_inexact_result}
1277 - I{float_invalid_operation}
1278 - I{float_overflow}
1279 - I{float_stack_check}
1280 - I{float_underflow}
1281 - I{guard_page}
1282 - I{illegal_instruction}
1283 - I{in_page_error}
1284 - I{integer_divide_by_zero}
1285 - I{integer_overflow}
1286 - I{invalid_disposition}
1287 - I{invalid_handle}
1288 - I{ms_vc_exception}
1289 - I{noncontinuable_exception}
1290 - I{possible_deadlock}
1291 - I{privileged_instruction}
1292 - I{single_step}
1293 - I{stack_overflow}
1294 - I{wow64_breakpoint}
1295
1296
1297
1298 @type apiHooks: dict( str S{->} list( tuple( str, int ) ) )
1299 @cvar apiHooks:
1300 Dictionary that maps module names to lists of
1301 tuples of ( procedure name, parameter count ).
1302
1303 All procedures listed here will be hooked for calls from the debugee.
1304 When this happens, the corresponding event handler can be notified both
1305 when the procedure is entered and when it's left by the debugee.
1306
1307 For example, let's hook the LoadLibraryEx() API call.
1308 This would be the declaration of apiHooks::
1309
1310 from winappdbg import EventHandler
1311 from winappdbg.win32 import *
1312
1313 # (...)
1314
1315 class MyEventHandler (EventHandler):
1316
1317 apiHook = {
1318
1319 "kernel32.dll" : (
1320
1321 # Procedure name Signature
1322 ( "LoadLibraryEx", (PVOID, HANDLE, DWORD) ),
1323
1324 # (more procedures can go here...)
1325 ),
1326
1327 # (more libraries can go here...)
1328 }
1329
1330 # (your method definitions go here...)
1331
1332 Note that all pointer types are treated like void pointers, so your
1333 callback won't get the string or structure pointed to by it, but the
1334 remote memory address instead. This is so to prevent the ctypes library
1335 from being "too helpful" and trying to dereference the pointer. To get
1336 the actual data being pointed to, use one of the L{Process.read}
1337 methods.
1338
1339 Now, to intercept calls to LoadLibraryEx define a method like this in
1340 your event handler class::
1341
1342 def pre_LoadLibraryEx(self, event, ra, lpFilename, hFile, dwFlags):
1343 szFilename = event.get_process().peek_string(lpFilename)
1344
1345 # (...)
1346
1347 Note that the first parameter is always the L{Event} object, and the
1348 second parameter is the return address. The third parameter and above
1349 are the values passed to the hooked function.
1350
1351 Finally, to intercept returns from calls to LoadLibraryEx define a
1352 method like this::
1353
1354 def post_LoadLibraryEx(self, event, retval):
1355 # (...)
1356
1357 The first parameter is the L{Event} object and the second is the
1358 return value from the hooked function.
1359 """
1360
1361
1362
1363
1364 apiHooks = {}
1365
1367 """
1368 Class constructor. Don't forget to call it when subclassing!
1369
1370 Forgetting to call the superclass constructor is a common mistake when
1371 you're new to Python. :)
1372
1373 Example::
1374 class MyEventHandler (EventHandler):
1375
1376 # Override the constructor to use an extra argument.
1377 def __init__(self, myArgument):
1378
1379 # Do something with the argument, like keeping it
1380 # as an instance variable.
1381 self.myVariable = myArgument
1382
1383 # Call the superclass constructor.
1384 super(MyEventHandler, self).__init__()
1385
1386 # The rest of your code below...
1387 """
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399 apiHooks = dict()
1400 for lib, hooks in self.apiHooks.iteritems():
1401 hook_objs = []
1402 for proc, args in hooks:
1403 if type(args) in (int, long):
1404 h = ApiHook(self, lib, proc, paramCount = args)
1405 else:
1406 h = ApiHook(self, lib, proc, signature = args)
1407 hook_objs.append(h)
1408 apiHooks[lib] = hook_objs
1409 self.__apiHooks = apiHooks
1410
1412 """
1413 Get the requested API hooks for the current DLL.
1414
1415 Used by L{__hook_dll} and L{__unhook_dll}.
1416 """
1417 result = []
1418 if self.__apiHooks:
1419 path = event.get_module().get_filename()
1420 if path:
1421 lib_name = PathOperations.pathname_to_filename(path).lower()
1422 for hook_lib, hook_api_list in self.__apiHooks.iteritems():
1423 if hook_lib == lib_name:
1424 result.extend(hook_api_list)
1425 return result
1426
1437
1448
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477 -class EventSift(EventHandler):
1478 """
1479 Event handler that allows you to use customized event handlers for each
1480 process you're attached to.
1481
1482 This makes coding the event handlers much easier, because each instance
1483 will only "know" about one process. So you can code your event handler as
1484 if only one process was being debugged, but your debugger can attach to
1485 multiple processes.
1486
1487 Example::
1488 from winappdbg import Debug, EventHandler, EventSift
1489
1490 # This class was written assuming only one process is attached.
1491 # If you used it directly it would break when attaching to another
1492 # process, or when a child process is spawned.
1493 class MyEventHandler (EventHandler):
1494
1495 def create_process(self, event):
1496 self.first = True
1497 self.name = event.get_process().get_filename()
1498 print "Attached to %s" % self.name
1499
1500 def breakpoint(self, event):
1501 if self.first:
1502 self.first = False
1503 print "First breakpoint reached at %s" % self.name
1504
1505 def exit_process(self, event):
1506 print "Detached from %s" % self.name
1507
1508 # Now when debugging we use the EventSift to be able to work with
1509 # multiple processes while keeping our code simple. :)
1510 if __name__ == "__main__":
1511 handler = EventSift(MyEventHandler)
1512 #handler = MyEventHandler() # try uncommenting this line...
1513 with Debug(handler) as debug:
1514 debug.execl("calc.exe")
1515 debug.execl("notepad.exe")
1516 debug.execl("charmap.exe")
1517 debug.loop()
1518
1519 Subclasses of C{EventSift} can prevent specific event types from
1520 being forwarded by simply defining a method for it. That means your
1521 subclass can handle some event types globally while letting other types
1522 be handled on per-process basis. To forward events manually you can
1523 call C{self.event(event)}.
1524
1525 Example::
1526 class MySift (EventSift):
1527
1528 # Don't forward this event.
1529 def debug_control_c(self, event):
1530 pass
1531
1532 # Handle this event globally without forwarding it.
1533 def output_string(self, event):
1534 print "Debug string: %s" % event.get_debug_string()
1535
1536 # Handle this event globally and then forward it.
1537 def create_process(self, event):
1538 print "New process created, PID: %d" % event.get_pid()
1539 return self.event(event)
1540
1541 # All other events will be forwarded.
1542
1543 Note that overriding the C{event} method would cause no events to be
1544 forwarded at all. To prevent this, call the superclass implementation.
1545
1546 Example::
1547
1548 def we_want_to_forward_this_event(event):
1549 "Use whatever logic you want here..."
1550 # (...return True or False...)
1551
1552 class MySift (EventSift):
1553
1554 def event(self, event):
1555
1556 # If the event matches some custom criteria...
1557 if we_want_to_forward_this_event(event):
1558
1559 # Forward it.
1560 return super(MySift, self).event(event)
1561
1562 # Otherwise, don't.
1563
1564 @type cls: class
1565 @ivar cls:
1566 Event handler class. There will be one instance of this class
1567 per debugged process in the L{forward} dictionary.
1568
1569 @type argv: list
1570 @ivar argv:
1571 Positional arguments to pass to the constructor of L{cls}.
1572
1573 @type argd: list
1574 @ivar argd:
1575 Keyword arguments to pass to the constructor of L{cls}.
1576
1577 @type forward: dict
1578 @ivar forward:
1579 Dictionary that maps each debugged process ID to an instance of L{cls}.
1580 """
1581
1582 - def __init__(self, cls, *argv, **argd):
1583 """
1584 Maintains an instance of your event handler for each process being
1585 debugged, and forwards the events of each process to each corresponding
1586 instance.
1587
1588 @warn: If you subclass L{EventSift} and reimplement this method,
1589 don't forget to call the superclass constructor!
1590
1591 @see: L{event}
1592
1593 @type cls: class
1594 @param cls: Event handler class. This must be the class itself, not an
1595 instance! All additional arguments passed to the constructor of
1596 the event forwarder will be passed on to the constructor of this
1597 class as well.
1598 """
1599 self.cls = cls
1600 self.argv = argv
1601 self.argd = argd
1602 self.forward = dict()
1603 super(EventSift, self).__init__()
1604
1605
1606
1624
1625 - def event(self, event):
1626 """
1627 Forwards events to the corresponding instance of your event handler
1628 for this process.
1629
1630 If you subclass L{EventSift} and reimplement this method, no event
1631 will be forwarded at all unless you call the superclass implementation.
1632
1633 If your filtering is based on the event type, there's a much easier way
1634 to do it: just implement a handler for it.
1635 """
1636 eventCode = event.get_event_code()
1637 pid = event.get_pid()
1638 handler = self.forward.get(pid, None)
1639 if handler is None:
1640 handler = self.cls(*self.argv, **self.argd)
1641 if eventCode != win32.EXIT_PROCESS_DEBUG_EVENT:
1642 self.forward[pid] = handler
1643 elif eventCode == win32.EXIT_PROCESS_DEBUG_EVENT:
1644 del self.forward[pid]
1645 return handler(event)
1646
1650 """
1651 Implements debug event dispatching capabilities.
1652
1653 @group Debugging events:
1654 get_event_handler, set_event_handler, get_handler_method
1655 """
1656
1657
1658
1659
1660 __preEventNotifyCallbackName = {
1661 win32.CREATE_THREAD_DEBUG_EVENT : '_notify_create_thread',
1662 win32.CREATE_PROCESS_DEBUG_EVENT : '_notify_create_process',
1663 win32.LOAD_DLL_DEBUG_EVENT : '_notify_load_dll',
1664 }
1665
1666
1667
1668
1669 __postEventNotifyCallbackName = {
1670 win32.EXIT_THREAD_DEBUG_EVENT : '_notify_exit_thread',
1671 win32.EXIT_PROCESS_DEBUG_EVENT : '_notify_exit_process',
1672 win32.UNLOAD_DLL_DEBUG_EVENT : '_notify_unload_dll',
1673 win32.RIP_EVENT : '_notify_rip',
1674 }
1675
1676
1677
1678
1679 __preExceptionNotifyCallbackName = {
1680 win32.EXCEPTION_BREAKPOINT : '_notify_breakpoint',
1681 win32.EXCEPTION_WX86_BREAKPOINT : '_notify_breakpoint',
1682 win32.EXCEPTION_SINGLE_STEP : '_notify_single_step',
1683 win32.EXCEPTION_GUARD_PAGE : '_notify_guard_page',
1684 win32.DBG_CONTROL_C : '_notify_debug_control_c',
1685 win32.MS_VC_EXCEPTION : '_notify_ms_vc_exception',
1686 }
1687
1688
1689
1690
1691 __postExceptionNotifyCallbackName = {
1692 }
1693
1694 - def __init__(self, eventHandler = None):
1695 """
1696 Event dispatcher.
1697
1698 @type eventHandler: L{EventHandler}
1699 @param eventHandler: (Optional) User-defined event handler.
1700
1701 @raise TypeError: The event handler is of an incorrect type.
1702
1703 @note: The L{eventHandler} parameter may be any callable Python object
1704 (for example a function, or an instance method).
1705 However you'll probably find it more convenient to use an instance
1706 of a subclass of L{EventHandler} here.
1707 """
1708 self.set_event_handler(eventHandler)
1709
1711 """
1712 Get the event handler.
1713
1714 @see: L{set_event_handler}
1715
1716 @rtype: L{EventHandler}
1717 @return: Current event handler object, or C{None}.
1718 """
1719 return self.__eventHandler
1720
1722 """
1723 Set the event handler.
1724
1725 @warn: This is normally not needed. Use with care!
1726
1727 @type eventHandler: L{EventHandler}
1728 @param eventHandler: New event handler object, or C{None}.
1729
1730 @rtype: L{EventHandler}
1731 @return: Previous event handler object, or C{None}.
1732
1733 @raise TypeError: The event handler is of an incorrect type.
1734
1735 @note: The L{eventHandler} parameter may be any callable Python object
1736 (for example a function, or an instance method).
1737 However you'll probably find it more convenient to use an instance
1738 of a subclass of L{EventHandler} here.
1739 """
1740 if eventHandler is not None and not callable(eventHandler):
1741 raise TypeError("Event handler must be a callable object")
1742 try:
1743 wrong_type = issubclass(eventHandler, EventHandler)
1744 except TypeError:
1745 wrong_type = False
1746 if wrong_type:
1747 classname = str(eventHandler)
1748 msg = "Event handler must be an instance of class %s"
1749 msg += "rather than the %s class itself. (Missing parens?)"
1750 msg = msg % (classname, classname)
1751 raise TypeError(msg)
1752 try:
1753 previous = self.__eventHandler
1754 except AttributeError:
1755 previous = None
1756 self.__eventHandler = eventHandler
1757 return previous
1758
1759 @staticmethod
1761 """
1762 Retrieves the appropriate callback method from an L{EventHandler}
1763 instance for the given L{Event} object.
1764
1765 @type eventHandler: L{EventHandler}
1766 @param eventHandler:
1767 Event handler object whose methods we are examining.
1768
1769 @type event: L{Event}
1770 @param event: Debugging event to be handled.
1771
1772 @type fallback: callable
1773 @param fallback: (Optional) If no suitable method is found in the
1774 L{EventHandler} instance, return this value.
1775
1776 @rtype: callable
1777 @return: Bound method that will handle the debugging event.
1778 Returns C{None} if no such method is defined.
1779 """
1780 eventCode = event.get_event_code()
1781 method = getattr(eventHandler, 'event', fallback)
1782 if eventCode == win32.EXCEPTION_DEBUG_EVENT:
1783 method = getattr(eventHandler, 'exception', method)
1784 method = getattr(eventHandler, event.eventMethod, method)
1785 return method
1786
1788 """
1789 Sends event notifications to the L{Debug} object and
1790 the L{EventHandler} object provided by the user.
1791
1792 The L{Debug} object will forward the notifications to it's contained
1793 snapshot objects (L{System}, L{Process}, L{Thread} and L{Module}) when
1794 appropriate.
1795
1796 @warning: This method is called automatically from L{Debug.dispatch}.
1797
1798 @see: L{Debug.cont}, L{Debug.loop}, L{Debug.wait}
1799
1800 @type event: L{Event}
1801 @param event: Event object passed to L{Debug.dispatch}.
1802
1803 @raise WindowsError: Raises an exception on error.
1804 """
1805 returnValue = None
1806 bCallHandler = True
1807 pre_handler = None
1808 post_handler = None
1809 eventCode = event.get_event_code()
1810
1811
1812
1813 if eventCode == win32.EXCEPTION_DEBUG_EVENT:
1814 exceptionCode = event.get_exception_code()
1815 pre_name = self.__preExceptionNotifyCallbackName.get(
1816 exceptionCode, None)
1817 post_name = self.__postExceptionNotifyCallbackName.get(
1818 exceptionCode, None)
1819 if pre_name is not None:
1820 pre_handler = getattr(self, pre_name, None)
1821 if post_name is not None:
1822 post_handler = getattr(self, post_name, None)
1823
1824
1825
1826
1827 if pre_handler is None:
1828 pre_name = self.__preEventNotifyCallbackName.get(eventCode, None)
1829 if pre_name is not None:
1830 pre_handler = getattr(self, pre_name, pre_handler)
1831
1832
1833
1834
1835 if post_handler is None:
1836 post_name = self.__postEventNotifyCallbackName.get(eventCode, None)
1837 if post_name is not None:
1838 post_handler = getattr(self, post_name, post_handler)
1839
1840
1841
1842 if pre_handler is not None:
1843 bCallHandler = pre_handler(event)
1844
1845
1846
1847 try:
1848 if bCallHandler and self.__eventHandler is not None:
1849 try:
1850 returnValue = self.__eventHandler(event)
1851 except Exception, e:
1852 msg = ("Event handler pre-callback %r"
1853 " raised an exception: %s")
1854 msg = msg % (self.__eventHandler, traceback.format_exc(e))
1855 warnings.warn(msg, EventCallbackWarning)
1856 returnValue = None
1857
1858
1859
1860 finally:
1861 if post_handler is not None:
1862 post_handler(event)
1863
1864
1865
1866 return returnValue
1867