Helper classes and functions

WinAppDbg provides some helper classes and functions, mostly related to input and output, that can come in handy when reading input from users or writing debugging data.

Console output with colors

The functions from the Color static class allow your scripts to write colored text to the console.

Tipically you’ll make a call to the can_use_colors function to determine if it’s possible to write text with colors. This is necessary because color output only works with a real console - if the user has redirected the output to a file or a pipe, trying to use colors will cause an exception to be raised.

The following functions set the console text color:

  • black
  • white
  • red
  • green
  • blue
  • cyan
  • magenta
  • yellow

You can also combine the colors with the brightness settings using the light and dark functions, to get more variations on colors:

Color.red()
Color.light()
print "This is printed in light red."
Color.dark()
print "This is printed in dark red."
Color.blue()
print "This is printed in dark blue."
Color.light()
print "This is printed in light blue."

The following functions set the console background color:

  • bk_black
  • bk_white
  • bk_red
  • bk_green
  • bk_blue
  • bk_cyan
  • bk_magenta
  • bk_yellow

The matching bk_light and bk_dark functions control the brightness of the background, and they work just like light and dark.

If you want to go back to the default text color, just call the default function. There’s also a bk_default function for the background color, and a reset method that reverts to the default for both at the same time.

Example #1: printing text with colors

Download

from winappdbg import Color

# Can we use colors?
if Color.can_use_colors():

    # Let's be polite: put everything in a try/except block
    # so we can reset the console colors before quitting.
    try:

        # Set black background.
        Color.bk_black()

        # For each color...
        for color in ( "red", "green", "blue", "cyan", "magenta", "yellow", "white" ):

            # Set the color.
            function = getattr( Color, color )
            function()

            # For each intensity...
            for intensity in ( "light", "dark" ):

                # Set the intensity.
                function = getattr( Color, intensity )
                function()

                # Print a message.
                print "This is %s %s text on black background." % ( intensity, color )

        # Set black text.
        Color.black()

        # For each color...
        for color in ( "red", "green", "blue", "cyan", "magenta", "yellow", "white" ):

            # Set the background color.
            function = getattr( Color, "bk_" + color )
            function()

            # For each intensity...
            for intensity in ( "light", "dark" ):

                # Set the background intensity.
                function = getattr( Color, "bk_" + intensity )
                function()

                # Print a message.
                print "This is black text on %s %s background." % ( intensity, color )

    # Reset the console colors and quit.
    finally:
        Color.reset()

# No colors available!
else:
    print "Can't use colors! Are you redirecting the output to a file?"

Text output in tables

The Table class lets you build text tables. Each row is added using the addRow method, and the number of columns is automatically inferred. Text justification for each column is defined using the justify method.

The show method prints the output. If you prefer to get the text table in a string, you can call the getOutput method instead. Also, the getWidth method tells you the width in characters of the whole table, so you know if it fits in the screen before printing it.

Example #2: printing a text table

Download

from winappdbg import Table

# Instance a Table object.
table = Table()

# Add a few rows.
table.addRow( "Right justified column text", "Left justified column text" )
table.addRow( "---------------------------", "--------------------------" )
table.addRow( "example", "text" )
table.addRow( "jabberwocky", "snark" )
table.addRow( "Trillian", "Zaphod", "Arthur Dent" )     # one extra!
table.addRow( "Dalek", "Cyberman" )

# By default all columns are left justified. Let's change that.
table.justify( 0, 1 )  # column 0 is now right justified

# Let's find out how wide the table is.
print "Table width: %d" % table.getWidth()

# Let's find out how many bytes would it be if written to a file.
print "Text size in characters: %d" % len( table.getOutput() )

# Show the table contents on screen.
print
table.show(),

Logging

The Logger class implements a simple text logger that can send its output to standard output and/or to a file. There are many libraries in Python that can do this, but this one has the advantage of being integrated with WinAppDbg objects.

If you want to integrate other logging facilities to your scripts you can also use the functions from the static class DebugLog, which contains all the WinAppDbg-related implementation of Logger.

Example #3: logging debug events

Download

from os.path import basename, splitext

from winappdbg import Debug, EventHandler, Logger, DebugLog

def main( argv ):

    # The log file name will be based on the target executable file name.
    logfile = basename( argv[ 0 ] )
    logfile = splitext( logfile )[ 0 ] + ".log"

    # Instance a global Logger object.
    global logger
    logger = Logger( logfile )

    # Launch the debugger.
    try:
        simple_debugger( argv )

    # On error log the exception and quit.
    except:
        logger.log_exc()

def my_event_handler( event ):

    # Get the Logger object.
    global logger

    # Log the event.
    logger.log_event( event )

def simple_debugger( argv ):

    # Instance a Debug object, passing it the event handler callback.
    debug = Debug( my_event_handler, bKillOnExit = True )
    try:

        # Start a new process for debugging.
        debug.execv( argv )

        # Wait for the debugee to finish.
        debug.loop()

    # Stop the debugger.
    finally:
        debug.stop()

Hexadecimal input

The static class HexInput contains a collection of functions to parse input data in various formats.

