示例#1
0
    def __init__(self, funcCallbacks):
        """
        This is the start of the debugger.
        """
        import os

        from dispatcher.core.Util import ConfigReader, unique_file_name
        from dispatcher.core.structures.Tracer.Config.config import ConfigFile as ConfigFile

        #Get the root IDA directory in order to locate the config.xml file
        root_dir = os.path.join(idc.GetIdaDirectory(), "plugins")
        ini_path = os.path.join(root_dir, "settings.ini")

        configReader = ConfigReader()
        configReader.Read(ini_path)

        # self.removeBreakpoints()

        self.windowsFileIO = funcCallbacks['windowsFileIO']
        self.windowsNetworkIO = funcCallbacks['windowsNetworkIO']
        self.linuxFileIO = funcCallbacks['linuxFileIO']
        self.interactivemodeCallback = funcCallbacks['interactivemodeCallback']

        #register the hotkey for marking the starting point for taint tracking
        taintStart_ctx = idaapi.add_hotkey("Shift-A", self.taintStart)
        self.taintStart = None
        #register the hotkey for marking the stopping point for taint tracking
        taintStop_ctx = idaapi.add_hotkey("Shift-Z", self.taintStop)
        self.taintStop = None

        configFile = configReader.configFile

        #Print( configFile )
        #Call ConfigFile to grab all configuration information from the config.xml file
        self.config = ConfigFile(configFile)

        (processName, osType, osArch) = self.getProcessInfo()

        self.processConfig = self.createProcessConfig(processName, osType,
                                                      osArch)

        filePath = os.path.splitext(configReader.traceFile)
        processBasename = os.path.splitext(processName)

        self.tracefile = filePath[0] + "_" + processBasename[0] + filePath[1]
        self.tracefile = unique_file_name(self.tracefile)
        Print(self.tracefile)

        traceFileName = os.path.splitext(self.tracefile)
        self.treeTracefile = traceFileName[0] + ".idb"

        self.logger = None
        logfile = traceFileName[0] + ".log"

        self.initLogging(logfile, configReader.logging, configReader.debugging)

        print "IDATrace init called."
示例#2
0
    def __init__(self,funcCallbacks):
        """
        This is the start of the debugger.
        """
        import os
        
        from dispatcher.core.Util import ConfigReader, unique_file_name
        from dispatcher.core.structures.Tracer.Config.config import ConfigFile as ConfigFile
        
        #Get the root IDA directory in order to locate the config.xml file
        root_dir = os.path.join( idc.GetIdaDirectory() ,"plugins")
        ini_path = os.path.join(root_dir,"settings.ini")

        configReader = ConfigReader()
        configReader.Read(ini_path)
        
       # self.removeBreakpoints()

        self.windowsFileIO       = funcCallbacks['windowsFileIO']
        self.windowsNetworkIO    = funcCallbacks['windowsNetworkIO']
        self.linuxFileIO         = funcCallbacks['linuxFileIO'] 
        self.interactivemodeCallback  = funcCallbacks['interactivemodeCallback']
                
        #register the hotkey for marking the starting point for taint tracking
        taintStart_ctx = idaapi.add_hotkey("Shift-A", self.taintStart)
        self.taintStart = None
        #register the hotkey for marking the stopping point for taint tracking
        taintStop_ctx = idaapi.add_hotkey("Shift-Z", self.taintStop)
        self.taintStop = None

        configFile = configReader.configFile
        
        #Print( configFile )
        #Call ConfigFile to grab all configuration information from the config.xml file
        self.config = ConfigFile(configFile)
        
        (processName, osType, osArch) = self.getProcessInfo()

        self.processConfig = self.createProcessConfig(processName, osType, osArch)

        filePath = os.path.splitext(configReader.traceFile)
        processBasename = os.path.splitext(processName)
        
        self.tracefile = filePath[0] + "_" + processBasename[0] + filePath[1]
        self.tracefile = unique_file_name(self.tracefile)
        Print(self.tracefile)
        
        traceFileName = os.path.splitext(self.tracefile)
        self.treeTracefile = traceFileName[0] + ".idb"
        
        self.logger = None
        logfile = traceFileName[0] + ".log"
        
        self.initLogging(logfile,configReader.logging,configReader.debugging)
 
        print "IDATrace init called."    
