예제 #1
0
def doIntercept(config, interceptorPort, targetPort):
    localHost = "0.0.0.0"
    targetHost = "localhost"

    config["baseport"] = targetPort

    # run the targetserver, as configured in config
    serverManager = simpleservermanager.SimpleServerManager(
        config, 0, targetPort)
    isStarted = serverManager.start()
    if not isStarted:
        print("Could not start server, check its output")
        return

    # test connection
    networkManager = networkmanager.NetworkManager(config, targetPort)

    if not networkManager.debugServerConnection():
        return

    # start mitm server
    if config["ipproto"] is "tcp":
        performTcpIntercept(config, localHost, interceptorPort, targetHost,
                            targetPort)
    else:
        performUdpIntercept(config, localHost, interceptorPort, targetHost,
                            targetPort)
예제 #2
0
    def _verify(self, crashData, serverManager):
        # start the server in the background
        self.networkManager = networkmanager.NetworkManager(
            self.config, self.config["target_port"])
        self.startChild(serverManager)

        # wait for ok (pid) from child that the server has started
        data = self.queue_sync.get()
        serverPid = data[1]
        self.serverPid = serverPid
        logging.info("Verifier: Server pid: " + str(serverPid))

        res = self.networkManager.debugServerConnection()
        if not res:
            logging.error("Could not connect")
            return None

        logging.info("Verifier: Sending fuzzed messages")
        self.networkManager.sendMessages(crashData.corpusData.networkData)

        # get crash result data from child
        #   or empty if server did not crash
        # serverCrashData is type verifier:ServerCrashData
        try:
            logging.info("Verifier: Wait for crash data")
            (t, serverCrashData) = self.queue_sync.get(
                True, sleeptimes["max_server_run_time"])
            serverStdout = self.queue_out.get()

            # it may be that the debugServer detects a process exit
            # (e.g. port already used), and therefore sends an
            # empty result. has to be handled.
            if serverCrashData:
                logging.info("Verifier: I've got a crash")
                print("Verifier: crash verified: %s: %s " %
                      (crashData.filename, serverCrashData.faultAddress))
                serverCrashData.setProcessStdout(serverStdout)
            else:
                logging.error("Verifier: Some server error:")
                logging.error("Verifier: Output: " + serverStdout)

            return serverCrashData
        except Queue.Empty:
            logging.info("Verifier: no crash on: %s" % (crashData.filename))
            print("Verifier: no crash on: %s" % (crashData.filename))
            self.stopChild()
            return None

        return None
예제 #3
0
파일: verifier.py 프로젝트: warsang/ffw
    def _verify(self, outcome, targetPort, debugServerManager):
        # start server in background
        # TODO move this to verifyOutDir (more efficient?)

        self.networkManager = networkmanager.NetworkManager(
            self.config, targetPort)
        self.startChild(debugServerManager)

        # wait for ok (pid) from child that the server has started
        data = self.queue_sync.get()
        serverPid = data[1]
        self.serverPid = serverPid
        logging.info("Verifier: Server pid: " + str(serverPid))
        logging.info("Verifier: Server Port: " + str(targetPort))

        res = self.networkManager.debugServerConnection()
        if not res:
            return None

        logging.info("Verifier: Sending fuzzed messages")
        self.networkManager.sendMessages(outcome["fuzzIterData"]["fuzzedData"])

        # get crash result data from child
        #   or empty if server did not crash
        try:
            logging.info("Verifier: Wait for crash data")
            (t, crashData) = self.queue_sync.get(
                True, sleeptimes["max_server_run_time"])
            serverStdout = self.queue_out.get()

            # it may be that the debugServer detects a process exit
            # (e.g. port already used), and therefore sends an
            # empty result. has to be handled.
            if crashData:
                logging.info("Verifier: I've got a crash: ")
                crashData.setProcessStdout(serverStdout)
            else:
                logging.error("Verifier: Some server error:")
                logging.error("Verifier: Output: " + serverStdout)

            return crashData
        except Queue.Empty:
            self._handleNoCrash()
            self.stopChild()
            return None

        return None
