winappdbg.event

Event handling module.

Contains the logic to handle debugging events in your scripts and tools.

@group Debugging:

EventHandler, EventSift

@group Debug events:

EventFactory, EventDispatcher, Event, NoEvent, CreateProcessEvent, CreateThreadEvent, ExitProcessEvent, ExitThreadEvent, LoadDLLEvent, UnloadDLLEvent, OutputDebugStringEvent, RIPEvent, ExceptionEvent

@group Warnings:

EventCallbackWarning

class winappdbg.event.CreateProcessEvent(debug, raw)

Process creation event.

get_debug_info()
Return type:

str

Returns:

Debugging information.

get_file_handle()
Return type:

FileHandle or None

Returns:

File handle to the main module, received from the system. Returns None if the handle is not available.

get_filename()
Return type:

str, None

Returns:

This method does it’s best to retrieve the filename to the main module of the process. However, sometimes that’s not possible, and None is returned instead.

get_image_base()
Return type:

int

Returns:

Base address of the main module.

Warning

This value is taken from the PE file and may be incorrect because of ASLR!

get_module()
Return type:

Module

Returns:

Main module of the process.

get_module_base()
Return type:

int

Returns:

Base address of the main module.

get_process_handle()
Return type:

ProcessHandle

Returns:

Process handle received from the system. Returns None if the handle is not available.

get_start_address()
Return type:

int

Returns:

Pointer to the first instruction to execute in this process.

Returns NULL when the debugger attaches to a process.

See http://msdn.microsoft.com/en-us/library/ms679295(VS.85).aspx

get_teb()
Return type:

int

Returns:

Pointer to the TEB.

get_thread_handle()
Return type:

ThreadHandle

Returns:

Thread handle received from the system. Returns None if the handle is not available.

class winappdbg.event.CreateThreadEvent(debug, raw)

Thread creation event.

get_start_address()
Return type:

int

Returns:

Pointer to the first instruction to execute in this thread.

Returns NULL when the debugger attached to a process and the thread already existed.

See http://msdn.microsoft.com/en-us/library/ms679295(VS.85).aspx

get_teb()
Return type:

int

Returns:

Pointer to the TEB.

get_thread_handle()
Return type:

ThreadHandle

Returns:

Thread handle received from the system. Returns None if the handle is not available.

class winappdbg.event.Event(debug, raw)

Event object.

Variables:
  • eventMethod (str) – Method name to call when using EventHandler subclasses. Used internally.

  • eventName (str) – User-friendly name of the event.

  • eventDescription (str) – User-friendly description of the event.

  • debug (Debug) – Debug object that received the event.

  • raw (winappdg.win32.DEBUG_EVENT) – Raw DEBUG_EVENT structure as used by the Win32 API.

  • continueStatus (int) – Continue status to pass to win32.ContinueDebugEvent().

generate_minidump(filename, DumpType=None, bIncludeContext=True, ExceptionParam=None, UserStreamParam=None, CallbackParam=None)

Generates a minidump file for the process where this event occurred.

This is a convenience wrapper around Process.generate_minidump() that automatically captures the thread context if requested.

Parameters:
  • filename (str) – Path to the output minidump file (.dmp).

  • DumpType (int) – Type of information to include in the minidump. See Process.generate_minidump() for details.

  • bIncludeContext (bool) – If True (default), captures and includes the context (register state) of the thread where the event occurred. Set to False to skip context capture.

  • ExceptionParam (MINIDUMP_EXCEPTION_INFORMATION or None) – Optional exception information. ExceptionEvent provides a more convenient method that automatically populates this.

  • UserStreamParam (MINIDUMP_USER_STREAM_INFORMATION or None) – Optional user-defined information streams.

  • CallbackParam (MINIDUMP_CALLBACK_INFORMATION or None) – Optional callback for customizing the dump.

Raises:

WindowsError – On error an exception is raised.

Example:

class MyEventHandler(EventHandler):
    def breakpoint(self, event):
        # Generate a minidump when hitting a breakpoint
        event.generate_minidump("breakpoint.dmp")

    def load_dll(self, event):
        # Generate a dump without context for DLL load events
        event.generate_minidump("dll_load.dmp", bIncludeContext=False)
get_event_code()
Return type:

int

Returns:

Debug event code as defined in the Win32 API.

get_event_description()
Return type:

str

Returns:

User-friendly description of the event.

get_event_name()
Return type:

str

Returns:

User-friendly name of the event.

get_pid()

See also

get_process()

