Esempio n. 1
0
    def do_replay(self):
        """
        This function replays the last Session. This function will later implement also probes to test when the process
        is crashing
        """
        log.info("Starting the full Replay")
        with open(self.project.project_dir + "/frida_fuzzer.history") as fp:
            for line in fp:
                pkt_file, seed = line.split("|")
                try:
                    # if libradamsa is not used, we call it as a subprocess and won't cache file contents
                    if not use_libradamsa():
                        fuzz_pkt = check_output(
                            ["radamsa", "-s",
                             str(seed.strip()), pkt_file])
                        # kind of arbitrary size limit, probably change this if you're fuzzing something
                        # else than Bluetooth protocols
                        if len(fuzz_pkt) > 672:
                            fuzz_pkt = fuzz_pkt[:672]
                    else:
                        if pkt_file not in self.corpus_cache:
                            input_pkt_data = b''
                            with open(pkt_file, 'rb') as input_pkt_file:
                                self.corpus_cache[
                                    pkt_file] = input_pkt_file.read()

                        fuzz_pkt = radamsa_mutate(self.corpus_cache[pkt_file],
                                                  672, int(seed))

                    # do any protocol or target specific transformations on the fuzzing payload
                    # if the user did not specify this function it will just return the untouched
                    # payload
                    fuzz_pkt = binascii.unhexlify(
                        self.frida_script.process_payload(fuzz_pkt.hex()))

                    if self.project.debug:
                        open(self.project.debug_dir + "/history",
                             "a").write("file: {} seed: {} \n{}\n".format(
                                 pkt_file,
                                 seed,
                                 fuzz_pkt,
                             ))
                    coverage = self.get_coverage_of_payload(
                        fuzz_pkt, pkt_file, None)
                    log.info("Current iteration: " +
                             time.strftime("%Y-%m-%d %H:%M:%S") +
                             " [seed=%d] [file=%s]" %
                             (int(seed.strip()), pkt_file))
                except (frida.TransportError,
                        frida.InvalidOperationError) as e:
                    log.success("doReplay: Got a frida error: " + str(e))
                    log.success("Current iteration: " +
                                time.strftime("%Y-%m-%d %H:%M:%S") +
                                " [seed=%d] [file=%s]" %
                                (int(seed.strip()), pkt_file))
                    log.success("Server Crashed! Lets narrow it down")
                    # crash_file = self.crash_dir + time.strftime("/%Y%m%d_%H%M%S_crash")
                    # with open(crash_file, "wb") as f:
                    #    f.write(fuzz_pkt)
                    # log.info("Payload is written to " + crash_file)
                    return False

                if coverage is None:
                    log.warn("No coverage was generated for [%d] %s!" %
                             (seed, pkt_file))
        log.info("Sending Empty Package to verify the crashing server")
        try:
            coverage = self.get_coverage_of_payload(b'FOOBAR')
        except (frida.TransportError, frida.InvalidOperationError) as e:
            log.success("Server Crashed! Lets narrow it down")
            # TODO
            # Rabbit Mode here

        log.warn(
            "History did not crash the Server! Might be due to some race conditions."
        )
        return False
Esempio n. 2
0
    def do_iteration(self, seed=None, corpus=None):
        if seed is None:
            seed = self.project.seed
        if corpus is None:
            corpus = self.corpus

        start_time = time.time()
        for pkt_file in corpus:
            # log.update("[seed=%d] " % seed + time.strftime("%Y-%m-%d %H:%M:%S") + " %s" % pkt_file)
            #log.info(time.strftime("%Y-%m-%d %H:%M:%S") + " %s" % pkt_file)
            start = ms_time_now()
            if not use_libradamsa():
                fuzz_pkt = check_output(["radamsa", "-s", str(seed), pkt_file])
                if len(fuzz_pkt) > 672:
                    fuzz_pkt = fuzz_pkt[:672]
            else:
                if pkt_file not in self.corpus_cache:
                    log.finish_update("%s not in cache" % pkt_file)
                    input_pkt_data = b''
                    with open(pkt_file, 'rb') as input_pkt_file:
                        self.corpus_cache[pkt_file] = input_pkt_file.read()

                (fuzz_pkt,
                 fuzz_pkt_len) = radamsa_mutate(self.corpus_cache[pkt_file],
                                                672, seed)
                fuzz_pkt = fuzz_pkt[:fuzz_pkt_len]
            end = ms_time_now()
            self.mutation_time += end - start

            # do any protocol or target specific transformations on the fuzzing payload
            # if the user did not specify this function it will just return the untouched
            # payload
            try:
                start = ms_time_now()
                fuzz_bin = self.frida_script.process_payload(fuzz_pkt.hex())
                fuzz_pkt = binascii.unhexlify(fuzz_bin)
                end = ms_time_now()
                self.process_payload_time += end - start
            except:
                pass

            # Writing History file for replaying
            open(self.project.project_dir + "/frida_fuzzer.history",
                 "a").write(str(pkt_file) + "|" + str(seed) + "\n")

            try:
                start = ms_time_now()
                coverage = self.get_coverage_of_payload(
                    fuzz_pkt, pkt_file, corpus)
                end = ms_time_now()
                self.get_coverage_of_payload_time += end - start
            except (frida.TransportError, frida.InvalidOperationError) as e:
                log.warn("doIteration: Got a frida error: " + str(e))
                truncated_payload = str(binascii.hexlify(fuzz_pkt))[:25]
                log.warn("had payload: " + truncated_payload + " [...]")
                log.info("Current iteration: " +
                         time.strftime("%Y-%m-%d %H:%M:%S") +
                         " [seed=%d] [file=%s]" % (seed, pkt_file))
                crash_file = self.project.crash_dir + time.strftime(
                    "/%Y%m%d_%H%M%S_crash")
                with open(crash_file + "_" + str(self.project.pid), "wb") as f:
                    f.write(fuzz_pkt)
                log.info("Payload is written to " + crash_file)
                self.project.crashes += 1
                return False

            if coverage is None:
                log.warn("No coverage was generated for [%d] %s!" %
                         (seed, pkt_file))
                continue

            if not coverage.issubset(self.accumulated_coverage):
                # New basic blocks covered!
                log.info("Found new path: [%d] %s" % (seed, pkt_file))
                newfile = open(
                    self.project.corpus_dir + "/" + str(seed) + "_" +
                    pkt_file.split("/")[-1], "wb")
                newfile.write(fuzz_pkt)
                newfile.close()

                cov_file = self.project.coverage_dir + "/" + pkt_file.split(
                    "/")[-1]
                write_drcov_file(self.modules, coverage, cov_file)
                write_drcov_file(
                    self.modules,
                    coverage.difference(self.accumulated_coverage),
                    cov_file + "_diff")

                self.project.last_new_path = seed
                self.accumulated_coverage = self.accumulated_coverage.union(
                    coverage)

            self.total_executions += 1

        end_time = time.time()
        speed = len(corpus) / (end_time - start_time)
        avg_speed = self.total_executions / (end_time - self.start_time)
        self.current_speed_avg = avg_speed

        log.finish_update(
            "[seed=%d] speed=[%3d exec/sec (avg: %d)] coverage=[%d bblocks] corpus=[%d files] "
            "last new path: [%d] crashes: [%d]" %
            (seed, speed, avg_speed, len(self.accumulated_coverage),
             len(corpus), self.project.last_new_path, self.project.crashes))
        return True