Stalking modules
Matthew Wollenweber (mwollenweber) <mjwcyberwartcom> Monday, August 17 2009 12:12.15 CDT


I hate when I'm debugging a DLL, but it's not loaded until it's needed. This creates the problem that (to my knowledge) you can't set a breakpoint at addresses that aren't loaded into memory. To get around this problem I created the following script for Immunity Debugger:

<code>
#!/usr/bin/env python
'''
Matthew Wollenweber
August 6 2009
[email protected]

I want to debug modules that are dynamically loaded at runtime and then unloaded. It's a pain to set and
reset breakpoints. This script watches for the module to be loaded. When the module is loaded breakpoints are set.

-r implies the use of a relative base for the target module
'''
DESC = "Set breakpoints when a specific library is loaded"
USAGE = "!stalkmod <-r> modname <breakpoint 0> ... <breakpoint n>"


import immlib
from immlib import LogBpHook
#import time
import struct
import unicodedata
import getopt



def main(args):
    imm = immlib.Debugger()
    imm.Log("starting modstalker")
    breakpoints = []
    module_name = ""
    
    
    try:
        opts, extra = getopt.getopt(args, "r")
        
        for flag, val in opts:
            if flag == "-r":
                imm.addKnowledge("getbase", 1)
        
        module_name = extra[0]
        for x in range(1, len(extra)):
            breakpoints.append(long(extra[x], 16))
    except:
        usage()
        imm.Log("ERROR in modstalker")
        return "ERROR. Exiting module"

    allmodules=imm.getAllModules()
    for x in allmodules:
        if x.getName().find(module_name) >= 0:
            for b in breakpoints:
                imm.setBreakpoint(b)        
            imm.Log("Module Already loaded. Breakpoints set")
            return "Module already loaded. Breakpoints set"
    
    imm.addKnowledge("breakpoints", breakpoints)
    imm.addKnowledge("modname", module_name)
                    
    load_hook = MyLoadHook()

    load_addr = imm.getAddress("kernel32.LoadLibraryW")
    load_hook.add("bp on loadlibraryW", load_addr, 0, 0, 0)
    load_addr = imm.getAddress("kernel32.LoadLibraryA")
    load_hook.add("bp on loadlibraryW", load_addr, 0, 0, 0)
    imm.Log("Placed hook on loadlibraryA and LoadLibraryW")
    
    return "Hooks loaded"

    
class MyLoadHook(LogBpHook):
    def __init__(self):
        LogBpHook.__init__(self)
        self.imm = immlib.Debugger()
        self.found = 0
            
    def run(self,regs):      
        imm = self.imm
        ucode = 0
        getbase = 0
        baseoffset = long(0)
        
        modname = imm.getKnowledge("modname")
        getbase = imm.getKnowledge("getbase")
        
        regs = imm.getRegs()
        ptr = imm.readMemory(regs['ESP']+0x4, 0x4)
        ptr = int(struct.unpack("L", ptr)[0])
        filename = imm.readString(ptr)
        
        
        #fuck unicode
        if len(filename) < 3:
            ucode = 1
            tmp = imm.readWString(ptr)
            filename = ""
            x = 0
            while x <  len(tmp):
                filename += str(tmp[x])
                x+=2
                
        filename = filename.lower()
        
        #imm.Log("I'm in: " + filename)
        #imm.Log("I'm stalking: " + modname)
        
        if filename.find(modname) >= 0:
            imm.Log("MATCHED. Setting breakpoints")
            if ucode == 0:
                imm.setBreakpoint(0x7c801DAB) #End of LoadLibraryA
            else:
                imm.setBreakpoint(0x7c80AEEB) #End of LoadLibraryW
              
            imm.Run() #let it run until the end of loadlibrary so that our memory is mapped
            #time.sleep(2)
            if getbase == 1:  
                allmodules=imm.getAllModules()
                for x in allmodules:
                    if x.getName().find(modname) >= 0:
                        baseoffset = x.getBase()
                        break
                
            bps = imm.getKnowledge("breakpoints")
            for x in bps:
                x = x + baseoffset
                imm.Log("set BP: %08x" % (x))
                imm.setBreakpoint(x)
            
            imm.Log("breakpoints set")
            self.found = 1
            self.UnHook()
                
        return
    
          
def usage():
    print USAGE


if __name__=="__main__":
    print "This module is for use within Immunity Debugger only"

</code>

This module stalks LoadLibraryA and LoadLibraryW. When your target module is loaded it sets breakpoints at the given addresses. Optionally you can set no breakpoints and it will pause on your module. You can also specify the '-r' flag to set the breakpoints relative to the base address of the module.  
    

Comments
Posted: Wednesday, December 31 1969 18:00.00 CST