Return type:

int

Returns:

Process global ID where the event occured.

get_process()

See also

get_pid()

Return type:

Process

Returns:

Process where the event occured.

get_thread()

See also

get_tid()

Return type:

Thread

Returns:

Thread where the event occured.

get_tid()

See also

get_thread()

Return type:

int

Returns:

Thread global ID where the event occured.

exception winappdbg.event.EventCallbackWarning

This warning is issued when an uncaught exception was raised by a user-defined event handler.

class winappdbg.event.EventDispatcher(eventHandler=None)

Implements debug event dispatching capabilities.

dispatch(event)

Sends event notifications to the Debug object and the EventHandler object provided by the user.

The Debug object will forward the notifications to it’s contained snapshot objects (System, Process, Thread and Module) when appropriate.

Warning

This method is called automatically from Debug.dispatch().

See also

Debug.cont(), Debug.loop(), Debug.wait()

Parameters:

event (Event) – Event object passed to Debug.dispatch().

Raises:

WindowsError – Raises an exception on error.

get_event_handler()

Get the event handler.

Return type:

EventHandler

Returns:

Current event handler object, or None.

static get_handler_method(eventHandler, event, fallback=None)

Retrieves the appropriate callback method from an EventHandler instance for the given Event object.

Parameters:
  • eventHandler (EventHandler) – Event handler object whose methods we are examining.

  • event (Event) – Debugging event to be handled.

  • fallback (callable) – (Optional) If no suitable method is found in the EventHandler instance, return this value.

Return type:

callable

Returns:

Bound method that will handle the debugging event. Returns None if no such method is defined.

set_event_handler(eventHandler)

Set the event handler.

Warning

This is normally not needed. Use with care!

Parameters:

eventHandler (EventHandler) – New event handler object, or None.

Return type:

EventHandler

Returns:

Previous event handler object, or None.

Raises:

TypeError – The event handler is of an incorrect type.

Note

The eventHandler parameter may be any callable Python object (for example a function, or an instance method). However you’ll probably find it more convenient to use an instance of a subclass of EventHandler here.

class winappdbg.event.EventFactory(*argv, **argd)

Factory of Event objects.

Variables:
  • baseEvent (Event) – Base class for Event objects. It’s used for unknown event codes.

  • eventClasses (dict(int, Event)) – Dictionary that maps event codes to Event subclasses.

baseEvent

alias of Event

classmethod get(debug, raw)
Parameters:
  • debug (Debug) – Debug object that received the event.

  • raw (winappdg.win32.DEBUG_EVENT) – Raw DEBUG_EVENT structure as used by the Win32 API.

Return type:

Event

Returns:

An Event object or one of it’s subclasses, depending on the event type.

class winappdbg.event.EventHandler

Base class for debug event handlers.

Your program should subclass it to implement it’s own event handling.

The constructor can be overriden as long as you call the superclass constructor. The special method __call__ MUST NOT be overriden.

The signature for event handlers is the following:

def event_handler(self, event):

Where event is an Event object.

Each event handler is named after the event they handle. This is the list of all valid event handler names:

  • event

    Receives an Event object or an object of any of it’s subclasses, and handles any event for which no handler was defined.

  • unknown_event

    Receives an Event object or an object of any of it’s subclasses, and handles any event unknown to the debugging engine. (This is not likely to happen unless the Win32 debugging API is changed in future versions of Windows).

  • exception

    Receives an ExceptionEvent object and handles any exception for which no handler was defined. See above for exception handlers.

  • unknown_exception

    Receives an ExceptionEvent object and handles any exception unknown to the debugging engine. This usually happens for C++ exceptions, which are not standardized and may change from one compiler to the next.

    Currently we have partial support for C++ exceptions thrown by Microsoft compilers.

    Also see: RaiseException()

  • create_thread

    Receives a CreateThreadEvent object.

  • create_process

    Receives a CreateProcessEvent object.

  • exit_thread

    Receives a ExitThreadEvent object.

  • exit_process

    Receives a ExitProcessEvent object.

  • load_dll

    Receives a LoadDLLEvent object.

  • unload_dll

    Receives an UnloadDLLEvent object.

  • output_string

    Receives an OutputDebugStringEvent object.

  • rip

    Receives a RIPEvent object.