示例#3
0
class IDATrace():
    
    def __init__(self,funcCallbacks):
        """
        This is the start of the debugger.
        """
        import os
        
        from dispatcher.core.Util import ConfigReader, unique_file_name
        from dispatcher.core.structures.Tracer.Config.config import ConfigFile as ConfigFile
        
        #Get the root IDA directory in order to locate the config.xml file
        root_dir = os.path.join( idc.GetIdaDirectory() ,"plugins")
        ini_path = os.path.join(root_dir,"settings.ini")

        configReader = ConfigReader()
        configReader.Read(ini_path)
        
       # self.removeBreakpoints()

        self.windowsFileIO       = funcCallbacks['windowsFileIO']
        self.windowsNetworkIO    = funcCallbacks['windowsNetworkIO']
        self.linuxFileIO         = funcCallbacks['linuxFileIO'] 
        self.interactivemodeCallback  = funcCallbacks['interactivemodeCallback']
                
        #register the hotkey for marking the starting point for taint tracking
        taintStart_ctx = idaapi.add_hotkey("Shift-A", self.taintStart)
        self.taintStart = None
        #register the hotkey for marking the stopping point for taint tracking
        taintStop_ctx = idaapi.add_hotkey("Shift-Z", self.taintStop)
        self.taintStop = None

        configFile = configReader.configFile
        
        #Print( configFile )
        #Call ConfigFile to grab all configuration information from the config.xml file
        self.config = ConfigFile(configFile)
        
        (processName, osType, osArch) = self.getProcessInfo()

        self.processConfig = self.createProcessConfig(processName, osType, osArch)

        filePath = os.path.splitext(configReader.traceFile)
        processBasename = os.path.splitext(processName)
        
        self.tracefile = filePath[0] + "_" + processBasename[0] + filePath[1]
        self.tracefile = unique_file_name(self.tracefile)
        Print(self.tracefile)
        
        traceFileName = os.path.splitext(self.tracefile)
        self.treeTracefile = traceFileName[0] + ".idb"
        
        self.logger = None
        logfile = traceFileName[0] + ".log"
        
        self.initLogging(logfile,configReader.logging,configReader.debugging)
 
        print "IDATrace init called."    
        
    def initLogging(self,logfile,bLog,bDbg):

        self.logger = logging.getLogger('IDATrace')
        
        logging.basicConfig(filename=logfile,
                                    filemode='w',
                                    format='%(asctime)s,%(msecs)d %(name)s %(levelname)s %(message)s',
                                    datefmt='%H:%M:%S',
                                    level=logging.INFO)

        if bLog:
            Print("Logging is turned on.")
            self.logger.disabled = False
        else:
            Print("Logging is turned off.")
            self.logger.disabled = True
        
        if bDbg:
            Print("Log Debug mode is turned on.")
            self.logger.setLevel(logging.DEBUG)


    """
    This function is the callback function when the user hits the Shift-A hotkey.
    This will set the starting break point for our interactive tainting
    """
    def taintStart(self):

        Print("Taint Start pressed!")
        #Remove the starting breakpoint
        if self.taintStart is not None:
            idc.DelBpt(self.taintStart)
        
        #Add a new starting breakpoint
        self.taintStart = idc.here()
        instruction =  idc.GetDisasm(self.taintStart)
        Print( instruction )
        idc.AddBpt(self.taintStart)
        idc.SetBptAttr(self.taintStart, idc.BPT_BRK, 0)
        
        callbackAddr = "interactivemodeCallback.startTrace()"
        customCallbackFuncs = ['ReadFile','recv']
        
        for callbackFunc in customCallbackFuncs:
            if callbackFunc in instruction:
                callbackAddr = "interactivemodeCallback." + callbackFunc + "()"
                Print("Found callback function %s for interactive mode" % callbackAddr)
                break
        
        idc.SetBptCnd(self.taintStart, callbackAddr)
    
    """
    This function is the callback function when the user hits the Shift-Z hotkey.
    This will set the stopping break point for our interactive tainting
    """           
    def taintStop(self):

        Print("Taint Stop pressed!")
        #Remove the stopping breakpoint
        if self.taintStop is not None:
            idc.DelBpt(self.taintStop)
        
        #Add a new stopping breakpoint
        self.taintStop = idc.here()
        Print( idc.GetDisasm(self.taintStop) )
        idc.AddBpt(self.taintStop)
        idc.SetBptAttr(self.taintStop, idc.BPT_BRK, 0)
        idc.SetBptCnd(self.taintStop, "interactivemodeCallback.stopTrace()")
        
    def getRunningProcesses(self,process_name):

        numOfProcessesRunning = idc.GetProcessQty()
        Print ("Found %d running processes" % (numOfProcessesRunning))
        
        Print("Searching for %s" % process_name )
        
        for i in range(numOfProcessesRunning):
            #Print("Process ID=[%d], %s" % (idc.GetProcessPid(i),idc.GetProcessName(i) ))
            
            if process_name in idc.GetProcessName(i):
                return idc.GetProcessPid(i)

        return -1
               
    def getProcessInfo(self):

        #Get basic information from the file being Debugged
        idainfo = idaapi.get_inf_structure()

        #Get the name of the input file we want to trace
        app_name = idc.GetInputFile()

        Print ("The input file is %s" % app_name )

        #Check to see what type of file we're tracing
        #And set up the proper debugger and input monitor
        if idainfo.filetype == idaapi.f_PE:
            Print ("Windows PE file" )
            os_type = "windows"
        
        elif idainfo.filetype == idaapi.f_MACHO:
            Print ("Mac OSX Macho file")
            os_type = "macosx"
            #debugger = "macosx"
            #checkInput = InputMonitor.checkMacLibs
        
        elif idainfo.filetype == idaapi.f_ELF:
            Print ("Linux ELF file")
            os_type = "linux"
            #debugger = "linux"
            #checkInput = InputMonitor.checkLinuxLibs
        
        else:
            Print ("Unknown binary, unable to debug")
            return None
            
        #Check the debugged executable if its 32 or 64bit
        if idainfo.is_64bit():
            Print("This binary is 64 bit")
            os_arch = "64"
        elif idainfo.is_32bit():
            Print( "This binary is 32 bit" )
            os_arch = "32"
        else:
            Print( "Bad binary. ARM processor?" )
            os_arch = "ARM"
            
        #Get the file type for the executable being debugger
        fileType = idaapi.get_file_type_name()
        #For ARM libraries returns 'ELF for ARM (Shared object)
        Print( fileType )
        
        return (app_name,os_type,os_arch)
    
    def getProcessConfig(self):
        return self.processConfig
    
    def setProcessConfig(self,processConfig):
        self.config.write(processConfig)
    
    def createProcessConfig(self,name,osType,osArch):
        import os

        from dispatcher.core.structures.Tracer.Config.config import ProcessConfig as ProcessConfig
        
        processConfig = self.config.read(name,osType,osArch)
        
        if processConfig is None:
            processConfig = ProcessConfig()
            processConfig.name = name
            processConfig.osType = osType
            processConfig.osArch = osArch
            processConfig.application = name
            processConfig.path = name
            processConfig.port = "0"
            processConfig.remote = "False"
            
            if osType == "macosx":
                processConfig.debugger = "macosx"
            elif osType == "windows":
                processConfig.debugger = "win32"
            elif osType == "linux":
                processConfig.debugger = "linux"
                
            if osArch == "ARM":
                processConfig.debugger = "Remote ARM Linux/Android debugger"
                #processConfig.debugger = "Remote GDB debugger"
            
            self.config.write(processConfig)
            Print( "Saving new process configuration" )
            
        return processConfig
    
    def setDebuggerOptions(self,processConfig,interactiveMode):
        
        if processConfig.getOsArch() == 'ARM':
            from dispatcher.core.structures.Tracer.ETDbgHookMobile import ETDbgHookMobile as ETDbgHook
            port = 23946
            host = "localhost"
            _pass = ""
        else:
            from dispatcher.core.structures.Tracer.ETDbgHook import ETDbgHook as ETDbgHook
            port = 0
            host = ""
            _pass = ""
 
        path  = processConfig.getPath()

        application = processConfig.getApplication()
        args  = processConfig.getArgs()
        sdir  = processConfig.getSdir()

        debugger = processConfig.getDebugger()
        remote = processConfig.getRemote()=="True"
        
        if remote:
            port  = int(processConfig.getPort())
            host  = processConfig.getHost()
            _pass = processConfig.getPass()
            
        #Use the win32 debugger as our debugger of choice
        #You can can between these debuggers: win32, linux, mac
        idc.LoadDebugger(debugger,remote)
        
        #Set the process parameters, dont know if this actually worked (Should test it)
        idc.SetInputFilePath(path)
        
        idaapi.set_process_options(application,args,sdir,host,_pass,port)
        
        if interactiveMode:
            Print("Using interactive mode.")
        else:
            Print("Using non-interactive mode.")

        EThook = ETDbgHook(self.tracefile,self.treeTracefile,self.logger,interactiveMode)
        EThook.hook()
        EThook.steps = 0
        
        return EThook
             
    def run(self,processConfig):

        from dispatcher.core.structures.Tracer import InputMonitor as InputMonitor
        from dispatcher.core.structures.Tracer.Arch.x86.Windows import WindowsApiCallbacks as WindowsApiCallbacks
        from dispatcher.core.structures.Tracer.Arch.x86.Linux import LinuxApiCallbacks as LinuxApiCallbacks

        EThook = self.setDebuggerOptions(processConfig,False)
        filters = dict()
        
        os_type = processConfig.getOsType()
        fileFilter = processConfig.getFileFilter()
        networkFilter = processConfig.getNetworkFilter()

        if os_type == "macosx":
            Print( "Setting MacOsxApiCallbacks" )
            EThook.checkInput  = InputMonitor.checkMacLibs

        elif os_type == "windows":
            Print( "Setting WindowsApiCallbacks" )
            
            EThook.checkInput =  InputMonitor.checkWindowsLibs
            
            if fileFilter is not None:
                Print( "Setting file filters for windows" )
                filters['file'] = fileFilter
                EThook.bCheckFileIO = True
                self.windowsFileIO.SetDebuggerInstance(EThook)
                self.windowsFileIO.SetFilters(filters)
                self.windowsFileIO.SetLoggerInstance(self.logger)
            
            if networkFilter is not None:
                Print( "Setting network filters for windows" )
                filters['network'] = networkFilter
                EThook.bCheckNetworkIO = True
                self.windowsNetworkIO.SetDebuggerInstance(EThook)
                self.windowsNetworkIO.SetFilters(filters)
                self.windowsNetworkIO.SetLoggerInstance(self.logger)

        elif os_type == "linux":
            Print( "Setting LinuxsApiCallbacks" )
            
            EThook.checkInput =  InputMonitor.checkLinuxLibs
            
            if fileFilter is not None:
                filters['file'] = fileFilter
                EThook.bCheckFileIO = True
                self.linuxFileIO.SetDebuggerInstance(EThook)
                self.linuxFileIO.SetFilters(filters)
                self.linuxFileIO.SetLoggerInstance(self.logger)
            
            if networkFilter is not None:
                filters['network'] = networkFilter
                EThook.bCheckNetworkIO = True
                self.linuxNetworkIO.SetDebuggerInstance(EThook)
                self.linuxNetworkIO.SetFilters(filters)
                self.linuxNetworkIO.SetLoggerInstance(self.logger)
   
        self.logger.info("Starting to trace..please wait...")
        idaapi.run_to(idaapi.cvar.inf.maxEA)
    
    def interactive(self,processConfig):

        from dispatcher.core.structures.Tracer import InteractivemodeCallbacks as InteractivemodeCallbacks
        
        EThook = self.setDebuggerOptions(processConfig,True)
        
        self.interactivemodeCallback.SetDebuggerInstance(EThook)
        self.interactivemodeCallback.SetLoggerInstance(self.logger)
        
        idaapi.run_to(idaapi.cvar.inf.maxEA)
        
    def attach(self,processConfig):

        from dispatcher.core.structures.Tracer import InteractivemodeCallbacks as InteractivemodeCallbacks
        
        EThook = self.setDebuggerOptions(processConfig,True)
        
        self.interactivemodeCallback.SetDebuggerInstance(EThook)
        self.interactivemodeCallback.SetLoggerInstance(self.logger)
        
        process_name = processConfig.getApplication()
        PID = self.getRunningProcesses(process_name)

        self.logger.info("Attaching to %s to generate a trace..please wait..." % process_name)
                
        if PID == -1:
            idc.Warning("%s is not running.  Please start the process first." % process_name)
        else:
            ret = idc.AttachProcess(PID, -1)