예제 #4
0
    def realDoActualFuzz(self):
        """
        The main fuzzing loop.

        all magic is performed here
        sends results via queue to the parent
        Only called once, by the fuzzingmaster
        """
        if "DebugWithFile" in self.config:
            utils.setupSlaveLoggingWithFile(self.threadId)

        random.seed(self.initialSeed)
        logging.info("Setup fuzzing..")
        signal.signal(signal.SIGINT, signal_handler)
        if 'use_netnamespace' in self.config and self.config[
                'use_netnamespace']:
            targetPort = self.config["target_port"]
        else:
            targetPort = self.config["target_port"] + self.threadId

        self.corpusManager = CorpusManager(self.config)
        self.corpusManager.loadCorpusFiles()
        if self.corpusManager.getCorpusCount() == 0:
            logging.error("No corpus input data found in: " +
                          self.config['input_dir'])
            return

        mutatorInterface = MutatorInterface(self.config, self.threadId)

        self.serverManager = ServerManager(self.config, self.threadId,
                                           targetPort)
        self.networkManager = networkmanager.NetworkManager(
            self.config, targetPort)

        self.iterStats = {
            "count": 0,  # number of iterations
            "crashCount": 0,  # number of crashes, absolute
            "startTime": time.time(),
            "lastUpdateTime": time.time(),
        }
        sendDataResult = None
        previousCorpusData = None

        # If we do not manage the server by ourselfs, disable it
        if 'disableServer' in self.config and self.config['disableServer']:
            self.serverManager.dis()
        else:
            self.serverManager.start()

        if not self.networkManager.waitForServerReadyness():
            logging.error("Error: Could not connect to server.")
            # TODO: better error, because server could not be started. stdout?
            return

        print(str(self.threadId) + " Start fuzzing...")
        self.queue.put((self.threadId, 0, 0, 0))

        corpusData = None
        while True:
            self.updateStats()
            logging.debug("\n\n")
            logging.debug("A fuzzing loop...")

            if self.config["debug"]:
                # lets sleep a bit
                time.sleep(0.5)

            selectedCorpusData = self.corpusManager.getRandomCorpus()

            # save this iteration data for future crashes
            # we do this at the start, not at the end, so we have to
            # only write it once
            previousCorpusData = corpusData
            corpusData = None

            # previous fuzz generated a crash
            if not self.networkManager.openConnection():
                if previousCorpusData is None:
                    logging.warn(
                        "Detected crash, but we didnt yet send any bad data?!")
                    continue

                self._handleCrash(previousCorpusData, 'A')
                continue

            corpusData = mutatorInterface.fuzz(selectedCorpusData)

            sendDataResult = self.networkManager.sendPartialPreData(
                corpusData.networkData)
            if not sendDataResult:
                logging.info(" B Could not send, possible crash? (predata)")
                if self.networkManager.testServerConnection():
                    logging.info(" B Broken connection... continue")
                    self.networkManager.closeConnection()
                    continue
                else:
                    # TODO really previousCorpusData? i think so
                    self._handleCrash(previousCorpusData, 'B')
                    self.networkManager.closeConnection()
                    self.serverManager.restart()
                    continue

            sendDataResult = self.networkManager.sendPartialPostData(
                corpusData.networkData)
            if not sendDataResult:
                logging.info(" C Could not send, possible crash? (postdata)")
                if self.networkManager.testServerConnection():
                    logging.info("C Broken connection... continue")
                    self.networkManager.closeConnection()
                    continue
                else:
                    self._handleCrash(corpusData, 'C')
                    self.networkManager.closeConnection()
                    continue

            # restart server periodically
            if (self.iterStats["count"] > 0 and self.iterStats["count"] %
                    self.config["restart_server_every"] == 0):

                if not self.networkManager.testServerConnection():
                    self._handleCrash(corpusData, 'D')
                    self.networkManager.closeConnection()

                logging.info("Restart server periodically: " +
                             str(self.iterStats["count"]))
                self.serverManager.restart()
                if not self.networkManager.testServerConnection():
                    logging.error(
                        "Error: Could not connect to server after restart. abort."
                    )
                    return

                if self.iterStats[
                        'count'] > 0 and self.iterStats['count'] % 300 == 0:
                    self.networkManager.tuneTimeouts(
                        self.corpusManager.getMaxLatency())

        # all done, terminate server
        self.serverManager.stopServer()