This is the list of all valid exception handler names (they all receive an ExceptionEvent object):

  • access_violation

  • array_bounds_exceeded

  • breakpoint

  • control_c_exit

  • datatype_misalignment

  • debug_control_c

  • float_denormal_operand

  • float_divide_by_zero

  • float_inexact_result

  • float_invalid_operation

  • float_overflow

  • float_stack_check

  • float_underflow

  • guard_page

  • illegal_instruction

  • in_page_error

  • integer_divide_by_zero

  • integer_overflow

  • invalid_disposition

  • invalid_handle

  • ms_vc_exception

  • noncontinuable_exception

  • possible_deadlock

  • privileged_instruction

  • single_step

  • stack_overflow

  • wow64_breakpoint

Variables:

apiHooks (dict(str, list(tuple(str, int)))) –

Dictionary that maps module names to lists of tuples of ( procedure name, parameter count ).

All procedures listed here will be hooked for calls from the debugee. When this happens, the corresponding event handler can be notified both when the procedure is entered and when it’s left by the debugee.

For example, let’s hook the LoadLibraryEx() API call. This would be the declaration of apiHooks:

from winappdbg import EventHandler
from winappdbg.win32 import *

# (...)

class MyEventHandler (EventHandler):

    apiHook = {

        "kernel32.dll" : (

            #   Procedure name      Signature
            (   "LoadLibraryEx",    (PVOID, HANDLE, DWORD) ),

            # (more procedures can go here...)
        ),

        # (more libraries can go here...)
    }

    # (your method definitions go here...)

Note that all pointer types are treated like void pointers, so your callback won’t get the string or structure pointed to by it, but the remote memory address instead. This is so to prevent the ctypes library from being “too helpful” and trying to dereference the pointer. To get the actual data being pointed to, use one of the Process.read() methods.

Now, to intercept calls to LoadLibraryEx define a method like this in your event handler class:

def pre_LoadLibraryEx(self, event, ra, lpFilename, hFile, dwFlags):
    szFilename = event.get_process().peek_string(lpFilename)

    # (...)

Note that the first parameter is always the Event object, and the second parameter is the return address. The third parameter and above are the values passed to the hooked function.

Finally, to intercept returns from calls to LoadLibraryEx define a method like this:

def post_LoadLibraryEx(self, event, retval):
    # (...)

The first parameter is the Event object and the second is the return value from the hooked function.

class winappdbg.event.EventSift(cls, *argv, **argd)

Event handler that allows you to use customized event handlers for each process you’re attached to.

This makes coding the event handlers much easier, because each instance will only “know” about one process. So you can code your event handler as if only one process was being debugged, but your debugger can attach to multiple processes.

Example:

from winappdbg import Debug, EventHandler, EventSift

# This class was written assuming only one process is attached.
# If you used it directly it would break when attaching to another
# process, or when a child process is spawned.
class MyEventHandler (EventHandler):

    def create_process(self, event):
        self.first = True
        self.name = event.get_process().get_filename()
        print("Attached to %s" % self.name)

    def breakpoint(self, event):
        if self.first:
            self.first = False
            print("First breakpoint reached at %s" % self.name)

    def exit_process(self, event):
        print("Detached from %s" % self.name)

# Now when debugging we use the EventSift to be able to work with
# multiple processes while keeping our code simple. :)
if __name__ == "__main__":
    handler = EventSift(MyEventHandler)
    #handler = MyEventHandler()  # try uncommenting this line...
    with Debug(handler) as debug:
        debug.execl("calc.exe")
        debug.execl("notepad.exe")
        debug.execl("charmap.exe")
        debug.loop()

Subclasses of EventSift can prevent specific event types from being forwarded by simply defining a method for it. That means your subclass can handle some event types globally while letting other types be handled on per-process basis. To forward events manually you can call self.event(event).

Example:

class MySift (EventSift):

    # Don't forward this event.
    def debug_control_c(self, event):
        pass

    # Handle this event globally without forwarding it.
    def output_string(self, event):
        print("Debug string: %s" % event.get_debug_string())

    # Handle this event globally and then forward it.
    def create_process(self, event):
        print("New process created, PID: %d" % event.get_pid())
        return self.event(event)

    # All other events will be forwarded.

Note that overriding the event method would cause no events to be forwarded at all. To prevent this, call the superclass implementation.

Example:

def we_want_to_forward_this_event(event):
    "Use whatever logic you want here..."
    # (...return True or False...)

class MySift (EventSift):

    def event(self, event):

        # If the event matches some custom criteria...
        if we_want_to_forward_this_event(event):

            # Forward it.
            return super().event(event)

        # Otherwise, don't.
