Пример #1
0
    def get_all_mutations(self):
        self.boring_cmps = set()
        offsets_to_lhs_to_rhs_to_info = {}
        num_mut = 0

        orig_run_info = [r for r in self.run_infos if not r.was_colored]
        #assert (len(orig_run_info) == 1)
        if len(orig_run_info) != 1:
            log_redq("Warning: Could not find canonical orig. run info! len(info)=%d" % len(orig_run_info))
            return num_mut, offsets_to_lhs_to_rhs_to_info    

        orig_run_info = orig_run_info[0]
        for addr_to_cmp in [self.addr_to_cmp, self.addr_to_inv_cmp]:
            for addr in addr_to_cmp:
                cmp = addr_to_cmp[addr]
                was_cmp_interessting = False
                if len(cmp.run_info_to_pairs) == len(self.run_infos):
                    for (offsets, lhs, rhs, encoding) in cmp.calc_mutations(orig_run_info, len(self.run_infos)):
                        offsets, lhs, rhs = self.strip_unchanged_bytes_from_mutation_values(offsets, lhs, rhs)
                        was_cmp_interessting = True
                        offsets_to_lhs_to_rhs_to_info[offsets] = offsets_to_lhs_to_rhs_to_info.get(offsets, {})
                        offsets_to_lhs_to_rhs_to_info[offsets][lhs] = offsets_to_lhs_to_rhs_to_info[offsets].get(lhs,{})
                        if not rhs in offsets_to_lhs_to_rhs_to_info[offsets][lhs]:
                            num_mut += 1
                        offsets_to_lhs_to_rhs_to_info[offsets][lhs][rhs] = offsets_to_lhs_to_rhs_to_info[offsets][lhs].get(rhs, MutInfo())
                        offsets_to_lhs_to_rhs_to_info[offsets][lhs][rhs].add_info(addr, encoding)
                if not was_cmp_interessting:
                    self.boring_cmps.add(cmp.addr)
        return num_mut, offsets_to_lhs_to_rhs_to_info
Пример #2
0
 def __perform_rq_dict(self, payload_array, metadata):
     rq_dict = havoc.get_redqueen_dict()
     counter = 0
     seen_addr_to_value = havoc.get_redqueen_seen_addr_to_value()
     if len(payload_array) < 256:
         for addr in rq_dict:
             for repl in rq_dict[addr]:
                 if addr in seen_addr_to_value and (
                         len(seen_addr_to_value[addr]) > 32
                         or repl in seen_addr_to_value[addr]):
                     continue
                 if not addr in seen_addr_to_value:
                     seen_addr_to_value[addr] = set()
                 seen_addr_to_value[addr].add(repl)
                 log_redq("Attempting %s " % repr(repl))
                 for apply_dict in [
                         havoc.dict_insert_sequence,
                         havoc.dict_replace_sequence
                 ]:
                     for i in range(len(payload_array) - len(repl)):
                         counter += 1
                         mutated = apply_dict(payload_array, repl, i)
                         # log_redq("dict_bf %d %s %s"%(i,repr(repl),repr(mutated)))
                         self.execute(mutated, label="rq_dict")
     log_redq("RQ-Dict: Have performed %d iters" % counter)
Пример #3
0
    def __perform_redqueen(self, payload, metadata):
        self.stage_update_label("redq_coloring")

        orig_hash = self.__get_bitmap_hash_robust(payload)
        extension = bytes([207, 117, 130, 107, 183, 200, 143, 154])
        appended_hash = self.__get_bitmap_hash_robust(payload + extension)

        if orig_hash and orig_hash == appended_hash:
            log_slave("Redqueen: input can be extended", self.slave.slave_id)
            payload_array = bytearray(payload + extension)
        else:
            payload_array = bytearray(payload)

        colored_alternatives = self.__perform_coloring(payload_array)
        if colored_alternatives:
            payload_array = colored_alternatives[0]
            assert isinstance(colored_alternatives[0],
                              bytearray), print("!! ColoredAlternatives:",
                                                repr(colored_alternatives[0]),
                                                type(colored_alternatives[0]))
        else:
            log_redq("Input is not stable, skipping..")
            return

        rq_info = RedqueenInfoGatherer()
        rq_info.make_paths(RedqueenWorkdir(self.slave.slave_id, self.config))
        rq_info.verbose = False
        for pld in colored_alternatives:
            if self.execute_redqueen(pld):
                rq_info.get_info(pld)

        rq_info.get_proposals()
        self.stage_update_label("redq_mutate")
        rq_info.run_mutate_redqueen(payload_array, self.execute)
