def main(): if (len(sys.argv) > 2): cfgFile = sys.argv.pop(1) fuzzInst = ADBFuzz(cfgFile) else: print "Missing configuration file!" usage() exit(1) cmd = sys.argv.pop(1) if (cmd == "showdump"): print "Obtaining symbolized trace..." dumpFile = sys.argv[1] libSearchPath = sys.argv[2] minidump = Minidump(dumpFile, libSearchPath) symbolTrace = minidump.getSymbolizedCrashTrace() print "" for frame in symbolTrace: print "#" + frame[0] + "\t" + frame[1] + " at " + frame[2] elif (cmd == "reproduce"): fuzzInst.config.fuzzerFile = sys.argv[1] fuzzInst.config.runTimeout = int(sys.argv[2]) isCrash = True if sys.argv[3] == 'crash': isCrash = True elif sys.argv[3] == 'abort': isCrash = False else: raise Exception("Unknown crash type " + sys.argv[3] + " specified!") if fuzzInst.testCrash(isCrash): exit(0) exit(1) elif (cmd == "run"): fuzzInst.remoteInit() if (len(sys.argv) > 2): fuzzInst.loopFuzz(sys.argv[1]) else: fuzzInst.loopFuzz() elif (cmd == "deploy"): fuzzInst.deploy(sys.argv[1], sys.argv[2]) elif (cmd == "reset"): fuzzInst.reset(sys.argv[1])
def runFuzzer(self): self.remoteInit() # Ensure Fennec isn't running if self.isFennecRunning(): self.stopFennec() # Clean all existing minidumps if not self.clearMinidumps(): raise Exception("Failed to clean existing minidumps") # Start our HTTP server for serving the fuzzer code self.HTTPProcess = self.startHTTPServer() # Start all loggers self.startLoggers() # Start Fennec self.startFennec() # Even though the program is already running, we should grant it # some extra time to load the fuzzer source and start running, # so it isn't directly diagnosed as hanging time.sleep(10); logSize = 0 hangDetected = False forceRestart = False while(self.isFennecRunning() and not self.checkLoggingThreads()): time.sleep(self.config.runTimeout) if not os.path.exists(self.logFile): raise Exception("Logfile not present. If you are using websockets, this could indicate a network problem.") # Poor man's hang detection. Yes, this is a bad # idea, just for the sake of proof-of-concept newLogSize = os.path.getsize(self.logFile) if (logSize == newLogSize): hangDetected = True break else: logSize = newLogSize if newLogSize > self.config.maxLogSize: forceRestart = True break if hangDetected or forceRestart: self.stopFennec() self.stopLoggers() print "Hang detected or running too long, restarting..." else: try: # Fennec died or a logger found something checkCrashDump = True crashUUID = None minidump = None # If Fennec is still running, stop it now if self.isFennecRunning(): checkCrashDump = False self.stopFennec() # Terminate our logging processes first self.stopLoggers() if checkCrashDump: dumps = self.getMinidumps() if (len(dumps) > 1): raise Exception("Multiple dumps detected!") if (len(dumps) < 1): raise Exception("No crash dump detected!") if not self.fetchMinidump(dumps[0]): raise Exception("Failed to fetch minidump with UUID " + dumps[0]) crashUUID = dumps[0] # Copy logfiles shutil.copy2(self.syslogFile, dumps[0] + ".syslog") shutil.copy2(self.logFile, dumps[0] + ".log") minidump = Minidump(dumps[0] + ".dmp", self.config.libDir) else: # We need to generate an arbitrary ID here crashUUID = str(uuid.uuid4()) # Copy logfiles shutil.copy2(self.syslogFile, crashUUID + ".syslog") shutil.copy2(self.logFile, crashUUID + ".log") print "Crash detected. Reproduction logfile stored at: " + crashUUID + ".log" if checkCrashDump: crashTrace = minidump.getCrashTrace() crashType = minidump.getCrashType() print "Crash type: " + crashType print "Crash backtrace:" print "" print crashTrace else: print "Crash type: Abnormal behavior (e.g. Assertion violation)" self.triager.process(crashUUID, minidump, crashUUID + ".syslog", crashUUID + ".log") except Exception, e: print "Error during crash processing: " print traceback.format_exc()
def runFuzzer(self): self.remoteInit() # Ensure Fennec isn't running if self.isFennecRunning(): self.stopFennec() # Clean all existing minidumps if not self.clearMinidumps(): raise Exception("Failed to clean existing minidumps") # Start our HTTP server for serving the fuzzer code self.HTTPProcess = self.startHTTPServer() # Start all loggers self.startLoggers() # Start Fennec self.startFennec() # Even though the program is already running, we should grant it # some extra time to load the fuzzer source and start running, # so it isn't directly diagnosed as hanging time.sleep(10) logSize = 0 hangDetected = False forceRestart = False while (self.isFennecRunning() and not self.checkLoggingThreads()): time.sleep(self.config.runTimeout) if not os.path.exists(self.logFile): raise Exception( "Logfile not present. If you are using websockets, this could indicate a network problem." ) # Poor man's hang detection. Yes, this is a bad # idea, just for the sake of proof-of-concept newLogSize = os.path.getsize(self.logFile) if (logSize == newLogSize): hangDetected = True break else: logSize = newLogSize if newLogSize > self.config.maxLogSize: forceRestart = True break if hangDetected or forceRestart: self.stopFennec() self.stopLoggers() print "Hang detected or running too long, restarting..." else: try: # Fennec died or a logger found something checkCrashDump = True crashUUID = None minidump = None # If Fennec is still running, stop it now if self.isFennecRunning(): checkCrashDump = False self.stopFennec() # Terminate our logging processes first self.stopLoggers() if checkCrashDump: dumps = self.getMinidumps() if (len(dumps) > 1): raise Exception("Multiple dumps detected!") if (len(dumps) < 1): raise Exception("No crash dump detected!") if not self.fetchMinidump(dumps[0]): raise Exception("Failed to fetch minidump with UUID " + dumps[0]) crashUUID = dumps[0] # Copy logfiles shutil.copy2(self.syslogFile, dumps[0] + ".syslog") shutil.copy2(self.logFile, dumps[0] + ".log") minidump = Minidump(dumps[0] + ".dmp", self.config.libDir) else: # We need to generate an arbitrary ID here crashUUID = str(uuid.uuid4()) # Copy logfiles shutil.copy2(self.syslogFile, crashUUID + ".syslog") shutil.copy2(self.logFile, crashUUID + ".log") print "Crash detected. Reproduction logfile stored at: " + crashUUID + ".log" if checkCrashDump: crashTrace = minidump.getCrashTrace() crashType = minidump.getCrashType() print "Crash type: " + crashType print "Crash backtrace:" print "" print crashTrace else: print "Crash type: Abnormal behavior (e.g. Assertion violation)" self.triager.process(crashUUID, minidump, crashUUID + ".syslog", crashUUID + ".log") except Exception, e: print "Error during crash processing: " print traceback.format_exc()