Function Description
integer Convert a string to an integer. Supports decimal, hexadecimal (0x prefix), octal (0o prefix) and binary (0b prefix). If no prefix is given, this method still does its best to tell if it’s hexadecimal or not. If all fails, the number is assumed to be decimal.
address Read an hexadecimal value from a string. Unlike integer no attempt is made to detect other formats. This function was conceived for parsing memory addresses, hence the name.
hexadecimal Convert a strip of hexadecimal numbers (like OllyDbg’s memory view) into binary data.
pattern Similar to hexadecimal, but it also accepts question marks as wildcards for unknown values in fixed positions. The return value is a regular expression that can perform a search for the given byte pattern.
is_pattern Determine if the given argument is a valid hexadecimal pattern to be used with pattern.
integer_list_file Read a list of integers from a file, assuming a specific file format. Check the documentation for HexInput.integer_list_file for details.
string_list_file Read a list of strings from a file, assuming a specific file format. Check the documentation for HexInput.string_list_file for details.
mixed_list_file Read a list of integers and strings from a file, assuming a specific file format. Check the documentation for HexInput.mixed_list_file for details.

Hexadecimal output

Two static classes contain all the functions related to hexadecimal output: HexOutput and HexDump. The first matches the input functions from HexInput, while the second is meant for showing data to the user rather than being parsed by a script.

The following functions are common to both:

Function Description
integer Numeric value output, in decimal format. The default size depends on the current architecture, but you can override it using the bits parameter.
address Memory address output, in hexadecimal format. The default size depends on the current architecture, but you can override it using the bits parameter.
hexadecimal Output binary data as a strip of hexadecimal numbers (like OllyDbg’s memory view). Currently both implementations are identical.

The HexOutput class also has file output functions to match those in HexInput:

Function Description
integer_list_file Write a list of integers into a file, assuming a specific file format. Check the documentation for HexOutput.integer_list_file for details.
string_list_file Write a list of strings into a file, assuming a specific file format. Check the documentation for HexOutput.string_list_file for details.
mixed_list_file Write a list of integers and strings into a file, assuming a specific file format. Check the documentation for HexOutput.mixed_list_file for details.

The HexDump class has additional methods for showing hex dumps and binary data to the user in a printable manner:

Function Description
hexblock Dump a block of hexadecimal numbers from binary data. Also show a printable text version of the data. The output mimics that of the WinDBG debugger.
hexline Dump a line of hexadecimal numbers from binary data. This is useful for printing bytes in a console one line at a time.
hexa_word Convert binary data to a string of hexadecimal WORDs.
hexa_dword Convert binary data to a string of hexadecimal DWORDs.
hexa_qword Convert binary data to a string of hexadecimal QWORDs.
hexblock_byte Dump a block of hexadecimal BYTEs from binary data.
hexblock_word Dump a block of hexadecimal WORDs from binary data.
hexblock_dword Dump a block of hexadecimal DWORDs from binary data.
hexblock_qword Dump a block of hexadecimal QWORDs from binary data.
hexblock_cb Dump a block of binary data using a callback function to convert each line of text. This allows you to customize the output.

Dumping code, stack and registers

The CrashDump static class has functions tipically used from the event handlers to show debug data like the disassembler output, the register contents or the stack trace. Crash dump objects use this class for text output, and pretty many examples in the Debugging section of the tutorial use functions from here too.

All functions return a string with the text to print. Here are the most commonly used ones:

Function Description
dump_code Dump a disassembly. Optionally mark where the program counter is.
dump_registers Dump the x86 processor register values. The output mimics that of the WinDBG debugger.
dump_stack_trace Dump a stack trace using only memory addresses.
dump_stack_trace_with_labels Dump a stack trace using labels instead of memory addresses when possible.

Example #4: dumping code, stack and registers

Download

from winappdbg import Thread, HexDump, CrashDump, System

def print_state( process_name ):

    # Request debug privileges.
    System.request_debug_privileges()

    # Find the first process that matches the requested name.
    system = System()
    process, filename = system.find_processes_by_filename( process_name )[ 0 ]

    # Suspend the process execution.
    process.suspend()
    try:

        # For each thread in the process...
        for thread in process.iter_threads():

            # Get the thread state.
            tid     = thread.get_tid()
            eip     = thread.get_pc()
            code    = thread.disassemble_around( eip )
            context = thread.get_context()

            # Display the thread state.
            print
            print "-" * 79
            print "Thread: %s" % HexDump.integer( tid )
            print
            print CrashDump.dump_registers( context )
            print CrashDump.dump_code( code, eip ),
            print "-" * 79

    # Resume the process execution.
    finally:
        process.resume()

Pathname and filename handling

The PathOperations static class provides functions to manipulate pathnames and filenames. It’s somewhat similar to the standard os.path module - except that it works by using only the Win32 API instead of manually parsing the filenames, which provides better compatibility with Windows (UNC path support, for example).

Function Description
path_is_relative Returns True if the path is relative.
path_is_absolute Returns True if the path is absolute.
make_relative Converts an absolute to a relative path.
make_absolute Converts a relative to an absolute path.
split_filename Split the file from the directory where it resides.
split_extension Split the file name from the file extension.
split_path Split each component of a path.
join_path Join back the components of a path.
native_to_win32_pathname Converts an NT Native path to a standard Win32 path.

Example #5: pathname and filename handling

Download

import sys

from winappdbg import PathOperations

# Get the command line argument.
path = sys.argv[ 1 ]
print "Path: %s" % path

# If it's a relative path...
if PathOperations.path_is_relative( path ):
    print "Path is relative."

    # Convert to absolute.
    absolute = PathOperations.make_absolute( path )
    print "Absolute path: %s" % absolute

# If it's an absolute path...
elif PathOperations.path_is_absolute( path ):
    print "Path is absolute."

    # Convert to relative.
    relative = PathOperations.make_relative( path )
    print "Relative path: %s" % relative

# If it's neither...
else:
    print "Path is invalid."