예제 #5
0
파일: fuzzingslave.py 프로젝트: warsang/ffw
    def doActualFuzz(self):
        """
        The main fuzzing loop.

        all magic is performed here
        sends results via queue to the parent
        Only called once, by the fuzzingmaster
        """
        global GLOBAL_SLEEP

        if "DebugWithFile" in self.config:
            utils.setupSlaveLoggingWithFile(self.threadId)

        random.seed(self.initialSeed)
        logging.info("Setup fuzzing..")
        signal.signal(signal.SIGINT, signal_handler)
        targetPort = self.config["baseport"] + self.threadId
        serverManager = simpleservermanager.SimpleServerManager(
            self.config, self.threadId, targetPort)
        networkManager = networkmanager.NetworkManager(self.config, targetPort)

        iterStats = {
            "count": 0,  # number of iterations
            "crashCount": 0,  # number of crashes, absolute
            "startTime": time.time(),
            "lastUpdateTime": time.time(),
        }
        sendDataResult = None
        previousFuzzingIterationData = None

        # start server, or not
        if 'disableServer' in self.config and self.config['disableServer']:
            serverManager.dis()
        serverManager.start()

        if not networkManager.waitForServerReadyness():
            logging.error("Error: Could not connect to server.")
            # TODO: better error, because server could not be started. stdout?
            return

        print(str(self.threadId) + " Start fuzzing...")
        self.queue.put((self.threadId, 0, 0, 0))

        fuzzingIterationData = None
        while True:
            self.updateStats(iterStats)
            logging.debug("\n\n")
            logging.debug("A fuzzing loop...")

            if self.config["debug"]:
                # lets sleep a bit
                time.sleep(0.5)

            selectedInput = self.getRandomInput()

            # save this iteration data for future crashes
            # we do this at the start, not at the end, so we have to
            # only write it once
            previousFuzzingIterationData = fuzzingIterationData
            fuzzingIterationData = None

            # previous fuzz generated a crash
            if not networkManager.openConnection():
                logging.info("Detected Crash (A)")
                iterStats["crashCount"] += 1
                srvCrashData = serverManager.getCrashData()
                crashData = FuzzingCrashData(srvCrashData)
                crashData.setFuzzerPos("A")
                self.exportFuzzResult(crashData, previousFuzzingIterationData)
                serverManager.restart()
                continue

            fuzzingIterationData = fuzzingiterationdata.FuzzingIterationData(
                self.config, selectedInput)
            if not fuzzingIterationData.fuzzData():
                logging.error("Could not fuzz the data")
                return

            sendDataResult = self.sendPreData(networkManager,
                                              fuzzingIterationData)
            if not sendDataResult:
                logging.info(" B Could not send, possible crash? (predata)")
                if networkManager.testServerConnection():
                    logging.info(" B Broken connection... continue")
                    networkManager.closeConnection()
                    continue
                else:
                    logging.info("Detected Crash (B)")
                    iterStats["crashCount"] += 1
                    srvCrashData = serverManager.getCrashData()
                    crashData = FuzzingCrashData(srvCrashData)
                    crashData.setFuzzerPos("B")
                    # TODO really previousFuzzingIterationData? i think so
                    self.exportFuzzResult(crashData,
                                          previousFuzzingIterationData)
                    networkManager.closeConnection()
                    serverManager.restart()
                    continue

            sendDataResult = self.sendData(networkManager,
                                           fuzzingIterationData)
            if not sendDataResult:
                logging.info(" C Could not send, possible crash? (postdata)")
                if networkManager.testServerConnection():
                    logging.info("C Broken connection... continue")
                    networkManager.closeConnection()
                    continue
                else:
                    logging.info("Detected Crash (C)")
                    iterStats["crashCount"] += 1
                    srvCrashData = serverManager.getCrashData()
                    crashData = FuzzingCrashData(srvCrashData)
                    crashData.setFuzzerPos("C")
                    self.exportFuzzResult(crashData, fuzzingIterationData)
                    networkManager.closeConnection()
                    serverManager.restart()
                    continue

            # restart server periodically
            if iterStats["count"] > 0 and iterStats["count"] % self.config[
                    "restart_server_every"] == 0:
                if not networkManager.testServerConnection():
                    logging.info("Detected Crash (D)")
                    iterStats["crashCount"] += 1
                    srvCrashData = serverManager.getCrashData()
                    crashData = FuzzingCrashData(srvCrashData)
                    crashData.setFuzzerPos("D")
                    self.exportFuzzResult(crashData, fuzzingIterationData)
                    networkManager.closeConnection()

                logging.info("Restart server periodically: " +
                             str(iterStats["count"]))
                serverManager.restart()
                if not networkManager.testServerConnection():
                    logging.error(
                        "Error: Could not connect to server after restart. abort."
                    )
                    return

        # all done, terminate server
        serverManager.stopServer()
