Extending Pydbg

Introduction

PyDbg is a python win32 debugger interface: it wraps the native windows debug API so users can have access to the debugging facilities provided by windows from within python. This document describes how I extended pydbg with some features to make my work easier. The first example shows how to make pydbg more interactive by spawning a python prompt from within the debugger. The second example shows how a breakpoint can be set inside a library that has not yet been loaded.

Example 1 : Pydbg + IPython

IPython provides an enhanced interactive Python shell to the user. It supports the ability to spawn a python shell from within a python script. This shell is even more powerful than the standard python prompt because of its numerous features (tab completion, ability to execute system commands, etc.).
example :

from IPython.Shell import IPShellEmbed
ipshell = IPShellEmbed()
ipshell()


One way we this functionality can be used is from within an exception handler. However, I want to be able to get to the prompt at any time when I press ctrl+break.
When a pydbg instance is running, it continually monitors the debuggee for debug events such as a breakpoint being hit or an exception being raised. This happens in the pydbg.debug_event_loop method (the pydbg.run method is an alias for this routine ). debug_event_loop in turns calls debug_event_iteration to actually process the debug events. To get to the python prompt when pydbg is running, I registered a signal handler that watches for a ctrl+break. Every time debug_event_iteration is invoked, the script checks if ctrl+break was hit. If it was hit, ipshell() is called:
from pydbg import *
from pydbg.defines import *
from pydbg.pydbg_core import *
from IPython.Shell import IPShellEmbed

import   signal
            
class SigHandler:

    def __init__(self):

        self.signaled = 0
        self.sn=None
    
    reset = __init__
    
    def __call__(self, sn, sf):

        self.sn = sn
        self.signaled += 1


class Tdbg(pydbg,pydbg_core):

    def __init__(self):

        pydbg.__init__(self)
        
        self.sh = sh = SigHandler()
        signal.signal(signal.SIGBREAK,sh)

    def debug_event_iteration(self):

        pydbg.debug_event_iteration (self)
        
        sh = self.sh
        
        if sh.signaled and sh.sn:
            if sh.sn==signal.SIGBREAK:
                ipshell = IPShellEmbed()
                ipshell()
            sh.reset()


dbg=Tdbg()
dbg.load("C:\\Program Files (x86)\\Mozilla Firefox\\firefox.exe")
dbg.run()


An example use of this script could be: Untitled

$ python Tdbg.py
 [ User hits ctrl+break ]
In [1]: self.func_reso
self.func_resolve          self.func_resolve_debuggee

In [1]: "0x%x"%self.func_resolve("ntdll","RtlAllocateHeap")
Out[1]: '0x77342f1f'

In [2]: for dll in self.syste
self.system_break self.system_dlls

In [2]: for dll in self.system_dlls:
   ...:     if dll.name == "ntdll.dll":
   ...:         print "0x%x"%dll.base
   ...:
   ...:
0x772f0000

In [3]: self.terminate_process()

In [4]: exit()
Do you really want to exit ([y]/n)? y

Example 2 : Setting a breakpoint inside a library that has not yet been loaded

Look at the the pydbg code here