Пример #4
0
Файл: mod.py Проект: vient/kAFL
 def get_info(self, input_data):
     self.num_alternative_inputs += 1
     self.save_rq_data(self.num_alternative_inputs, input_data)
     log_redq("redqueen saving new input %d" % self.num_alternative_inputs)
     with open(
             self.collected_infos_path + "/input_%d.bin" %
         (self.num_alternative_inputs), "wb") as f:
         f.write(input_data)
Пример #5
0
 def blacklist_hash_addr(self, addr):
     self.lock.acquire()
     if not addr in self.blacklisted_hashes:
         log_redq("Blacklist Hash: %x" % addr)
         self.blacklisted_hashes[addr] = 1
         if addr in self.candidate_hashes:
             del self.candidate_hashes[addr]
     self.lock.release()
Пример #6
0
 def add_candidate_hash_addr(self, addr):
     self.lock.acquire()
     if not addr in self.blacklisted_hashes:
         if not addr in self.candidate_hashes:
             log_redq("Hash candidate: %x" % addr)
             self.candidate_hashes[addr] = 1
             self.candidate_file_offsets[addr] = {}
     self.lock.release()
Пример #7
0
 def update_redqueen_blacklist(self, workdir):
     log_redq("update blacklist with: %s" %
              repr(self.blacklisted_compares.keys()))
     with open(workdir.blacklist(), "w") as f:
         for addr in self.blacklisted_compares.keys():
             hexaddr = hex(addr).rstrip("L").lstrip("0x")
             if hexaddr:
                 f.write(hexaddr + "\n")
         f.flush()
         os.fsync(f.fileno())
Пример #8
0
Файл: cmp.py Проект: vient/kAFL
def redqueen_global_config(redq_hammering, redq_do_simple, afl_arith_max):
    global HAMMER_LEA
    global SKIP_SIMPLE
    global AFL_ARITH_MAX

    HAMMER_LEA = redq_hammering
    SKIP_SIMPLE = not redq_do_simple
    AFL_ARITH_MAX = afl_arith_max

    log_redq("Config: hammer=%s, skip_simple=%s, arith_max=%s" %
             (HAMMER_LEA, SKIP_SIMPLE, AFL_ARITH_MAX))
Пример #9
0
    def __respond_verification(self, response):

        jobs = response.data[0]
        methods = response.data[1]

        results = []
        i = 0
        self.comm.slave_locks_A[self.slave_id].acquire()

        while True:
                payload, payload_shm_size = self.q.copy_master_payload(self.comm.get_master_payload_shm(self.slave_id), i, self.comm.get_master_payload_shm_size())

                payload_content_len_init = struct.unpack("I", payload[0:4])[0]

                payload_content_len = perform_trim(payload_content_len_init, self.q.send_payload, self.q.modify_payload_size, self.error_handler)

                if payload_content_len_init != payload_content_len:
                    log_slave("TRIM: " + "{0:.2f}".format(((payload_content_len*1.0)/(payload_content_len_init*1.0))*100.0) + "% (" + str(payload_content_len) + "/" + str(payload_content_len_init) + ")", self.slave_id)

                patches = jobs[0]
                if len(patches) > 0:
                    log_slave("Got payload to fix with size: %d and patches %s"%( payload_content_len, patches), self.slave_id )

                    if len(patches):
                        log_redq("Slave "+str(self.slave_id)+" Orig  Payload: " + repr(payload[4:4+payload_content_len]))
                        hash = HashFixer(self.q, self.redqueen_state)
                        new_payload = hash.try_fix_data(payload[4:4+payload_content_len])

                        if new_payload:
                            log_redq("Slave "+str(self.slave_id)+"Fixed Payload: " + repr("".join(map(chr,new_payload))))
                            payload = payload[:4]+"".join(map(chr,new_payload))
                            self.q.set_payload(new_payload)

                start_time = time.time()
                bitmap = self.q.send_payload(apply_patches=False)
                performance = time.time() - start_time
                log_slave("performance: " + str(1.0/performance) + " -> " + str(performance), self.slave_id)
                break
                    

        if not bitmap:
            log_slave("SHM ERROR....", self.slave_id)

        new_bits = self.q.copy_bitmap(self.comm.get_bitmap_shm(self.slave_id), i, self.comm.get_bitmap_shm_size(),
                                      bitmap, payload, payload_shm_size, effector_mode_hash=None, apply_patches = False)
        if new_bits:
            self.q.copy_mapserver_payload(self.comm.get_mapserver_payload_shm(self.slave_id), i, self.comm.get_mapserver_payload_shm_size())
        
        results.append(FuzzingResult(i, self.q.crashed, self.q.timeout, self.q.kasan, jobs[i], self.slave_id, performance, methods[i], mmh3.hash64(bitmap), reloaded=(self.q.timeout or self.q.crashed or self.q.kasan), new_bits=new_bits, qid=self.slave_id))

        self.comm.slave_locks_B[self.slave_id].release()
        send_msg(KAFL_TAG_RESULT, results, self.comm.to_mapserver_queue, source=self.slave_id)