예제 #6
0
    def realDoActualFuzz(self):
        #logging.basicConfig(level=logging.DEBUG)
        if "debug" in self.config and self.config["debug"]:
            self.config["processes"] = 1

        if "DebugWithFile" in self.config and self.config["DebugWithFile"]:
            utils.setupSlaveLoggingWithFile(self.threadId)

        if 'use_netnamespace' in self.config and self.config[
                'use_netnamespace']:
            targetPort = self.config["target_port"]

        else:
            targetPort = self.config["target_port"] + self.threadId
        self.targetPort = targetPort

        logging.info("Setup fuzzing..")
        random.seed(self.initialSeed)
        signal.signal(signal.SIGINT, signal_handler)

        mutatorInterface = MutatorInterface(self.config, self.threadId)

        self.networkManager = networkmanager.NetworkManager(
            self.config, targetPort)
        self.corpusManager = HonggCorpusManager(self.config)
        self.corpusManager.loadCorpusFiles()
        if self.corpusManager.getCorpusCount() == 0:
            logging.error("No corpus input data found in: " +
                          self.config['input_dir'])
            return
        # watch for new files / corpus
        self.corpusManager.startWatch()

        # start honggfuzz with target binary
        honggfuzzArgs = self._prepareHonggfuzzArgs()
        serverManager = ServerManager(self.config, self.threadId, targetPort,
                                      honggfuzzArgs, True)
        serverManager.start()

        # connect to honggfuzz
        honggComm = honggcomm.HonggComm()
        if honggComm.openSocket(serverManager.process.pid):
            print(" connected to honggfuzz!")
            logging.info("Honggfuzz connection successful")
        else:
            logging.error("Could not connect to honggfuzz socket.")
            return

        # test connection first
        if not self.networkManager.debugServerConnection():
            logging.error("Bootstrap: Could not connect to server.")
            return

        # warmup
        # Send all initial corpus once and ignore new BB commands so we
        # dont add it again.
        # Note that at the end, there may be still commands in the socket
        # queue which we need to ignore on the fuzzing loop.
        initialCorpusIter = iter(self.corpusManager)
        print("Performing warmup. This can take some time.")
        while True:
            logging.debug("A warmup loop...")
            try:
                # this generates errors because multiple processes
                # try to write to stdout
                # sys.stdout.write('.')
                # sys.stdout.flush()
                initialCorpusData = initialCorpusIter.next()
            except StopIteration:
                break

            honggData = honggComm.readSocket()
            if honggData == "Fuzz":
                logging.debug("  Warmup Fuzz: Sending: " +
                              str(initialCorpusData.filename))
                self._connectAndSendData(initialCorpusData)
                honggComm.writeSocket("okay")

            else:
                # We dont really care what the fuzzer sends us
                # BUT it should be always "New!"
                # It should never be "Cras"
                if honggData == "New!":
                    logging.debug(
                        "  Warmup: Honggfuzz answered correctly, received: " +
                        honggData)
                else:
                    logging.warn(
                        "  Warumup: Honggfuzz answered wrong, it should be New! but is: "
                        + honggData)

        # the actual fuzzing
        logging.debug("Warmup finished.")
        logging.info("Performing fuzzing")
        honggCorpusData = None

        # Just assume target is alive, because of the warmup phase
        # this var is needed mainly to not create false-positives, e.g.
        # if the target is for some reason unstartable, it would be detected
        # as crash
        haveCheckedTargetIsAlive = True

        while True:
            logging.debug("A fuzzing loop...")
            self._uploadStats()
            self.corpusManager.checkForNewFiles()
            honggData = None

            try:
                honggData = honggComm.readSocket()
            except Exception as e:
                logging.error("Could not read from honggfuzz socket: " +
                              str(e))
                logging.error("Honggfuzz server crashed? Killed?")
                return

            # honggfuzz says: Send fuzz data via network
            if honggData == "Fuzz":
                couldSend = False

                # are we really sure that the target is alive? If not, check
                if not haveCheckedTargetIsAlive:
                    if not self.networkManager.waitForServerReadyness():
                        logging.error(
                            "Wanted to fuzz, but targets seems down. Force honggfuzz to restart it."
                        )
                        try:
                            honggComm.writeSocket("bad!")
                        except Exception as e:
                            logging.error("Honggfuzz server crashed? Killed?")
                            return
                        self.iterStats["hangCount"] += 1
                    else:
                        haveCheckedTargetIsAlive = True

                # check first if we have new corpus from other threads
                # if yes: send it. We'll ignore New!/Cras msgs by setting:
                #   honggCorpusData = None
                if self.corpusManager.hasNewExternalCorpus():
                    honggCorpusData = None  # ignore results
                    corpus = self.corpusManager.getNewExternalCorpus()
                    corpus.processed = True
                    couldSend = self._connectAndSendData(corpus)

                # just randomly select a corpus, fuzz it, send it
                # honggfuzz will tell us what to do next
                else:
                    self.iterStats["iterCount"] += 1

                    corpus = self.corpusManager.getRandomCorpus()
                    honggCorpusData = mutatorInterface.fuzz(corpus)
                    couldSend = self._connectAndSendData(honggCorpusData)

                if couldSend:
                    # Notify honggfuzz that we are finished sending the fuzzed data
                    try:
                        honggComm.writeSocket("okay")
                    except Exception as e:
                        logging.error("Honggfuzz server crashed? Killed?")
                        return

                    # the correct way is to send SIGIO signal to honggfuzz
                    # https://github.com/google/honggfuzz/issues/200
                    os.kill(serverManager.process.pid, signal.SIGIO)
                else:
                    # target seems to be down. Have honggfuzz restart it
                    # and hope for the best, but check after restart if it
                    # is really up
                    logging.warn(
                        str(self.threadId) +
                        ": Server appears to be down, force restart at iteration "
                        + str(self.iterStats['iterCount']))
                    self.iterStats["hangCount"] += 1
                    try:
                        honggComm.writeSocket("bad!")
                    except Exception as e:
                        logging.error("Honggfuzz server crashed? Killed?")
                        return

                    if self.config['hangsAreCrashes']:
                        self._handleCrash(honggCorpusData, 'hang')
                        self.iterStats["crashCount"] += 1

                    haveCheckedTargetIsAlive = False

            # honggfuzz says: new basic-block found
            #   (from the data we sent before)
            elif honggData == "New!":
                # Warmup may result in a stray message, ignore here
                # If new-corpus-from-other-thread: Ignore here
                if honggCorpusData is not None:
                    logging.info("--[ Adding file to corpus...")
                    self.corpusManager.addNewCorpusData(honggCorpusData)
                    honggCorpusData.getParentCorpus().statsAddNew()

                    self.iterStats["corpusCount"] += 1

            # honggfuzz says: target crashed (yay!)
            elif honggData == "Cras":
                # Warmup may result in a stray message, ignore here
                # If new-corpus-from-other-thread: Ignore here
                if honggCorpusData is not None:
                    logging.info("--[ Adding crash...")
                    self._handleCrash(honggCorpusData, 'honggcomm')
                    self.iterStats["crashCount"] += 1

                # target was down and needs to be restarted by honggfuzz.
                # check if it was successfully restarted!
                haveCheckedTargetIsAlive = False

            elif honggData == "":
                logging.info("Hongfuzz quit, exiting too\n")
                break
            else:
                # This should not happen
                logging.error("--[ Unknown Honggfuzz msg: " + str(honggData))

            # periodically restart server
            if self.iterStats['iterCount'] > 0 and self.iterStats[
                    'iterCount'] % self.config['restart_server_every'] == 0:
                logging.info("restart server periodically at iteration " +
                             str(self.iterStats['iterCount']))
                try:
                    honggComm.writeSocket("bad!")
                except Exception as e:
                    logging.error("Honggfuzz server crashed? Killed?")
                    return

                haveCheckedTargetIsAlive = False

            if self.iterStats['iterCount'] > 0 and self.iterStats[
                    'iterCount'] % 300 == 0:
                self.networkManager.tuneTimeouts(
                    self.corpusManager.getMaxLatency())