Variables:
  • cls – Event handler class. There will be one instance of this class per debugged process in the forward dictionary.

  • argv – Positional arguments to pass to the constructor of cls.

  • argd – Keyword arguments to pass to the constructor of cls.

  • forward – Dictionary that maps each debugged process ID to an instance of cls.

event(event)

Forwards events to the corresponding instance of your event handler for this process.

If you subclass EventSift and reimplement this method, no event will be forwarded at all unless you call the superclass implementation.

If your filtering is based on the event type, there’s a much easier way to do it: just implement a handler for it.

class winappdbg.event.ExceptionEvent(debug, raw)

Exception event.

Variables:
  • exceptionName (dict(int, str)) – Mapping of exception constants to their names.

  • exceptionDescription (dict(int, str)) – Mapping of exception constants to user-friendly strings.

  • breakpoint (Breakpoint) – If the exception was caused by one of our breakpoints, this member contains a reference to the breakpoint object. Otherwise it’s not defined. It should only be used from the condition or action callback routines, instead of the event handler.

  • hook (Hook) – If the exception was caused by a function hook, this member contains a reference to the hook object. Otherwise it’s not defined. It should only be used from the hook callback routines, instead of the event handler.

property eventMethod

str(object=’’) -> str str(bytes_or_buffer[, encoding[, errors]]) -> str

Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.__str__() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to ‘strict’.

generate_minidump(filename, DumpType=None, bIncludeContext=True, bIncludeException=True, UserStreamParam=None, CallbackParam=None)

Generates a minidump file for the exception, including exception information.

This is an enhanced version of Event.generate_minidump() that automatically captures the exception information for crash dumps.

Parameters:
  • filename (str) – Path to the output minidump file (.dmp).

  • DumpType (int) – Type of information to include in the minidump. See Process.generate_minidump() for details.

  • bIncludeContext (bool) – If True (default), captures and includes the context (register state) of the thread where the exception occurred.

  • bIncludeException (bool) – If True (default), captures and includes the exception information in the minidump. This provides crash analysis tools with the exception record.

  • UserStreamParam (MINIDUMP_USER_STREAM_INFORMATION or None) – Optional user-defined information streams.

  • CallbackParam (MINIDUMP_CALLBACK_INFORMATION or None) – Optional callback for customizing the dump.

Raises:

WindowsError – On error an exception is raised.

Example:

class MyEventHandler(EventHandler):
    def access_violation(self, event):
        # Automatically capture exception and context
        event.generate_minidump("crash.dmp")

    def breakpoint(self, event):
        # Just capture state without exception record
        event.generate_minidump("debug.dmp", bIncludeException=False)
get_exception_address()
Return type:

int

Returns:

Memory address where the exception occured.

get_exception_code()
Return type:

int

Returns:

Exception code as defined by the Win32 API.

get_exception_description()
Return type:

str

Returns:

User-friendly name of the exception.

get_exception_information(index)
Parameters:

index (int) – Index into the exception information block.

Return type:

int

Returns:

Exception information DWORD.

get_exception_information_as_list()
Return type:

list( int )

Returns:

Exception information block.

get_exception_name()
Return type:

str

Returns:

Name of the exception as defined by the Win32 API.

get_fault_address()
Return type:

int

Returns:

Access violation memory address.

Note

This method is only meaningful for access violation exceptions, in-page memory error exceptions and guard page exceptions.

Raises:

NotImplementedError – Wrong kind of exception.

get_fault_type()
Return type:

int

Returns:

Access violation type. Should be one of the following constants:

  • win32.EXCEPTION_READ_FAULT

  • win32.EXCEPTION_WRITE_FAULT

  • win32.EXCEPTION_EXECUTE_FAULT

Note

This method is only meaningful for access violation exceptions, in-page memory error exceptions and guard page exceptions.

Raises:

NotImplementedError – Wrong kind of exception.

get_nested_exceptions()

Traverses the exception record linked list and builds a Python list.

Nested exception records are received for nested exceptions. This happens when an exception is raised in the debugee while trying to handle a previous exception.

Return type:

list( ExceptionEvent )

Returns:

List of ExceptionEvent objects representing each exception record found in this event.

There is always at least one exception record, so the list is never empty. All other methods of this class read from the first exception record only, that is, the most recent exception.

get_ntstatus_code()
Return type:

int

Returns:

NTSTATUS status code that caused the exception.

Note

This method is only meaningful for in-page memory error exceptions.

Raises:

NotImplementedError – Not an in-page memory error.

get_raw_exception_record_list()