Пример #10
0
    def run_mutate_redqueen(self, payload_array, func, default_info):
        for (offset, lhs, rhs, info) in self.enumerate_mutations():
            if self.verbose:
                log_redq("redqueen fuzz data %s" % repr(
                    (offset, lhs, rhs, info)))

            def run(data):
                default_info["redqueen"] = [repr(lhs), repr(rhs)] + list(
                    info.infos)
                func(data, default_info)

            RedqueenInfoGatherer.fuzz_data(payload_array, run, offset, lhs,
                                           rhs)
Пример #11
0
 def run_mutate_redqueen(self,
                         payload_array,
                         func,
                         kafl_state,
                         skip_null=True):
     if kafl_state:
         kafl_state.technique = "REDQUEEN"
     for (offset, lhs, rhs, info) in self.enumerate_mutations():
         if self.verbose:
             log_redq("%s" % repr((offset, lhs, rhs, info)))
         RedqueenInfoGatherer.fuzz_data(
             payload_array, lambda data: func(data, [repr(
                 lhs), repr(rhs)] + list(info.infos), offset), offset, lhs,
             rhs)
Пример #12
0
 def try_fix_cmp_offset(self, shape, data, cmp, offsets, repls):
     # try:
     backup = {}
     for i, repl in zip(offsets, repls):
         backup[i] = data[i:i + len(repl)]
         HashFixer.replace_data(data, i, array('B', repl))
     if self.does_data_fix_cmp(shape, data, cmp):
         log_redq("found candidate offset %x %s" %
                  (cmp.addr, repr(offsets)))
         self.redqueen_state.add_candidate_file_offset(
             cmp.addr, tuple(offsets))
         return True
     for i in offsets:
         HashFixer.replace_data(data, i, backup[i])
     return False
Пример #13
0
 def try_fix_cmp(self, shape, fixed_data, run_info, cmp):
     known_offsets = self.redqueen_state.get_candidate_file_offsets(
         cmp.addr)
     log_redq("known offsets for: %x = %s" % (cmp.addr, known_offsets))
     mutations = [x for x in cmp.calc_mutations(run_info, 1)]
     for (offsets, lhs, rhs, enc) in cmp.calc_mutations(run_info, 1):
         if offsets in known_offsets:
             if self.try_fix_cmp_with(shape, fixed_data, cmp, offsets, lhs,
                                      rhs, enc):
                 return True
     for (offsets, lhs, rhs, enc) in cmp.calc_mutations(run_info, 1):
         if not offsets in known_offsets:
             if self.try_fix_cmp_with(shape, fixed_data, cmp, offsets, lhs,
                                      rhs, enc):
                 return True
     return False
Пример #14
0
class RedqueenInfoGatherer:
    def __init__(self):
        self.num_alternative_inputs = 0
        self.se_path = None
        self.workdir = None
        self.num_mutations = 0
        self.verbose = False

    def make_paths(self, workdir):
        global se_saved_counter
        se_saved_counter += 1
        self.se_path = workdir.base_path + "/se_%d" % (se_saved_counter)
        self.workdir = workdir
        os.mkdir(self.se_path)

    def get_info(self, input_data):
        self.num_alternative_inputs += 1
        self.save_rq_data(self.num_alternative_inputs, input_data)
        with open(
                self.se_path + "/input_%d.bin" % (self.num_alternative_inputs),
                "wb") as f:
            f.write(input_data)

    def save_rq_data(self, id, data):
        if os.path.exists(self.workdir.redqueen()):
            copyfile(self.workdir.redqueen(),
                     "%s/redqueen_result_%d.txt" % (self.se_path, id))
        if os.path.exists(self.workdir.symbolic()):
            copyfile(self.workdir.symbolic(),
                     "%s/symbolic_result_%d.txt" % (self.se_path, id))
        if os.path.exists(self.workdir.pt_trace()):
            copyfile(self.workdir.pt_trace(),
                     "%s/trace_result_%d.txt" % (self.se_path, id))
        if os.path.exists(self.workdir.code_dump()):
            copyfile(self.workdir.code_dump(),
                     "%s/redqueen_vm.img" % (self.se_path))
        with open("%s/fin_%d.txt" % (self.se_path, id), "w") as f:
            f.write("OK")

    def get_symbolic_proposals(self):
        proposals = set()
        sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
        kafl_sock = '/tmp/rq_se_sock'
        try:
            sock.connect(kafl_sock)
            sock.sendall(self.se_path + "\n")
            buffer = ""
            while True:
                res = sock.recv(16)
                buffer += res
                if "\n" in res:
                    break
        except socket.error, msg:
            log_redq("SE failed to get SE response, maybe no demon running?")
            log_redq("SE %s" % msg)
            return []
        results = json.loads(buffer)
        log_redq("SE JSON:" + str(results))
        orig_id = self.num_alternative_inputs
        return parser.parse_se(self.se_path, results, orig_id)
