1#!~/.wine/drive_c/Python25/python.exe
2# -*- coding: utf-8 -*-
3
4# Copyright (c) 2009-2014, Mario Vilas
5# All rights reserved.
6#
7# Redistribution and use in source and binary forms, with or without
8# modification, are permitted provided that the following conditions are met:
9#
10#     * Redistributions of source code must retain the above copyright notice,
11#       this list of conditions and the following disclaimer.
12#     * Redistributions in binary form must reproduce the above copyright
13#       notice,this list of conditions and the following disclaimer in the
14#       documentation and/or other materials provided with the distribution.
15#     * Neither the name of the copyright holder nor the names of its
16#       contributors may be used to endorse or promote products derived from
17#       this software without specific prior written permission.
18#
19# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29# POSSIBILITY OF SUCH DAMAGE.
30
31"""
32Event 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$"
59
60__all__ = [
61            # Factory of Event objects and all of it's subclasses.
62            # Users should not need to instance Event objects directly.
63            'EventFactory',
64
65            # Event dispatcher used internally by the Debug class.
66            'EventDispatcher',
67
68            # Base classes for user-defined event handlers.
69            'EventHandler',
70            'EventSift',
71
72            # Warning for uncaught exceptions on event callbacks.
73            'EventCallbackWarning',
74
75            # Dummy event object that can be used as a placeholder.
76            # It's never returned by the EventFactory.
77            'NoEvent',
78
79            # Base class for event objects.
80            'Event',
81
82            # Event objects.
83            'CreateProcessEvent',
84            'CreateThreadEvent',
85            'ExitProcessEvent',
86            'ExitThreadEvent',
87            'LoadDLLEvent',
88            'UnloadDLLEvent',
89            'OutputDebugStringEvent',
90            'RIPEvent',
91            'ExceptionEvent'
92          ]
93
94from winappdbg import win32
95from winappdbg import compat
96from winappdbg.win32 import FileHandle, ProcessHandle, ThreadHandle
97from winappdbg.breakpoint import ApiHook
98from winappdbg.module import Module
99from winappdbg.thread import Thread
100from winappdbg.process import Process
101from winappdbg.textio import HexDump
102from winappdbg.util import StaticClass, PathOperations
103
104import sys
105import ctypes
106import warnings
107import traceback
108
109#==============================================================================
110
111class EventCallbackWarning (RuntimeWarning):
112    """
113    This warning is issued when an uncaught exception was raised by a
114    user-defined event handler.
115    """
116
117#==============================================================================
118
119class Event (object):
120    """
121    Event object.
122
123    @type eventMethod: str
124    @cvar eventMethod:
125        Method name to call when using L{EventHandler} subclasses.
126        Used internally.
127
128    @type eventName: str
129    @cvar eventName:
130        User-friendly name of the event.
131
132    @type eventDescription: str
133    @cvar eventDescription:
134        User-friendly description of the event.
135
136    @type debug: L{Debug}
137    @ivar debug:
138        Debug object that received the event.
139
140    @type raw: L{DEBUG_EVENT}
141    @ivar raw:
142        Raw DEBUG_EVENT structure as used by the Win32 API.
143
144    @type continueStatus: int
145    @ivar continueStatus:
146        Continue status to pass to L{win32.ContinueDebugEvent}.
147    """
148
149    eventMethod      = 'unknown_event'
150    eventName        = 'Unknown event'
151    eventDescription = 'A debug event of an unknown type has occured.'
152
153    def __init__(self, debug, raw):
154        """
155        @type  debug: L{Debug}
156        @param debug: Debug object that received the event.
157
158        @type  raw: L{DEBUG_EVENT}
159        @param raw: Raw DEBUG_EVENT structure as used by the Win32 API.
160        """
161        self.debug          = debug
162        self.raw            = raw
163        self.continueStatus = win32.DBG_EXCEPTION_NOT_HANDLED
164
165##    @property
166##    def debug(self):
167##        """
168##        @rtype  debug: L{Debug}
169##        @return debug:
170##            Debug object that received the event.
171##        """
172##        return self.__debug()
173
174    def get_event_name(self):
175        """
176        @rtype:  str
177        @return: User-friendly name of the event.
178        """
179        return self.eventName
180
181    def get_event_description(self):
182        """
183        @rtype:  str
184        @return: User-friendly description of the event.
185        """
186        return self.eventDescription
187
188    def get_event_code(self):
189        """
190        @rtype:  int
191        @return: Debug event code as defined in the Win32 API.
192        """
193        return self.raw.dwDebugEventCode
194
195##    # Compatibility with version 1.0
196##    # XXX to be removed in version 1.4
197##    def get_code(self):
198##        """
199##        Alias of L{get_event_code} for backwards compatibility
200##        with WinAppDbg version 1.0.
201##        Will be phased out in the next version.
202##
203##        @rtype:  int
204##        @return: Debug event code as defined in the Win32 API.
205##        """
206##        return self.get_event_code()
207
208    def get_pid(self):
209        """
210        @see: L{get_process}
211
212        @rtype:  int
213        @return: Process global ID where the event occured.
214        """
215        return self.raw.dwProcessId
216
217    def get_tid(self):
218        """
219        @see: L{get_thread}
220
221        @rtype:  int
222        @return: Thread global ID where the event occured.
223        """
224        return self.raw.dwThreadId
225
226    def get_process(self):
227        """
228        @see: L{get_pid}
229
230        @rtype:  L{Process}
231        @return: Process where the event occured.
232        """
233        pid     = self.get_pid()
234        system  = self.debug.system
235        if system.has_process(pid):
236            process = system.get_process(pid)
237        else:
238            # XXX HACK
239            # The process object was missing for some reason, so make a new one.
240            process = Process(pid)
241            system._add_process(process)
242##            process.scan_threads()    # not needed
243            process.scan_modules()
244        return process
245
246    def get_thread(self):
247        """
248        @see: L{get_tid}
249
250        @rtype:  L{Thread}
251        @return: Thread where the event occured.
252        """
253        tid     = self.get_tid()
254        process = self.get_process()
255        if process.has_thread(tid):
256            thread = process.get_thread(tid)
257        else:
258            # XXX HACK
259            # The thread object was missing for some reason, so make a new one.
260            thread = Thread(tid)
261            process._add_thread(thread)
262        return thread
263
264#==============================================================================
265
266class NoEvent (Event):
267    """
268    No event.
269
270    Dummy L{Event} object that can be used as a placeholder when no debug
271    event has occured yet. It's never returned by the L{EventFactory}.
272    """
273
274    eventMethod      = 'no_event'
275    eventName        = 'No event'
276    eventDescription = 'No debug event has occured.'
277
278    def __init__(self, debug, raw = None):
279        Event.__init__(self, debug, raw)
280
281    def __len__(self):
282        """
283        Always returns C{0}, so when evaluating the object as a boolean it's
284        always C{False}. This prevents L{Debug.cont} from trying to continue
285        a dummy event.
286        """
287        return 0
288
289    def get_event_code(self):
290        return -1
291
292    def get_pid(self):
293        return -1
294
295    def get_tid(self):
296        return -1
297
298    def get_process(self):
299        return Process(self.get_pid())
300
301    def get_thread(self):
302        return Thread(self.get_tid())
303
304#==============================================================================
305
306class ExceptionEvent (Event):
307    """
308    Exception event.
309
310    @type exceptionName: dict( int S{->} str )
311    @cvar exceptionName:
312        Mapping of exception constants to their names.
313
314    @type exceptionDescription: dict( int S{->} str )
315    @cvar exceptionDescription:
316        Mapping of exception constants to user-friendly strings.
317
318    @type breakpoint: L{Breakpoint}
319    @ivar breakpoint:
320        If the exception was caused by one of our breakpoints, this member
321        contains a reference to the breakpoint object. Otherwise it's not
322        defined. It should only be used from the condition or action callback
323        routines, instead of the event handler.
324
325    @type hook: L{Hook}
326    @ivar hook:
327        If the exception was caused by a function hook, this member contains a
328        reference to the hook object. Otherwise it's not defined. It should
329        only be used from the hook callback routines, instead of the event
330        handler.
331    """
332
333    eventName        = 'Exception event'
334    eventDescription = 'An exception was raised by the debugee.'
335
336    __exceptionMethod = {
337        win32.EXCEPTION_ACCESS_VIOLATION          : 'access_violation',
338        win32.EXCEPTION_ARRAY_BOUNDS_EXCEEDED     : 'array_bounds_exceeded',
339        win32.EXCEPTION_BREAKPOINT                : 'breakpoint',
340        win32.EXCEPTION_DATATYPE_MISALIGNMENT     : 'datatype_misalignment',
341        win32.EXCEPTION_FLT_DENORMAL_OPERAND      : 'float_denormal_operand',
342        win32.EXCEPTION_FLT_DIVIDE_BY_ZERO        : 'float_divide_by_zero',
343        win32.EXCEPTION_FLT_INEXACT_RESULT        : 'float_inexact_result',
344        win32.EXCEPTION_FLT_INVALID_OPERATION     : 'float_invalid_operation',
345        win32.EXCEPTION_FLT_OVERFLOW              : 'float_overflow',
346        win32.EXCEPTION_FLT_STACK_CHECK           : 'float_stack_check',
347        win32.EXCEPTION_FLT_UNDERFLOW             : 'float_underflow',
348        win32.EXCEPTION_ILLEGAL_INSTRUCTION       : 'illegal_instruction',
349        win32.EXCEPTION_IN_PAGE_ERROR             : 'in_page_error',
350        win32.EXCEPTION_INT_DIVIDE_BY_ZERO        : 'integer_divide_by_zero',
351        win32.EXCEPTION_INT_OVERFLOW              : 'integer_overflow',
352        win32.EXCEPTION_INVALID_DISPOSITION       : 'invalid_disposition',
353        win32.EXCEPTION_NONCONTINUABLE_EXCEPTION  : 'noncontinuable_exception',
354        win32.EXCEPTION_PRIV_INSTRUCTION          : 'privileged_instruction',
355        win32.EXCEPTION_SINGLE_STEP               : 'single_step',
356        win32.EXCEPTION_STACK_OVERFLOW            : 'stack_overflow',
357        win32.EXCEPTION_GUARD_PAGE                : 'guard_page',
358        win32.EXCEPTION_INVALID_HANDLE            : 'invalid_handle',
359        win32.EXCEPTION_POSSIBLE_DEADLOCK         : 'possible_deadlock',
360        win32.EXCEPTION_WX86_BREAKPOINT           : 'wow64_breakpoint',
361        win32.CONTROL_C_EXIT                      : 'control_c_exit',
362        win32.DBG_CONTROL_C                       : 'debug_control_c',
363        win32.MS_VC_EXCEPTION                     : 'ms_vc_exception',
364    }
365
366    __exceptionName = {
367        win32.EXCEPTION_ACCESS_VIOLATION          : 'EXCEPTION_ACCESS_VIOLATION',
368        win32.EXCEPTION_ARRAY_BOUNDS_EXCEEDED     : 'EXCEPTION_ARRAY_BOUNDS_EXCEEDED',
369        win32.EXCEPTION_BREAKPOINT                : 'EXCEPTION_BREAKPOINT',
370        win32.EXCEPTION_DATATYPE_MISALIGNMENT     : 'EXCEPTION_DATATYPE_MISALIGNMENT',
371        win32.EXCEPTION_FLT_DENORMAL_OPERAND      : 'EXCEPTION_FLT_DENORMAL_OPERAND',
372        win32.EXCEPTION_FLT_DIVIDE_BY_ZERO        : 'EXCEPTION_FLT_DIVIDE_BY_ZERO',
373        win32.EXCEPTION_FLT_INEXACT_RESULT        : 'EXCEPTION_FLT_INEXACT_RESULT',
374        win32.EXCEPTION_FLT_INVALID_OPERATION     : 'EXCEPTION_FLT_INVALID_OPERATION',
375        win32.EXCEPTION_FLT_OVERFLOW              : 'EXCEPTION_FLT_OVERFLOW',
376        win32.EXCEPTION_FLT_STACK_CHECK           : 'EXCEPTION_FLT_STACK_CHECK',
377        win32.EXCEPTION_FLT_UNDERFLOW             : 'EXCEPTION_FLT_UNDERFLOW',
378        win32.EXCEPTION_ILLEGAL_INSTRUCTION       : 'EXCEPTION_ILLEGAL_INSTRUCTION',
379        win32.EXCEPTION_IN_PAGE_ERROR             : 'EXCEPTION_IN_PAGE_ERROR',
380        win32.EXCEPTION_INT_DIVIDE_BY_ZERO        : 'EXCEPTION_INT_DIVIDE_BY_ZERO',
381        win32.EXCEPTION_INT_OVERFLOW              : 'EXCEPTION_INT_OVERFLOW',
382        win32.EXCEPTION_INVALID_DISPOSITION       : 'EXCEPTION_INVALID_DISPOSITION',
383        win32.EXCEPTION_NONCONTINUABLE_EXCEPTION  : 'EXCEPTION_NONCONTINUABLE_EXCEPTION',
384        win32.EXCEPTION_PRIV_INSTRUCTION          : 'EXCEPTION_PRIV_INSTRUCTION',
385        win32.EXCEPTION_SINGLE_STEP               : 'EXCEPTION_SINGLE_STEP',
386        win32.EXCEPTION_STACK_OVERFLOW            : 'EXCEPTION_STACK_OVERFLOW',
387        win32.EXCEPTION_GUARD_PAGE                : 'EXCEPTION_GUARD_PAGE',
388        win32.EXCEPTION_INVALID_HANDLE            : 'EXCEPTION_INVALID_HANDLE',
389        win32.EXCEPTION_POSSIBLE_DEADLOCK         : 'EXCEPTION_POSSIBLE_DEADLOCK',
390        win32.EXCEPTION_WX86_BREAKPOINT           : 'EXCEPTION_WX86_BREAKPOINT',
391        win32.CONTROL_C_EXIT                      : 'CONTROL_C_EXIT',
392        win32.DBG_CONTROL_C                       : 'DBG_CONTROL_C',
393        win32.MS_VC_EXCEPTION                     : 'MS_VC_EXCEPTION',
394    }
395
396    __exceptionDescription = {
397        win32.EXCEPTION_ACCESS_VIOLATION          : 'Access violation',
398        win32.EXCEPTION_ARRAY_BOUNDS_EXCEEDED     : 'Array bounds exceeded',
399        win32.EXCEPTION_BREAKPOINT                : 'Breakpoint',
400        win32.EXCEPTION_DATATYPE_MISALIGNMENT     : 'Datatype misalignment',
401        win32.EXCEPTION_FLT_DENORMAL_OPERAND      : 'Float denormal operand',
402        win32.EXCEPTION_FLT_DIVIDE_BY_ZERO        : 'Float divide by zero',
403        win32.EXCEPTION_FLT_INEXACT_RESULT        : 'Float inexact result',
404        win32.EXCEPTION_FLT_INVALID_OPERATION     : 'Float invalid operation',
405        win32.EXCEPTION_FLT_OVERFLOW              : 'Float overflow',
406        win32.EXCEPTION_FLT_STACK_CHECK           : 'Float stack check',
407        win32.EXCEPTION_FLT_UNDERFLOW             : 'Float underflow',
408        win32.EXCEPTION_ILLEGAL_INSTRUCTION       : 'Illegal instruction',
409        win32.EXCEPTION_IN_PAGE_ERROR             : 'In-page error',
410        win32.EXCEPTION_INT_DIVIDE_BY_ZERO        : 'Integer divide by zero',
411        win32.EXCEPTION_INT_OVERFLOW              : 'Integer overflow',
412        win32.EXCEPTION_INVALID_DISPOSITION       : 'Invalid disposition',
413        win32.EXCEPTION_NONCONTINUABLE_EXCEPTION  : 'Noncontinuable exception',
414        win32.EXCEPTION_PRIV_INSTRUCTION          : 'Privileged instruction',
415        win32.EXCEPTION_SINGLE_STEP               : 'Single step event',
416        win32.EXCEPTION_STACK_OVERFLOW            : 'Stack limits overflow',
417        win32.EXCEPTION_GUARD_PAGE                : 'Guard page hit',
418        win32.EXCEPTION_INVALID_HANDLE            : 'Invalid handle',
419        win32.EXCEPTION_POSSIBLE_DEADLOCK         : 'Possible deadlock',
420        win32.EXCEPTION_WX86_BREAKPOINT           : 'WOW64 breakpoint',
421        win32.CONTROL_C_EXIT                      : 'Control-C exit',
422        win32.DBG_CONTROL_C                       : 'Debug Control-C',
423        win32.MS_VC_EXCEPTION                     : 'Microsoft Visual C++ exception',
424    }
425
426    @property
427    def eventMethod(self):
428        return self.__exceptionMethod.get(
429                                self.get_exception_code(), 'unknown_exception')
430
431    def get_exception_name(self):
432        """
433        @rtype:  str
434        @return: Name of the exception as defined by the Win32 API.
435        """
436        code = self.get_exception_code()
437        unk  = HexDump.integer(code)
438        return self.__exceptionName.get(code, unk)
439
440    def get_exception_description(self):
441        """
442        @rtype:  str
443        @return: User-friendly name of the exception.
444        """
445        code = self.get_exception_code()
446        description = self.__exceptionDescription.get(code, None)
447        if description is None:
448            try:
449                description = 'Exception code %s (%s)'
450                description = description % (HexDump.integer(code),
451                                             ctypes.FormatError(code))
452            except OverflowError:
453                description = 'Exception code %s' % HexDump.integer(code)
454        return description
455
456    def is_first_chance(self):
457        """
458        @rtype:  bool
459        @return: C{True} for first chance exceptions, C{False} for last chance.
460        """
461        return self.raw.u.Exception.dwFirstChance != 0
462
463    def is_last_chance(self):
464        """
465        @rtype:  bool
466        @return: The opposite of L{is_first_chance}.
467        """
468        return not self.is_first_chance()
469
470    def is_noncontinuable(self):
471        """
472        @see: U{http://msdn.microsoft.com/en-us/library/aa363082(VS.85).aspx}
473
474        @rtype:  bool
475        @return: C{True} if the exception is noncontinuable,
476            C{False} otherwise.
477
478            Attempting to continue a noncontinuable exception results in an
479            EXCEPTION_NONCONTINUABLE_EXCEPTION exception to be raised.
480        """
481        return bool( self.raw.u.Exception.ExceptionRecord.ExceptionFlags & \
482                                            win32.EXCEPTION_NONCONTINUABLE )
483
484    def is_continuable(self):
485        """
486        @rtype:  bool
487        @return: The opposite of L{is_noncontinuable}.
488        """
489        return not self.is_noncontinuable()
490
491    def is_user_defined_exception(self):
492        """
493        Determines if this is an user-defined exception. User-defined
494        exceptions may contain any exception code that is not system reserved.
495
496        Often the exception code is also a valid Win32 error code, but that's
497        up to the debugged application.
498
499        @rtype:  bool
500        @return: C{True} if the exception is user-defined, C{False} otherwise.
501        """
502        return self.get_exception_code() & 0x10000000 == 0
503
504    def is_system_defined_exception(self):
505        """
506        @rtype:  bool
507        @return: The opposite of L{is_user_defined_exception}.
508        """
509        return not self.is_user_defined_exception()
510
511    def get_exception_code(self):
512        """
513        @rtype:  int
514        @return: Exception code as defined by the Win32 API.
515        """
516        return self.raw.u.Exception.ExceptionRecord.ExceptionCode
517
518    def get_exception_address(self):
519        """
520        @rtype:  int
521        @return: Memory address where the exception occured.
522        """
523        address = self.raw.u.Exception.ExceptionRecord.ExceptionAddress
524        if address is None:
525            address = 0
526        return address
527
528    def get_exception_information(self, index):
529        """
530        @type  index: int
531        @param index: Index into the exception information block.
532
533        @rtype:  int
534        @return: Exception information DWORD.
535        """
536        if index < 0 or index > win32.EXCEPTION_MAXIMUM_PARAMETERS:
537            raise IndexError("Array index out of range: %s" % repr(index))
538        info = self.raw.u.Exception.ExceptionRecord.ExceptionInformation
539        value = info[index]
540        if value is None:
541            value = 0
542        return value
543
544    def get_exception_information_as_list(self):
545        """
546        @rtype:  list( int )
547        @return: Exception information block.
548        """
549        info = self.raw.u.Exception.ExceptionRecord.ExceptionInformation
550        data = list()
551        for index in compat.xrange(0, win32.EXCEPTION_MAXIMUM_PARAMETERS):
552            value = info[index]
553            if value is None:
554                value = 0
555            data.append(value)
556        return data
557
558    def get_fault_type(self):
559        """
560        @rtype:  int
561        @return: Access violation type.
562            Should be one of the following constants:
563
564             - L{win32.EXCEPTION_READ_FAULT}
565             - L{win32.EXCEPTION_WRITE_FAULT}
566             - L{win32.EXCEPTION_EXECUTE_FAULT}
567
568        @note: This method is only meaningful for access violation exceptions,
569            in-page memory error exceptions and guard page exceptions.
570
571        @raise NotImplementedError: Wrong kind of exception.
572        """
573        if self.get_exception_code() not in (win32.EXCEPTION_ACCESS_VIOLATION,
574                    win32.EXCEPTION_IN_PAGE_ERROR, win32.EXCEPTION_GUARD_PAGE):
575            msg = "This method is not meaningful for %s."
576            raise NotImplementedError(msg % self.get_exception_name())
577        return self.get_exception_information(0)
578
579    def get_fault_address(self):
580        """
581        @rtype:  int
582        @return: Access violation memory address.
583
584        @note: This method is only meaningful for access violation exceptions,
585            in-page memory error exceptions and guard page exceptions.
586
587        @raise NotImplementedError: Wrong kind of exception.
588        """
589        if self.get_exception_code() not in (win32.EXCEPTION_ACCESS_VIOLATION,
590                    win32.EXCEPTION_IN_PAGE_ERROR, win32.EXCEPTION_GUARD_PAGE):
591            msg = "This method is not meaningful for %s."
592            raise NotImplementedError(msg % self.get_exception_name())
593        return self.get_exception_information(1)
594
595    def get_ntstatus_code(self):
596        """
597        @rtype:  int
598        @return: NTSTATUS status code that caused the exception.
599
600        @note: This method is only meaningful for in-page memory error
601            exceptions.
602
603        @raise NotImplementedError: Not an in-page memory error.
604        """
605        if self.get_exception_code() != win32.EXCEPTION_IN_PAGE_ERROR:
606            msg = "This method is only meaningful "\
607                  "for in-page memory error exceptions."
608            raise NotImplementedError(msg)
609        return self.get_exception_information(2)
610
611    def is_nested(self):
612        """
613        @rtype:  bool
614        @return: Returns C{True} if there are additional exception records
615            associated with this exception. This would mean the exception
616            is nested, that is, it was triggered while trying to handle
617            at least one previous exception.
618        """
619        return bool(self.raw.u.Exception.ExceptionRecord.ExceptionRecord)
620
621    def get_raw_exception_record_list(self):
622        """
623        Traverses the exception record linked list and builds a Python list.
624
625        Nested exception records are received for nested exceptions. This
626        happens when an exception is raised in the debugee while trying to
627        handle a previous exception.
628
629        @rtype:  list( L{win32.EXCEPTION_RECORD} )
630        @return:
631            List of raw exception record structures as used by the Win32 API.
632
633            There is always at least one exception record, so the list is
634            never empty. All other methods of this class read from the first
635            exception record only, that is, the most recent exception.
636        """
637        # The first EXCEPTION_RECORD is contained in EXCEPTION_DEBUG_INFO.
638        # The remaining EXCEPTION_RECORD structures are linked by pointers.
639        nested = list()
640        record = self.raw.u.Exception
641        while True:
642            record = record.ExceptionRecord
643            if not record:
644                break
645            nested.append(record)
646        return nested
647
648    def get_nested_exceptions(self):
649        """
650        Traverses the exception record linked list and builds a Python list.
651
652        Nested exception records are received for nested exceptions. This
653        happens when an exception is raised in the debugee while trying to
654        handle a previous exception.
655
656        @rtype:  list( L{ExceptionEvent} )
657        @return:
658            List of ExceptionEvent objects representing each exception record
659            found in this event.
660
661            There is always at least one exception record, so the list is
662            never empty. All other methods of this class read from the first
663            exception record only, that is, the most recent exception.
664        """
665        # The list always begins with ourselves.
666        # Just put a reference to "self" as the first element,
667        # and start looping from the second exception record.
668        nested = [ self ]
669        raw = self.raw
670        dwDebugEventCode = raw.dwDebugEventCode
671        dwProcessId      = raw.dwProcessId
672        dwThreadId       = raw.dwThreadId
673        dwFirstChance    = raw.u.Exception.dwFirstChance
674        record           = raw.u.Exception.ExceptionRecord
675        while True:
676            record = record.ExceptionRecord
677            if not record:
678                break
679            raw = win32.DEBUG_EVENT()
680            raw.dwDebugEventCode            = dwDebugEventCode
681            raw.dwProcessId                 = dwProcessId
682            raw.dwThreadId                  = dwThreadId
683            raw.u.Exception.ExceptionRecord = record
684            raw.u.Exception.dwFirstChance   = dwFirstChance
685            event = EventFactory.get(self.debug, raw)
686            nested.append(event)
687        return nested
688
689#==============================================================================
690
691class CreateThreadEvent (Event):
692    """
693    Thread creation event.
694    """
695
696    eventMethod      = 'create_thread'
697    eventName        = 'Thread creation event'
698    eventDescription = 'A new thread has started.'
699
700    def get_thread_handle(self):
701        """
702        @rtype:  L{ThreadHandle}
703        @return: Thread handle received from the system.
704            Returns C{None} if the handle is not available.
705        """
706        # The handle doesn't need to be closed.
707        # See http://msdn.microsoft.com/en-us/library/ms681423(VS.85).aspx
708        hThread = self.raw.u.CreateThread.hThread
709        if hThread in (0, win32.NULL, win32.INVALID_HANDLE_VALUE):
710            hThread = None
711        else:
712            hThread = ThreadHandle(hThread, False, win32.THREAD_ALL_ACCESS)
713        return hThread
714
715    def get_teb(self):
716        """
717        @rtype:  int
718        @return: Pointer to the TEB.
719        """
720        return self.raw.u.CreateThread.lpThreadLocalBase
721
722    def get_start_address(self):
723        """
724        @rtype:  int
725        @return: Pointer to the first instruction to execute in this thread.
726
727            Returns C{NULL} when the debugger attached to a process
728            and the thread already existed.
729
730            See U{http://msdn.microsoft.com/en-us/library/ms679295(VS.85).aspx}
731        """
732        return self.raw.u.CreateThread.lpStartAddress
733
734#==============================================================================
735
736class CreateProcessEvent (Event):
737    """
738    Process creation event.
739    """
740
741    eventMethod      = 'create_process'
742    eventName        = 'Process creation event'
743    eventDescription = 'A new process has started.'
744
745    def get_file_handle(self):
746        """
747        @rtype:  L{FileHandle} or None
748        @return: File handle to the main module, received from the system.
749            Returns C{None} if the handle is not available.
750        """
751        # This handle DOES need to be closed.
752        # Therefore we must cache it so it doesn't
753        # get closed after the first call.
754        try:
755            hFile = self.__hFile
756        except AttributeError:
757            hFile = self.raw.u.CreateProcessInfo.hFile
758            if hFile in (0, win32.NULL, win32.INVALID_HANDLE_VALUE):
759                hFile = None
760            else:
761                hFile = FileHandle(hFile, True)
762            self.__hFile = hFile
763        return hFile
764
765    def get_process_handle(self):
766        """
767        @rtype:  L{ProcessHandle}
768        @return: Process handle received from the system.
769            Returns C{None} if the handle is not available.
770        """
771        # The handle doesn't need to be closed.
772        # See http://msdn.microsoft.com/en-us/library/ms681423(VS.85).aspx
773        hProcess = self.raw.u.CreateProcessInfo.hProcess
774        if hProcess in (0, win32.NULL, win32.INVALID_HANDLE_VALUE):
775            hProcess = None
776        else:
777            hProcess = ProcessHandle(hProcess, False, win32.PROCESS_ALL_ACCESS)
778        return hProcess
779
780    def get_thread_handle(self):
781        """
782        @rtype:  L{ThreadHandle}
783        @return: Thread handle received from the system.
784            Returns C{None} if the handle is not available.
785        """
786        # The handle doesn't need to be closed.
787        # See http://msdn.microsoft.com/en-us/library/ms681423(VS.85).aspx
788        hThread = self.raw.u.CreateProcessInfo.hThread
789        if hThread in (0, win32.NULL, win32.INVALID_HANDLE_VALUE):
790            hThread = None
791        else:
792            hThread = ThreadHandle(hThread, False, win32.THREAD_ALL_ACCESS)
793        return hThread
794
795    def get_start_address(self):
796        """
797        @rtype:  int
798        @return: Pointer to the first instruction to execute in this process.
799
800            Returns C{NULL} when the debugger attaches to a process.
801
802            See U{http://msdn.microsoft.com/en-us/library/ms679295(VS.85).aspx}
803        """
804        return self.raw.u.CreateProcessInfo.lpStartAddress
805
806    def get_image_base(self):
807        """
808        @rtype:  int
809        @return: Base address of the main module.
810        @warn: This value is taken from the PE file
811            and may be incorrect because of ASLR!
812        """
813        # TODO try to calculate the real value when ASLR is active.
814        return self.raw.u.CreateProcessInfo.lpBaseOfImage
815
816    def get_teb(self):
817        """
818        @rtype:  int
819        @return: Pointer to the TEB.
820        """
821        return self.raw.u.CreateProcessInfo.lpThreadLocalBase
822
823    def get_debug_info(self):
824        """
825        @rtype:  str
826        @return: Debugging information.
827        """
828        raw  = self.raw.u.CreateProcessInfo
829        ptr  = raw.lpBaseOfImage + raw.dwDebugInfoFileOffset
830        size = raw.nDebugInfoSize
831        data = self.get_process().peek(ptr, size)
832        if len(data) == size:
833            return data
834        return None
835
836    def get_filename(self):
837        """
838        @rtype:  str, None
839        @return: This method does it's best to retrieve the filename to
840        the main module of the process. However, sometimes that's not
841        possible, and C{None} is returned instead.
842        """
843
844        # Try to get the filename from the file handle.
845        szFilename = None
846        hFile = self.get_file_handle()
847        if hFile:
848            szFilename = hFile.get_filename()
849        if not szFilename:
850
851            # Try to get it from CREATE_PROCESS_DEBUG_INFO.lpImageName
852            # It's NULL or *NULL most of the times, see MSDN:
853            # http://msdn.microsoft.com/en-us/library/ms679286(VS.85).aspx
854            aProcess = self.get_process()
855            lpRemoteFilenamePtr = self.raw.u.CreateProcessInfo.lpImageName
856            if lpRemoteFilenamePtr:
857                lpFilename  = aProcess.peek_uint(lpRemoteFilenamePtr)
858                fUnicode    = bool( self.raw.u.CreateProcessInfo.fUnicode )
859                szFilename  = aProcess.peek_string(lpFilename, fUnicode)
860
861                # XXX TODO
862                # Sometimes the filename is relative (ntdll.dll, kernel32.dll).
863                # It could be converted to an absolute pathname (SearchPath).
864
865            # Try to get it from Process.get_image_name().
866            if not szFilename:
867                szFilename = aProcess.get_image_name()
868
869        # Return the filename, or None on error.
870        return szFilename
871
872    def get_module_base(self):
873        """
874        @rtype:  int
875        @return: Base address of the main module.
876        """
877        return self.get_image_base()
878
879    def get_module(self):
880        """
881        @rtype:  L{Module}
882        @return: Main module of the process.
883        """
884        return self.get_process().get_module( self.get_module_base() )
885
886#==============================================================================
887
888class ExitThreadEvent (Event):
889    """
890    Thread termination event.
891    """
892
893    eventMethod      = 'exit_thread'
894    eventName        = 'Thread termination event'
895    eventDescription = 'A thread has finished executing.'
896
897    def get_exit_code(self):
898        """
899        @rtype:  int
900        @return: Exit code of the thread.
901        """
902        return self.raw.u.ExitThread.dwExitCode
903
904#==============================================================================
905
906class ExitProcessEvent (Event):
907    """
908    Process termination event.
909    """
910
911    eventMethod      = 'exit_process'
912    eventName        = 'Process termination event'
913    eventDescription = 'A process has finished executing.'
914
915    def get_exit_code(self):
916        """
917        @rtype:  int
918        @return: Exit code of the process.
919        """
920        return self.raw.u.ExitProcess.dwExitCode
921
922    def get_filename(self):
923        """
924        @rtype:  None or str
925        @return: Filename of the main module.
926            C{None} if the filename is unknown.
927        """
928        return self.get_module().get_filename()
929
930    def get_image_base(self):
931        """
932        @rtype:  int
933        @return: Base address of the main module.
934        """
935        return self.get_module_base()
936
937    def get_module_base(self):
938        """
939        @rtype:  int
940        @return: Base address of the main module.
941        """
942        return self.get_module().get_base()
943
944    def get_module(self):
945        """
946        @rtype:  L{Module}
947        @return: Main module of the process.
948        """
949        return self.get_process().get_main_module()
950
951#==============================================================================
952
953class LoadDLLEvent (Event):
954    """
955    Module load event.
956    """
957
958    eventMethod      = 'load_dll'
959    eventName        = 'Module load event'
960    eventDescription = 'A new DLL library was loaded by the debugee.'
961
962    def get_module_base(self):
963        """
964        @rtype:  int
965        @return: Base address for the newly loaded DLL.
966        """
967        return self.raw.u.LoadDll.lpBaseOfDll
968
969    def get_module(self):
970        """
971        @rtype:  L{Module}
972        @return: Module object for the newly loaded DLL.
973        """
974        lpBaseOfDll = self.get_module_base()
975        aProcess    = self.get_process()
976        if aProcess.has_module(lpBaseOfDll):
977            aModule = aProcess.get_module(lpBaseOfDll)
978        else:
979            # XXX HACK
980            # For some reason the module object is missing, so make a new one.
981            aModule = Module(lpBaseOfDll,
982                             hFile    = self.get_file_handle(),
983                             fileName = self.get_filename(),
984                             process  = aProcess)
985            aProcess._add_module(aModule)
986        return aModule
987
988    def get_file_handle(self):
989        """
990        @rtype:  L{FileHandle} or None
991        @return: File handle to the newly loaded DLL received from the system.
992            Returns C{None} if the handle is not available.
993        """
994        # This handle DOES need to be closed.
995        # Therefore we must cache it so it doesn't
996        # get closed after the first call.
997        try:
998            hFile = self.__hFile
999        except AttributeError:
1000            hFile = self.raw.u.LoadDll.hFile
1001            if hFile in (0, win32.NULL, win32.INVALID_HANDLE_VALUE):
1002                hFile = None
1003            else:
1004                hFile = FileHandle(hFile, True)
1005            self.__hFile = hFile
1006        return hFile
1007
1008    def get_filename(self):
1009        """
1010        @rtype:  str, None
1011        @return: This method does it's best to retrieve the filename to
1012        the newly loaded module. However, sometimes that's not
1013        possible, and C{None} is returned instead.
1014        """
1015        szFilename = None
1016
1017        # Try to get it from LOAD_DLL_DEBUG_INFO.lpImageName
1018        # It's NULL or *NULL most of the times, see MSDN:
1019        # http://msdn.microsoft.com/en-us/library/ms679286(VS.85).aspx
1020        aProcess = self.get_process()
1021        lpRemoteFilenamePtr = self.raw.u.LoadDll.lpImageName
1022        if lpRemoteFilenamePtr:
1023            lpFilename  = aProcess.peek_uint(lpRemoteFilenamePtr)
1024            fUnicode    = bool( self.raw.u.LoadDll.fUnicode )
1025            szFilename  = aProcess.peek_string(lpFilename, fUnicode)
1026            if not szFilename:
1027                szFilename = None
1028
1029        # Try to get the filename from the file handle.
1030        if not szFilename:
1031            hFile = self.get_file_handle()
1032            if hFile:
1033                szFilename = hFile.get_filename()
1034
1035        # Return the filename, or None on error.
1036        return szFilename
1037
1038#==============================================================================
1039
1040class UnloadDLLEvent (Event):
1041    """
1042    Module unload event.
1043    """
1044
1045    eventMethod      = 'unload_dll'
1046    eventName        = 'Module unload event'
1047    eventDescription = 'A DLL library was unloaded by the debugee.'
1048
1049    def get_module_base(self):
1050        """
1051        @rtype:  int
1052        @return: Base address for the recently unloaded DLL.
1053        """
1054        return self.raw.u.UnloadDll.lpBaseOfDll
1055
1056    def get_module(self):
1057        """
1058        @rtype:  L{Module}
1059        @return: Module object for the recently unloaded DLL.
1060        """
1061        lpBaseOfDll = self.get_module_base()
1062        aProcess    = self.get_process()
1063        if aProcess.has_module(lpBaseOfDll):
1064            aModule = aProcess.get_module(lpBaseOfDll)
1065        else:
1066            aModule = Module(lpBaseOfDll, process = aProcess)
1067            aProcess._add_module(aModule)
1068        return aModule
1069
1070    def get_file_handle(self):
1071        """
1072        @rtype:  None or L{FileHandle}
1073        @return: File handle to the recently unloaded DLL.
1074            Returns C{None} if the handle is not available.
1075        """
1076        hFile = self.get_module().hFile
1077        if hFile in (0, win32.NULL, win32.INVALID_HANDLE_VALUE):
1078            hFile = None
1079        return hFile
1080
1081    def get_filename(self):
1082        """
1083        @rtype:  None or str
1084        @return: Filename of the recently unloaded DLL.
1085            C{None} if the filename is unknown.
1086        """
1087        return self.get_module().get_filename()
1088
1089#==============================================================================
1090
1091class OutputDebugStringEvent (Event):
1092    """
1093    Debug string output event.
1094    """
1095
1096    eventMethod      = 'output_string'
1097    eventName        = 'Debug string output event'
1098    eventDescription = 'The debugee sent a message to the debugger.'
1099
1100    def get_debug_string(self):
1101        """
1102        @rtype:  str, compat.unicode
1103        @return: String sent by the debugee.
1104            It may be ANSI or Unicode and may end with a null character.
1105        """
1106        return self.get_process().peek_string(
1107                                self.raw.u.DebugString.lpDebugStringData,
1108                                bool( self.raw.u.DebugString.fUnicode ),
1109                                self.raw.u.DebugString.nDebugStringLength)
1110
1111#==============================================================================
1112
1113class RIPEvent (Event):
1114    """
1115    RIP event.
1116    """
1117
1118    eventMethod      = 'rip'
1119    eventName        = 'RIP event'
1120    eventDescription = 'An error has occured and the process ' \
1121                       'can no longer be debugged.'
1122
1123    def get_rip_error(self):
1124        """
1125        @rtype:  int
1126        @return: RIP error code as defined by the Win32 API.
1127        """
1128        return self.raw.u.RipInfo.dwError
1129
1130    def get_rip_type(self):
1131        """
1132        @rtype:  int
1133        @return: RIP type code as defined by the Win32 API.
1134            May be C{0} or one of the following:
1135             - L{win32.SLE_ERROR}
1136             - L{win32.SLE_MINORERROR}
1137             - L{win32.SLE_WARNING}
1138        """
1139        return self.raw.u.RipInfo.dwType
1140
1141#==============================================================================
1142
1143class EventFactory (StaticClass):
1144    """
1145    Factory of L{Event} objects.
1146
1147    @type baseEvent: L{Event}
1148    @cvar baseEvent:
1149        Base class for Event objects.
1150        It's used for unknown event codes.
1151
1152    @type eventClasses: dict( int S{->} L{Event} )
1153    @cvar eventClasses:
1154        Dictionary that maps event codes to L{Event} subclasses.
1155    """
1156
1157    baseEvent    = Event
1158    eventClasses = {
1159        win32.EXCEPTION_DEBUG_EVENT       : ExceptionEvent,           # 1
1160        win32.CREATE_THREAD_DEBUG_EVENT   : CreateThreadEvent,        # 2
1161        win32.CREATE_PROCESS_DEBUG_EVENT  : CreateProcessEvent,       # 3
1162        win32.EXIT_THREAD_DEBUG_EVENT     : ExitThreadEvent,          # 4
1163        win32.EXIT_PROCESS_DEBUG_EVENT    : ExitProcessEvent,         # 5
1164        win32.LOAD_DLL_DEBUG_EVENT        : LoadDLLEvent,             # 6
1165        win32.UNLOAD_DLL_DEBUG_EVENT      : UnloadDLLEvent,           # 7
1166        win32.OUTPUT_DEBUG_STRING_EVENT   : OutputDebugStringEvent,   # 8
1167        win32.RIP_EVENT                   : RIPEvent,                 # 9
1168    }
1169
1170    @classmethod
1171    def get(cls, debug, raw):
1172        """
1173        @type  debug: L{Debug}
1174        @param debug: Debug object that received the event.
1175
1176        @type  raw: L{DEBUG_EVENT}
1177        @param raw: Raw DEBUG_EVENT structure as used by the Win32 API.
1178
1179        @rtype: L{Event}
1180        @returns: An Event object or one of it's subclasses,
1181            depending on the event type.
1182        """
1183        eventClass = cls.eventClasses.get(raw.dwDebugEventCode, cls.baseEvent)
1184        return eventClass(debug, raw)
1185
1186#==============================================================================
1187
1188class EventHandler (object):
1189    """
1190    Base class for debug event handlers.
1191
1192    Your program should subclass it to implement it's own event handling.
1193
1194    The constructor can be overriden as long as you call the superclass
1195    constructor. The special method L{__call__} B{MUST NOT} be overriden.
1196
1197    The signature for event handlers is the following::
1198
1199        def event_handler(self, event):
1200
1201    Where B{event} is an L{Event} object.
1202
1203    Each event handler is named after the event they handle.
1204    This is the list of all valid event handler names:
1205
1206     - I{event}
1207
1208       Receives an L{Event} object or an object of any of it's subclasses,
1209       and handles any event for which no handler was defined.
1210
1211     - I{unknown_event}
1212
1213       Receives an L{Event} object or an object of any of it's subclasses,
1214       and handles any event unknown to the debugging engine. (This is not
1215       likely to happen unless the Win32 debugging API is changed in future
1216       versions of Windows).
1217
1218     - I{exception}
1219
1220       Receives an L{ExceptionEvent} object and handles any exception for
1221       which no handler was defined. See above for exception handlers.
1222
1223     - I{unknown_exception}
1224
1225       Receives an L{ExceptionEvent} object and handles any exception unknown
1226       to the debugging engine. This usually happens for C++ exceptions, which
1227       are not standardized and may change from one compiler to the next.
1228
1229       Currently we have partial support for C++ exceptions thrown by Microsoft
1230       compilers.
1231
1232       Also see: U{RaiseException()
1233       <http://msdn.microsoft.com/en-us/library/ms680552(VS.85).aspx>}
1234
1235     - I{create_thread}
1236
1237       Receives a L{CreateThreadEvent} object.
1238
1239     - I{create_process}
1240
1241       Receives a L{CreateProcessEvent} object.
1242
1243     - I{exit_thread}
1244
1245       Receives a L{ExitThreadEvent} object.
1246
1247     - I{exit_process}
1248
1249       Receives a L{ExitProcessEvent} object.
1250
1251     - I{load_dll}
1252
1253       Receives a L{LoadDLLEvent} object.
1254
1255     - I{unload_dll}
1256
1257       Receives an L{UnloadDLLEvent} object.
1258
1259     - I{output_string}
1260
1261       Receives an L{OutputDebugStringEvent} object.
1262
1263     - I{rip}
1264
1265       Receives a L{RIPEvent} object.
1266
1267    This is the list of all valid exception handler names
1268    (they all receive an L{ExceptionEvent} object):
1269
1270     - I{access_violation}
1271     - I{array_bounds_exceeded}
1272     - I{breakpoint}
1273     - I{control_c_exit}
1274     - I{datatype_misalignment}
1275     - I{debug_control_c}
1276     - I{float_denormal_operand}
1277     - I{float_divide_by_zero}
1278     - I{float_inexact_result}
1279     - I{float_invalid_operation}
1280     - I{float_overflow}
1281     - I{float_stack_check}
1282     - I{float_underflow}
1283     - I{guard_page}
1284     - I{illegal_instruction}
1285     - I{in_page_error}
1286     - I{integer_divide_by_zero}
1287     - I{integer_overflow}
1288     - I{invalid_disposition}
1289     - I{invalid_handle}
1290     - I{ms_vc_exception}
1291     - I{noncontinuable_exception}
1292     - I{possible_deadlock}
1293     - I{privileged_instruction}
1294     - I{single_step}
1295     - I{stack_overflow}
1296     - I{wow64_breakpoint}
1297
1298
1299
1300    @type apiHooks: dict( str S{->} list( tuple( str, int ) ) )
1301    @cvar apiHooks:
1302        Dictionary that maps module names to lists of
1303        tuples of ( procedure name, parameter count ).
1304
1305        All procedures listed here will be hooked for calls from the debugee.
1306        When this happens, the corresponding event handler can be notified both
1307        when the procedure is entered and when it's left by the debugee.
1308
1309        For example, let's hook the LoadLibraryEx() API call.
1310        This would be the declaration of apiHooks::
1311
1312            from winappdbg import EventHandler
1313            from winappdbg.win32 import *
1314
1315            # (...)
1316
1317            class MyEventHandler (EventHandler):
1318
1319                apiHook = {
1320
1321                    "kernel32.dll" : (
1322
1323                        #   Procedure name      Signature
1324                        (   "LoadLibraryEx",    (PVOID, HANDLE, DWORD) ),
1325
1326                        # (more procedures can go here...)
1327                    ),
1328
1329                    # (more libraries can go here...)
1330                }
1331
1332                # (your method definitions go here...)
1333
1334        Note that all pointer types are treated like void pointers, so your
1335        callback won't get the string or structure pointed to by it, but the
1336        remote memory address instead. This is so to prevent the ctypes library
1337        from being "too helpful" and trying to dereference the pointer. To get
1338        the actual data being pointed to, use one of the L{Process.read}
1339        methods.
1340
1341        Now, to intercept calls to LoadLibraryEx define a method like this in
1342        your event handler class::
1343
1344            def pre_LoadLibraryEx(self, event, ra, lpFilename, hFile, dwFlags):
1345                szFilename = event.get_process().peek_string(lpFilename)
1346
1347                # (...)
1348
1349        Note that the first parameter is always the L{Event} object, and the
1350        second parameter is the return address. The third parameter and above
1351        are the values passed to the hooked function.
1352
1353        Finally, to intercept returns from calls to LoadLibraryEx define a
1354        method like this::
1355
1356            def post_LoadLibraryEx(self, event, retval):
1357                # (...)
1358
1359        The first parameter is the L{Event} object and the second is the
1360        return value from the hooked function.
1361    """
1362
1363#------------------------------------------------------------------------------
1364
1365    # Default (empty) API hooks dictionary.
1366    apiHooks = {}
1367
1368    def __init__(self):
1369        """
1370        Class constructor. Don't forget to call it when subclassing!
1371
1372        Forgetting to call the superclass constructor is a common mistake when
1373        you're new to Python. :)
1374
1375        Example::
1376            class MyEventHandler (EventHandler):
1377
1378                # Override the constructor to use an extra argument.
1379                def __init__(self, myArgument):
1380
1381                    # Do something with the argument, like keeping it
1382                    # as an instance variable.
1383                    self.myVariable = myArgument
1384
1385                    # Call the superclass constructor.
1386                    super(MyEventHandler, self).__init__()
1387
1388                # The rest of your code below...
1389        """
1390
1391        # TODO
1392        # All this does is set up the hooks.
1393        # This code should be moved to the EventDispatcher class.
1394        # Then the hooks can be set up at set_event_handler() instead, making
1395        # this class even simpler. The downside here is deciding where to store
1396        # the ApiHook objects.
1397
1398        # Convert the tuples into instances of the ApiHook class.
1399        # A new dictionary must be instanced, otherwise we could also be
1400        #  affecting all other instances of the EventHandler.
1401        apiHooks = dict()
1402        for lib, hooks in compat.iteritems(self.apiHooks):
1403            hook_objs = []
1404            for proc, args in hooks:
1405                if type(args) in (int, long):
1406                    h = ApiHook(self, lib, proc, paramCount = args)
1407                else:
1408                    h = ApiHook(self, lib, proc,  signature = args)
1409                hook_objs.append(h)
1410            apiHooks[lib] = hook_objs
1411        self.__apiHooks = apiHooks
1412
1413    def __get_hooks_for_dll(self, event):
1414        """
1415        Get the requested API hooks for the current DLL.
1416
1417        Used by L{__hook_dll} and L{__unhook_dll}.
1418        """
1419        result = []
1420        if self.__apiHooks:
1421            path = event.get_module().get_filename()
1422            if path:
1423                lib_name = PathOperations.pathname_to_filename(path).lower()
1424                for hook_lib, hook_api_list in compat.iteritems(self.__apiHooks):
1425                    if hook_lib == lib_name:
1426                        result.extend(hook_api_list)
1427        return result
1428
1429    def __hook_dll(self, event):
1430        """
1431        Hook the requested API calls (in self.apiHooks).
1432
1433        This method is called automatically whenever a DLL is loaded.
1434        """
1435        debug = event.debug
1436        pid   = event.get_pid()
1437        for hook_api_stub in self.__get_hooks_for_dll(event):
1438            hook_api_stub.hook(debug, pid)
1439
1440    def __unhook_dll(self, event):
1441        """
1442        Unhook the requested API calls (in self.apiHooks).
1443
1444        This method is called automatically whenever a DLL is unloaded.
1445        """
1446        debug = event.debug
1447        pid   = event.get_pid()
1448        for hook_api_stub in self.__get_hooks_for_dll(event):
1449            hook_api_stub.unhook(debug, pid)
1450
1451    def __call__(self, event):
1452        """
1453        Dispatch debug events.
1454
1455        @warn: B{Don't override this method!}
1456
1457        @type  event: L{Event}
1458        @param event: Event object.
1459        """
1460        try:
1461            code = event.get_event_code()
1462            if code == win32.LOAD_DLL_DEBUG_EVENT:
1463                self.__hook_dll(event)
1464            elif code == win32.UNLOAD_DLL_DEBUG_EVENT:
1465                self.__unhook_dll(event)
1466        finally:
1467            method = EventDispatcher.get_handler_method(self, event)
1468            if method is not None:
1469                return method(event)
1470
1471#==============================================================================
1472
1473# TODO
1474#  * Make it more generic by adding a few more callbacks.
1475#    That way it will be possible to make a thread sifter too.
1476#  * This interface feels too much like an antipattern.
1477#    When apiHooks is deprecated this will have to be reviewed.
1478
1479class EventSift(EventHandler):
1480    """
1481    Event handler that allows you to use customized event handlers for each
1482    process you're attached to.
1483
1484    This makes coding the event handlers much easier, because each instance
1485    will only "know" about one process. So you can code your event handler as
1486    if only one process was being debugged, but your debugger can attach to
1487    multiple processes.
1488
1489    Example::
1490        from winappdbg import Debug, EventHandler, EventSift
1491
1492        # This class was written assuming only one process is attached.
1493        # If you used it directly it would break when attaching to another
1494        # process, or when a child process is spawned.
1495        class MyEventHandler (EventHandler):
1496
1497            def create_process(self, event):
1498                self.first = True
1499                self.name = event.get_process().get_filename()
1500                print "Attached to %s" % self.name
1501
1502            def breakpoint(self, event):
1503                if self.first:
1504                    self.first = False
1505                    print "First breakpoint reached at %s" % self.name
1506
1507            def exit_process(self, event):
1508                print "Detached from %s" % self.name
1509
1510        # Now when debugging we use the EventSift to be able to work with
1511        # multiple processes while keeping our code simple. :)
1512        if __name__ == "__main__":
1513            handler = EventSift(MyEventHandler)
1514            #handler = MyEventHandler()  # try uncommenting this line...
1515            with Debug(handler) as debug:
1516                debug.execl("calc.exe")
1517                debug.execl("notepad.exe")
1518                debug.execl("charmap.exe")
1519                debug.loop()
1520
1521    Subclasses of C{EventSift} can prevent specific event types from
1522    being forwarded by simply defining a method for it. That means your
1523    subclass can handle some event types globally while letting other types
1524    be handled on per-process basis. To forward events manually you can
1525    call C{self.event(event)}.
1526
1527    Example::
1528        class MySift (EventSift):
1529
1530            # Don't forward this event.
1531            def debug_control_c(self, event):
1532                pass
1533
1534            # Handle this event globally without forwarding it.
1535            def output_string(self, event):
1536                print "Debug string: %s" % event.get_debug_string()
1537
1538            # Handle this event globally and then forward it.
1539            def create_process(self, event):
1540                print "New process created, PID: %d" % event.get_pid()
1541                return self.event(event)
1542
1543            # All other events will be forwarded.
1544
1545    Note that overriding the C{event} method would cause no events to be
1546    forwarded at all. To prevent this, call the superclass implementation.
1547
1548    Example::
1549
1550        def we_want_to_forward_this_event(event):
1551            "Use whatever logic you want here..."
1552            # (...return True or False...)
1553
1554        class MySift (EventSift):
1555
1556            def event(self, event):
1557
1558                # If the event matches some custom criteria...
1559                if we_want_to_forward_this_event(event):
1560
1561                    # Forward it.
1562                    return super(MySift, self).event(event)
1563
1564                # Otherwise, don't.
1565
1566    @type cls: class
1567    @ivar cls:
1568        Event handler class. There will be one instance of this class
1569        per debugged process in the L{forward} dictionary.
1570
1571    @type argv: list
1572    @ivar argv:
1573        Positional arguments to pass to the constructor of L{cls}.
1574
1575    @type argd: list
1576    @ivar argd:
1577        Keyword arguments to pass to the constructor of L{cls}.
1578
1579    @type forward: dict
1580    @ivar forward:
1581        Dictionary that maps each debugged process ID to an instance of L{cls}.
1582    """
1583
1584    def __init__(self, cls, *argv, **argd):
1585        """
1586        Maintains an instance of your event handler for each process being
1587        debugged, and forwards the events of each process to each corresponding
1588        instance.
1589
1590        @warn: If you subclass L{EventSift} and reimplement this method,
1591            don't forget to call the superclass constructor!
1592
1593        @see: L{event}
1594
1595        @type  cls: class
1596        @param cls: Event handler class. This must be the class itself, not an
1597            instance! All additional arguments passed to the constructor of
1598            the event forwarder will be passed on to the constructor of this
1599            class as well.
1600        """
1601        self.cls     = cls
1602        self.argv    = argv
1603        self.argd    = argd
1604        self.forward = dict()
1605        super(EventSift, self).__init__()
1606
1607    # XXX HORRIBLE HACK
1608    # This makes apiHooks work in the inner handlers.
1609    def __call__(self, event):
1610        try:
1611            eventCode = event.get_event_code()
1612            if eventCode in (win32.LOAD_DLL_DEBUG_EVENT,
1613                             win32.LOAD_DLL_DEBUG_EVENT):
1614                pid = event.get_pid()
1615                handler = self.forward.get(pid, None)
1616                if handler is None:
1617                    handler = self.cls(*self.argv, **self.argd)
1618                self.forward[pid] = handler
1619                if isinstance(handler, EventHandler):
1620                    if eventCode == win32.LOAD_DLL_DEBUG_EVENT:
1621                        handler.__EventHandler_hook_dll(event)
1622                    else:
1623                        handler.__EventHandler_unhook_dll(event)
1624        finally:
1625            return super(EventSift, self).__call__(event)
1626
1627    def event(self, event):
1628        """
1629        Forwards events to the corresponding instance of your event handler
1630        for this process.
1631
1632        If you subclass L{EventSift} and reimplement this method, no event
1633        will be forwarded at all unless you call the superclass implementation.
1634
1635        If your filtering is based on the event type, there's a much easier way
1636        to do it: just implement a handler for it.
1637        """
1638        eventCode = event.get_event_code()
1639        pid = event.get_pid()
1640        handler = self.forward.get(pid, None)
1641        if handler is None:
1642            handler = self.cls(*self.argv, **self.argd)
1643            if eventCode != win32.EXIT_PROCESS_DEBUG_EVENT:
1644                self.forward[pid] = handler
1645        elif eventCode == win32.EXIT_PROCESS_DEBUG_EVENT:
1646            del self.forward[pid]
1647        return handler(event)
1648
1649#==============================================================================
1650
1651class EventDispatcher (object):
1652    """
1653    Implements debug event dispatching capabilities.
1654
1655    @group Debugging events:
1656        get_event_handler, set_event_handler, get_handler_method
1657    """
1658
1659    # Maps event code constants to the names of the pre-notify routines.
1660    # These routines are called BEFORE the user-defined handlers.
1661    # Unknown codes are ignored.
1662    __preEventNotifyCallbackName = {
1663        win32.CREATE_THREAD_DEBUG_EVENT   : '_notify_create_thread',
1664        win32.CREATE_PROCESS_DEBUG_EVENT  : '_notify_create_process',
1665        win32.LOAD_DLL_DEBUG_EVENT        : '_notify_load_dll',
1666    }
1667
1668    # Maps event code constants to the names of the post-notify routines.
1669    # These routines are called AFTER the user-defined handlers.
1670    # Unknown codes are ignored.
1671    __postEventNotifyCallbackName = {
1672        win32.EXIT_THREAD_DEBUG_EVENT     : '_notify_exit_thread',
1673        win32.EXIT_PROCESS_DEBUG_EVENT    : '_notify_exit_process',
1674        win32.UNLOAD_DLL_DEBUG_EVENT      : '_notify_unload_dll',
1675        win32.RIP_EVENT                   : '_notify_rip',
1676    }
1677
1678    # Maps exception code constants to the names of the pre-notify routines.
1679    # These routines are called BEFORE the user-defined handlers.
1680    # Unknown codes are ignored.
1681    __preExceptionNotifyCallbackName = {
1682        win32.EXCEPTION_BREAKPOINT        : '_notify_breakpoint',
1683        win32.EXCEPTION_WX86_BREAKPOINT   : '_notify_breakpoint',
1684        win32.EXCEPTION_SINGLE_STEP       : '_notify_single_step',
1685        win32.EXCEPTION_GUARD_PAGE        : '_notify_guard_page',
1686        win32.DBG_CONTROL_C               : '_notify_debug_control_c',
1687        win32.MS_VC_EXCEPTION             : '_notify_ms_vc_exception',
1688    }
1689
1690    # Maps exception code constants to the names of the post-notify routines.
1691    # These routines are called AFTER the user-defined handlers.
1692    # Unknown codes are ignored.
1693    __postExceptionNotifyCallbackName = {
1694    }
1695
1696    def __init__(self, eventHandler = None):
1697        """
1698        Event dispatcher.
1699
1700        @type  eventHandler: L{EventHandler}
1701        @param eventHandler: (Optional) User-defined event handler.
1702
1703        @raise TypeError: The event handler is of an incorrect type.
1704
1705        @note: The L{eventHandler} parameter may be any callable Python object
1706            (for example a function, or an instance method).
1707            However you'll probably find it more convenient to use an instance
1708            of a subclass of L{EventHandler} here.
1709        """
1710        self.set_event_handler(eventHandler)
1711
1712    def get_event_handler(self):
1713        """
1714        Get the event handler.
1715
1716        @see: L{set_event_handler}
1717
1718        @rtype:  L{EventHandler}
1719        @return: Current event handler object, or C{None}.
1720        """
1721        return self.__eventHandler
1722
1723    def set_event_handler(self, eventHandler):
1724        """
1725        Set the event handler.
1726
1727        @warn: This is normally not needed. Use with care!
1728
1729        @type  eventHandler: L{EventHandler}
1730        @param eventHandler: New event handler object, or C{None}.
1731
1732        @rtype:  L{EventHandler}
1733        @return: Previous event handler object, or C{None}.
1734
1735        @raise TypeError: The event handler is of an incorrect type.
1736
1737        @note: The L{eventHandler} parameter may be any callable Python object
1738            (for example a function, or an instance method).
1739            However you'll probably find it more convenient to use an instance
1740            of a subclass of L{EventHandler} here.
1741        """
1742        if eventHandler is not None and not callable(eventHandler):
1743            raise TypeError("Event handler must be a callable object")
1744        try:
1745            wrong_type = issubclass(eventHandler, EventHandler)
1746        except TypeError:
1747            wrong_type = False
1748        if wrong_type:
1749            classname = str(eventHandler)
1750            msg  = "Event handler must be an instance of class %s"
1751            msg += "rather than the %s class itself. (Missing parens?)"
1752            msg  = msg % (classname, classname)
1753            raise TypeError(msg)
1754        try:
1755            previous = self.__eventHandler
1756        except AttributeError:
1757            previous = None
1758        self.__eventHandler = eventHandler
1759        return previous
1760
1761    @staticmethod
1762    def get_handler_method(eventHandler, event, fallback=None):
1763        """
1764        Retrieves the appropriate callback method from an L{EventHandler}
1765        instance for the given L{Event} object.
1766
1767        @type  eventHandler: L{EventHandler}
1768        @param eventHandler:
1769            Event handler object whose methods we are examining.
1770
1771        @type  event: L{Event}
1772        @param event: Debugging event to be handled.
1773
1774        @type  fallback: callable
1775        @param fallback: (Optional) If no suitable method is found in the
1776            L{EventHandler} instance, return this value.
1777
1778        @rtype:  callable
1779        @return: Bound method that will handle the debugging event.
1780            Returns C{None} if no such method is defined.
1781        """
1782        eventCode = event.get_event_code()
1783        method = getattr(eventHandler, 'event', fallback)
1784        if eventCode == win32.EXCEPTION_DEBUG_EVENT:
1785            method = getattr(eventHandler, 'exception', method)
1786        method = getattr(eventHandler, event.eventMethod, method)
1787        return method
1788
1789    def dispatch(self, event):
1790        """
1791        Sends event notifications to the L{Debug} object and
1792        the L{EventHandler} object provided by the user.
1793
1794        The L{Debug} object will forward the notifications to it's contained
1795        snapshot objects (L{System}, L{Process}, L{Thread} and L{Module}) when
1796        appropriate.
1797
1798        @warning: This method is called automatically from L{Debug.dispatch}.
1799
1800        @see: L{Debug.cont}, L{Debug.loop}, L{Debug.wait}
1801
1802        @type  event: L{Event}
1803        @param event: Event object passed to L{Debug.dispatch}.
1804
1805        @raise WindowsError: Raises an exception on error.
1806        """
1807        returnValue  = None
1808        bCallHandler = True
1809        pre_handler  = None
1810        post_handler = None
1811        eventCode    = event.get_event_code()
1812
1813        # Get the pre and post notification methods for exceptions.
1814        # If not found, the following steps take care of that.
1815        if eventCode == win32.EXCEPTION_DEBUG_EVENT:
1816            exceptionCode = event.get_exception_code()
1817            pre_name      = self.__preExceptionNotifyCallbackName.get(
1818                                                           exceptionCode, None)
1819            post_name     = self.__postExceptionNotifyCallbackName.get(
1820                                                           exceptionCode, None)
1821            if  pre_name     is not None:
1822                pre_handler  = getattr(self, pre_name,  None)
1823            if  post_name    is not None:
1824                post_handler = getattr(self, post_name, None)
1825
1826        # Get the pre notification method for all other events.
1827        # This includes the exception event if no notify method was found
1828        # for this exception code.
1829        if pre_handler is None:
1830            pre_name = self.__preEventNotifyCallbackName.get(eventCode, None)
1831            if  pre_name is not None:
1832                pre_handler = getattr(self, pre_name, pre_handler)
1833
1834        # Get the post notification method for all other events.
1835        # This includes the exception event if no notify method was found
1836        # for this exception code.
1837        if post_handler is None:
1838            post_name = self.__postEventNotifyCallbackName.get(eventCode, None)
1839            if  post_name is not None:
1840                post_handler = getattr(self, post_name, post_handler)
1841
1842        # Call the pre-notify method only if it was defined.
1843        # If an exception is raised don't call the other methods.
1844        if pre_handler is not None:
1845            bCallHandler = pre_handler(event)
1846
1847        # Call the user-defined event handler only if the pre-notify
1848        #  method was not defined, or was and it returned True.
1849        try:
1850            if bCallHandler and self.__eventHandler is not None:
1851                try:
1852                    returnValue = self.__eventHandler(event)
1853                except Exception:
1854                    e = sys.exc_info()[1]
1855                    msg = ("Event handler pre-callback %r"
1856                           " raised an exception: %s")
1857                    msg = msg % (self.__eventHandler, traceback.format_exc(e))
1858                    warnings.warn(msg, EventCallbackWarning)
1859                    returnValue = None
1860
1861        # Call the post-notify method if defined, even if an exception is
1862        #  raised by the user-defined event handler.
1863        finally:
1864            if post_handler is not None:
1865                post_handler(event)
1866
1867        # Return the value from the call to the user-defined event handler.
1868        # If not defined return None.
1869        return returnValue
1870