예제 #7
0
    def doActualFuzz(self):
        """
        Child thread of fuzzer - does teh actual fuzzing.

        Sends results/stats via queue to the parent.
        Will start the target via honggfuzz, connect to the honggfuzz socket,
        and according to the honggfuzz commands from the socket, send
        the fuzzed messages to the target binary.
        """
        #logging.basicConfig(level=logging.DEBUG)
        self.config["processes"] = 1

        logging.info("Setup fuzzing..")
        random.seed(self.initialSeed)
        signal.signal(signal.SIGINT, signal_handler)
        targetPort = self.config["baseport"] + self.threadId
        self.targetPort = targetPort

        networkManager = networkmanager.NetworkManager(self.config, targetPort)
        self.corpusManager = corpusmanager.CorpusManager(self.config)
        self.corpusManager.initialLoad()
        self.corpusManager.startWatch()

        # start honggfuzz with target binary
        self._startServer()

        # connect with honggfuzz
        honggComm = honggcomm.HonggComm()
        honggComm.openSocket(self.fuzzerPid)

        # warmup
        # Send all initial corpus once and ignore new BB commands so we
        # dont add it again.
        # Note that at the end, there may be still commands in the socket
        # queue which we need to ignore on the fuzzing loop.
        initialCorpusIter = iter(self.corpusManager)
        logging.info("Performing warmup")
        while True:
            logging.debug("A warmup loop...")

            try:
                initialCorpusData = initialCorpusIter.next()
            except StopIteration:
                break

            honggData = honggComm.readSocket()
            if honggData == "Fuzz":
                logging.debug("Fuzz: Warmup send")
                self._connectAndSendData(networkManager, initialCorpusData)
                honggComm.writeSocket("okay")

            else:
                # We dont really care what the fuzzer sends us
                # BUT it should be always "New!"
                # It should never be "Cras"
                logging.debug("received: " + honggData)

        # the actual fuzzing
        logging.info("Performing fuzzing")
        fuzzingIterationData = None
        while True:
            logging.debug("A fuzzing loop...")
            self._uploadStats()
            self.corpusManager.checkForNewFiles()

            honggData = honggComm.readSocket()
            if honggData == "Fuzz":
                # check first if we have new corpus from other threads
                # if yes: send it. We'll ignore New!/Cras msgs by settings
                # fuzzingIterationData = None
                if self.corpusManager.hasNewExternalCorpus():
                    fuzzingIterationData = None  # important
                    corpus = self.corpusManager.getNewExternalCorpus()
                    corpus.processed = True
                    self._connectAndSendData(networkManager, corpus.getData())

                # just randomly select a corpus, fuzz it, (handle result)
                else:
                    self.iterStats["iterCount"] += 1

                    corpus = self.corpusManager.getRandomCorpus()
                    fuzzingIterationData = FuzzingIterationData(
                        self.config, corpus.getData())
                    if not fuzzingIterationData.fuzzData():
                        logging.error("Could not fuzz the data")
                        return

                    self._connectAndSendData(networkManager,
                                             fuzzingIterationData.fuzzedData)

                # send okay to continue honggfuzz
                honggComm.writeSocket("okay")

            elif honggData == "New!":
                # Warmup may result in a stray message, ignore here
                # If new-corpus-from-other-thread: Ignore here
                if fuzzingIterationData is not None:
                    logging.info("--[ Adding file to corpus...")
                    self.corpusManager.addNewCorpus(
                        fuzzingIterationData.fuzzedData,
                        fuzzingIterationData.seed)
                    self.iterStats["corpusCount"] += 1

            elif honggData == "Cras":
                # Warmup may result in a stray message, ignore here
                # If new-corpus-from-other-thread: Ignore here
                if fuzzingIterationData is not None:
                    logging.info("--[ Adding crash...")
                    self._handleCrash(fuzzingIterationData)
                    self.iterStats["crashCount"] += 1

            elif honggData == "":
                logging.info("Hongfuzz quit, exiting too\n")
                break
            else:
                # This should not happen
                logging.error("--[ Unknown: " + str(honggData))