Пример #15
0
 def get_symbolic_proposals(self):
     proposals = set()
     sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
     kafl_sock = '/tmp/rq_se_sock'
     try:
         sock.connect(kafl_sock)
         sock.sendall(self.se_path + "\n")
         buffer = ""
         while True:
             res = sock.recv(16)
             buffer += res
             if "\n" in res:
                 break
     except socket.error, msg:
         log_redq("SE failed to get SE response, maybe no demon running?")
         log_redq("SE %s" % msg)
         return []
Пример #16
0
Файл: mod.py Проект: vient/kAFL
    def run_mutate_redqueen(self, payload_array, func):
        for (offset, lhs, rhs, info) in self.enumerate_mutations():
            if self.verbose:
                log_redq("redqueen fuzz data %s" % repr(
                    (offset, lhs, rhs, info)))

            def run(data):
                extra_info = {
                    "redqueen": [repr(lhs), repr(rhs)] + list(info.infos)
                }
                func(data, None, extra_info)

            assert isinstance(payload_array,
                              bytearray), print("fuzz_data:",
                                                type(payload_array),
                                                type(lhs[0]), type(rhs[0]))
            RedqueenInfoGatherer.fuzz_data(payload_array, run, offset, lhs,
                                           rhs)
Пример #17
0
    def __perform_redqueen(self, payload_array, colored_alternatives):
        if self.config.argument_values['r']:
            t = time.time()
            rq_info = RedqueenInfoGatherer()
            rq_info.make_paths(RedqueenWorkdir(0))
            rq_info.verbose = False
            for payload in colored_alternatives:
                if self.__redqueen(payload):
                    self.__sync_redqueen(0)
                    self.kafl_state["technique"] = "REDQUEEN"
                    rq_info.get_info(payload)

            if not self.mode_se_only:
                rq_info.get_proposals()

                self.kafl_state[
                    "progress_requeen_amount"] = rq_info.get_num_mutations()
                log_master("Redqueen Stage...(" +
                           str(self.kafl_state["progress_requeen_amount"]) +
                           ")")
                rq_info.run_mutate_redqueen(payload_array,
                                            self.__redqueen_handler,
                                            kafl_state=self.kafl_state,
                                            skip_null=True)

                if self.mode_fix_checksum:
                    for addr in rq_info.get_hash_candidates():
                        self.redqueen_state.add_candidate_hash_addr(addr)

                self.__buffered_handler(None, last_payload=True)
                log_master("Redqueen Sync...")
                tmp_progress_redqueen = self.kafl_state["progress_redqueen"]
                self.kafl_state["progress_redqueen"] = self.kafl_state[
                    "progress_requeen_amount"]

                self.__sync_redqueen(tmp_progress_redqueen)
            self.__update_redqueen_slaves()

            duration = time.time() - t
            self.kafl_state[
                "time_redqueen"] = self.kafl_state["time_redqueen"] + duration
            log_redq("TIME IN REDQUEEN: %fs" %
                     self.kafl_state["time_redqueen"])
Пример #18
0
 def get_cmps(self, data):
     # log_redq("runnning on %s"%repr("".join( map(chr, data) )) )
     self.qemu.set_payload(data)
     # self.qemu.send_enable_patches()
     log_redq("hashfix run in rq mode")
     self.qemu.send_rq_set_whitelist_instrumentation()
     self.qemu.send_enable_redqueen()
     self.qemu.send_payload(timeout_detection=True, apply_patches=True)
     log_redq("hashfix run in non rq mode")
     self.qemu.send_disable_redqueen()
     self.qemu.send_payload(timeout_detection=True, apply_patches=True)
     log_redq("hashfix done running, now parsing")
     res = self.parse_redqueen_results(data)
     log_redq("hashfix done parsing")
     return res