Traverses the exception record linked list and builds a Python list.

Nested exception records are received for nested exceptions. This happens when an exception is raised in the debugee while trying to handle a previous exception.

Return type:

list( win32.EXCEPTION_RECORD )

Returns:

List of raw exception record structures as used by the Win32 API.

There is always at least one exception record, so the list is never empty. All other methods of this class read from the first exception record only, that is, the most recent exception.

is_continuable()
Return type:

bool

Returns:

The opposite of is_noncontinuable().

is_first_chance()
Return type:

bool

Returns:

True for first chance exceptions, False for last chance.

is_last_chance()
Return type:

bool

Returns:

The opposite of is_first_chance().

is_nested()
Return type:

bool

Returns:

Returns True if there are additional exception records associated with this exception. This would mean the exception is nested, that is, it was triggered while trying to handle at least one previous exception.

is_noncontinuable()
Return type:

bool

Returns:

True if the exception is noncontinuable, False otherwise.

Attempting to continue a noncontinuable exception results in an EXCEPTION_NONCONTINUABLE_EXCEPTION exception to be raised.

is_system_defined_exception()
Return type:

bool

Returns:

The opposite of is_user_defined_exception().

is_user_defined_exception()

Determines if this is an user-defined exception. User-defined exceptions may contain any exception code that is not system reserved.

Often the exception code is also a valid Win32 error code, but that’s up to the debugged application.

Return type:

bool

Returns:

True if the exception is user-defined, False otherwise.

class winappdbg.event.ExitProcessEvent(debug, raw)

Process termination event.

get_exit_code()
Return type:

int

Returns:

Exit code of the process.

get_filename()
Return type:

None or str

Returns:

Filename of the main module. None if the filename is unknown.

get_image_base()
Return type:

int

Returns:

Base address of the main module.

get_module()
Return type:

Module

Returns:

Main module of the process.

get_module_base()
Return type:

int

Returns:

Base address of the main module.

class winappdbg.event.ExitThreadEvent(debug, raw)

Thread termination event.

get_exit_code()
Return type:

int

Returns:

Exit code of the thread.

class winappdbg.event.LoadDLLEvent(debug, raw)

Module load event.

get_file_handle()
Return type:

FileHandle or None

Returns:

File handle to the newly loaded DLL received from the system. Returns None if the handle is not available.

get_filename()
Return type:

str, None

Returns:

This method does it’s best to retrieve the filename to the newly loaded module. However, sometimes that’s not possible, and None is returned instead.

get_module()
Return type:

Module

Returns:

Module object for the newly loaded DLL.

get_module_base()
Return type:

int

Returns:

Base address for the newly loaded DLL.

class winappdbg.event.NoEvent(debug, raw=None)

No event.

Dummy Event object that can be used as a placeholder when no debug event has occured yet. It’s never returned by the EventFactory.

get_event_code()
Return type:

int

Returns:

Debug event code as defined in the Win32 API.

get_pid()

See also

get_process()

Return type:

int

Returns:

Process global ID where the event occured.

get_process()

See also

get_pid()

Return type:

Process

Returns:

Process where the event occured.

get_thread()

See also

get_tid()

Return type:

Thread

Returns:

Thread where the event occured.

get_tid()

See also

get_thread()

Return type:

int

Returns:

Thread global ID where the event occured.

class winappdbg.event.OutputDebugStringEvent(debug, raw)

Debug string output event.

get_debug_string()
Return type:

bytes or str

Returns:

String sent by the debugee. It may be ANSI or Unicode and may end with a null character.

class winappdbg.event.RIPEvent(debug, raw)

RIP event.

get_rip_error()
Return type:

int

Returns:

RIP error code as defined by the Win32 API.

get_rip_type()
Return type:

int

Returns:

RIP type code as defined by the Win32 API. May be 0 or one of the following:

  • winappdbg.win32.SLE_ERROR

  • winappdbg.win32.SLE_MINORERROR

  • winappdbg.win32.SLE_WARNING

class winappdbg.event.UnloadDLLEvent(debug, raw)

Module unload event.

get_file_handle()
Return type:

None or FileHandle

Returns:

File handle to the recently unloaded DLL. Returns None if the handle is not available.

get_filename()
Return type:

None or str

Returns:

Filename of the recently unloaded DLL. None if the filename is unknown.

get_module()
Return type:

Module

Returns:

Module object for the recently unloaded DLL.

get_module_base()
Return type:

int

Returns:

Base address for the recently unloaded DLL.