예제 #8
0
    def doActualFuzz(self):
        """
        Child thread of fuzzer - does teh actual fuzzing.

        Sends results/stats via queue to the parent.
        Will start the target via honggfuzz, connect to the honggfuzz socket,
        and according to the honggfuzz commands from the socket, send
        the fuzzed messages to the target binary.

        New fuzzed data will be generated via FuzzingIterationData, where
        the initial data from the corpus is managed by CorpusManager.
        """
        #logging.basicConfig(level=logging.DEBUG)
        if "debug" in self.config and self.config["debug"]:
            self.config["processes"] = 1

        if "DebugWithFile" in self.config:
            utils.setupSlaveLoggingWithFile(self.threadId)

        logging.info("Setup fuzzing..")
        random.seed(self.initialSeed)
        signal.signal(signal.SIGINT, signal_handler)
        targetPort = self.config["baseport"] + self.threadId
        self.targetPort = targetPort

        networkManager = networkmanager.NetworkManager(self.config, targetPort)
        self.corpusManager = corpusmanager.CorpusManager(self.config)
        self.corpusManager.initialLoad()
        self.corpusManager.startWatch()

        # start honggfuzz with target binary
        self._startServer()

        # connect with honggfuzz
        honggComm = honggcomm.HonggComm()
        honggComm.openSocket(self.fuzzerPid)

        # warmup
        # Send all initial corpus once and ignore new BB commands so we
        # dont add it again.
        # Note that at the end, there may be still commands in the socket
        # queue which we need to ignore on the fuzzing loop.
        initialCorpusIter = iter(self.corpusManager)
        logging.info("Performing warmup")
        while True:
            logging.debug("A warmup loop...")

            try:
                initialCorpusData = initialCorpusIter.next()
            except StopIteration:
                break

            honggData = honggComm.readSocket()
            if honggData == "Fuzz":
                logging.debug("Fuzz: Warmup send")
                self._connectAndSendData(networkManager, initialCorpusData)
                honggComm.writeSocket("okay")

            else:
                # We dont really care what the fuzzer sends us
                # BUT it should be always "New!"
                # It should never be "Cras"
                logging.debug("received: " + honggData)

        # the actual fuzzing
        logging.info("Performing fuzzing")
        fuzzingIterationData = None

        # Just assume target is alive, because of the warmup phase
        # this var is needed mainly to not create false-positives, e.g.
        # if the target is for some reason unstartable, it would be detected
        # as crash
        haveCheckedTargetIsAlive = True

        while True:
            logging.debug("A fuzzing loop...")
            self._uploadStats()
            self.corpusManager.checkForNewFiles()

            honggData = honggComm.readSocket()
            # honggfuzz says: Send fuzz data via network
            if honggData == "Fuzz":
                couldSend = False

                # are we really sure that the target is alive? If not, check
                if not haveCheckedTargetIsAlive:
                    if not networkManager.waitForServerReadyness():
                        logging.error(
                            "Wanted to fuzz, but targets seems down. Force honggfuzz to restart it."
                        )
                        honggComm.writeSocket("bad!")
                        self.iterStats["timeoutCount"] += 1
                    else:
                        haveCheckedTargetIsAlive = True

                # check first if we have new corpus from other threads
                # if yes: send it. We'll ignore New!/Cras msgs by setting:
                #   fuzzingIterationData = None
                if self.corpusManager.hasNewExternalCorpus():
                    fuzzingIterationData = None  # ignore results
                    corpus = self.corpusManager.getNewExternalCorpus()
                    corpus.processed = True
                    couldSend = self._connectAndSendData(
                        networkManager, corpus.getData())

                # just randomly select a corpus, fuzz it, send it
                # honggfuzz will tell us what to do next
                else:
                    self.iterStats["iterCount"] += 1

                    corpus = self.corpusManager.getRandomCorpus()
                    fuzzingIterationData = FuzzingIterationData(
                        self.config, corpus.getData(), corpus)
                    if not fuzzingIterationData.fuzzData():
                        logging.error("Could not fuzz the data")
                        return

                    couldSend = self._connectAndSendData(
                        networkManager, fuzzingIterationData.fuzzedData)

                if couldSend:
                    # all ok...
                    honggComm.writeSocket("okay")
                else:
                    # target seems to be down. Have honggfuzz restart it
                    # and hope for the best, but check after restart if it
                    # is really up
                    logging.info("Server appears to be down, force restart")
                    self.iterStats["timeoutCount"] += 1
                    honggComm.writeSocket("bad!")
                    haveCheckedTargetIsAlive = False

            # honggfuzz says: new basic-block found
            #   (from the data we sent before)
            elif honggData == "New!":
                # Warmup may result in a stray message, ignore here
                # If new-corpus-from-other-thread: Ignore here
                if fuzzingIterationData is not None:
                    logging.info("--[ Adding file to corpus...")
                    self.corpusManager.addNewCorpus(
                        fuzzingIterationData.fuzzedData,
                        fuzzingIterationData.seed)
                    fuzzingIterationData.getParentCorpus().statsAddNew()

                    self.iterStats["corpusCount"] += 1

            # honggfuzz says: target crashed (yay!)
            elif honggData == "Cras":
                # Warmup may result in a stray message, ignore here
                # If new-corpus-from-other-thread: Ignore here
                if fuzzingIterationData is not None:
                    logging.info("--[ Adding crash...")
                    self._handleCrash(fuzzingIterationData)
                    self.iterStats["crashCount"] += 1

                # target was down and needs to be restarted by honggfuzz.
                # check if it was successfully restarted!
                haveCheckedTargetIsAlive = False

            elif honggData == "":
                logging.info("Hongfuzz quit, exiting too\n")
                break
            else:
                # This should not happen
                logging.error("--[ Unknown Honggfuzz msg: " + str(honggData))