Пример #19
0
 def try_fix_cmp_with(self, shape, fixed_data, cmp, offsets, lhs, rhs, enc):
     log_redq("Trying mutation %s" % (repr((offsets, lhs, rhs, enc))))
     if list(map(len, lhs)) != list(map(len, rhs)):
         return False
     self.redqueen_state.update_redqueen_whitelist(
         self.qemu.redqueen_workdir,
         self.redqueen_state.get_candidate_hash_addrs())
     try:
         if self.try_fix_cmp_offset(shape, fixed_data, cmp, offsets, rhs):
             log_redq("Mutation fixed it")
             return True
         log_redq("Mutation didn't Fix it")
         return False
     except Exception as e:
         log_redq("fixing hash failed %s" % traceback.format_exc())
         raise e
Пример #20
0
 def __perform_dict(self, payload_array, payload):
     self.kafl_state["technique"] = "DICT-BF"
     log_master("Dict on %s" % repr(payload_array.tostring()))
     dict = havoc.get_redqueen_dict()
     log_redq("using %s" % repr(dict))
     counter = 0
     if len(payload_array) < 256:
         for addr in dict:
             for repl in dict[addr]:
                 if addr in self.seen_addr_to_value and (
                         len(self.seen_addr_to_value[addr]) > 32
                         or repl in self.seen_addr_to_value[addr]):
                     continue
                 if not addr in self.seen_addr_to_value:
                     self.seen_addr_to_value[addr] = set()
                 self.seen_addr_to_value[addr].add(repl)
                 for i in range(len(payload_array)):
                     counter += 1
                     mutated = havoc.apply_dict_to_data(
                         payload_array, repl, i).tostring()
                     self.__dict_bf_handler(mutated)
     log_redq("have performed %d iters" % counter)
     self.__buffered_handler(None, last_payload=True)
Пример #21
0
def clear_redqueen_dict():
    global redqueen_dict, redqueen_addr_list
    log_redq("clearing dict %s" % repr(redqueen_dict))
    redqueen_dict = {}
    redqueen_addr_list = []
Пример #22
0
Файл: cmp.py Проект: ufwt/kAFL
def enable_hammering():
    global HAMMER_LEA
    log_redq("Hammering enabled!")
    HAMMER_LEA = True
Пример #23
0
    def try_fix_data(self, data):
        self.qemu.send_payload(timeout_detection=True, apply_patches=False)
        self.qemu.send_payload(timeout_detection=True, apply_patches=True)
        log_redq("PATCHES %s\n" % repr(
            list(map(hex, self.redqueen_state.get_candidate_hash_addrs()))))
        log_redq("BLACKLIST %s\n" % repr(
            list(map(hex, self.redqueen_state.get_blacklisted_hash_addrs()))))
        self.redqueen_state.update_redqueen_patches(self.qemu.redqueen_workdir)
        self.redqueen_state.update_redqueen_whitelist(
            self.qemu.redqueen_workdir,
            self.redqueen_state.get_candidate_hash_addrs())
        fixed_data = array('B', data)
        orig_cmps, _ = self.get_cmps(fixed_data)
        shape = self.get_shape(orig_cmps)
        log_redq("shape of hashes: ")
        for addr in shape:
            log_redq("\t%x: %d" % (addr, shape[addr]))

        if len(shape) == 0:
            return fixed_data

        num_iters = min(len(orig_cmps)**2 + 1, len(orig_cmps) * 3 + 1)
        num_cmps = sum(shape.values()) + 1
        if num_iters < num_cmps:
            num_iters = num_cmps

        log_redq("try fixing for %d iters" % num_iters)
        for i in range(num_iters):
            broken_checks, run_info = self.get_broken_cmps(fixed_data)
            log_redq("got %d broken checks\n" % len(broken_checks))
            if not broken_checks:
                return fixed_data
            cmp = broken_checks.pop(-1)
            if not self.try_fix_cmp(shape, fixed_data, run_info, cmp):
                log_redq("cmp at %x unfixable:" % cmp.addr)
                self.mark_unfixable(cmp)
        broken_checks, run_info = self.get_broken_cmps(fixed_data)
        for cmp in broken_checks:
            self.mark_unfixable(cmp)
        return False
Пример #24
0
 def mark_unfixable(self, cmp):
     log_redq("Unfixable cmp at: %x" % cmp.addr)
     self.blacklisted_addrs.add(cmp.addr)
     self.redqueen_state.blacklist_hash_addr(cmp.addr)