Esempio n. 1
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)
Esempio n. 2
0
    def __perform_redqueen(self, payload_array, metadata):
        if self.config.argument_values['r']:
            default_info = {"method": "colorization", "parent": metadata["id"]}

            payload_bytes = array('B', payload_array)

            orig_hash = self.__get_bitmap_hash_robust(payload_bytes,
                                                      default_info)
            extension = array("B", [207, 117, 130, 107, 183, 200, 143, 154])
            appended_hash = self.__get_bitmap_hash_robust(
                payload_bytes + extension, default_info)

            if orig_hash and orig_hash == appended_hash:
                safe_print("input can be extended")
                payload_bytes += extension

            colored_alternatives = self.__perform_coloring(
                payload_bytes, default_info)
            if colored_alternatives:
                payload_bytes = array('B', colored_alternatives[0])
            else:
                safe_print("input is not stable, skip redqueen")
                return

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

            rq_info.get_proposals()
            default_info = {"method": "redqueen", "parent": metadata["id"]}
            rq_info.run_mutate_redqueen(payload_bytes, self.execute,
                                        default_info)

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

            # for addr in rq_info.get_boring_cmps():
            #    self.redqueen_state.blacklist_cmp_addr(addr)
            # self.redqueen_state.update_redqueen_blacklist(RedqueenWorkdir(0))

            duration = time.time() - t
Esempio n. 3
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"])
Esempio n. 4
0
    def __init__(self, qid, config, debug_mode=False, notifiers=True):

        self.hprintf_print_mode = True
        self.internal_buffer_overflow_counter = 0

        # True => handshake *not yet done*
        self.handshake_stage_1 = True
        self.handshake_stage_2 = True

        self.debug_mode = debug_mode
        self.patches_enabled = False
        self.needs_execution_for_patches = False
        self.debug_counter = 0
        self.verbose = config.argument_values['v']

        self.bitmap_size = config.config_values['BITMAP_SHM_SIZE']
        self.payload_size = config.config_values['PAYLOAD_SHM_SIZE']
        self.config = config
        self.qemu_id = str(qid)

        self.process = None
        self.control = None
        self.persistent_runs = 0

        project_name = self.config.argument_values['work_dir'].split("/")[-1]
        self.payload_filename = "/dev/shm/kafl_%s_qemu_payload_%s" % (
            project_name, self.qemu_id)
        self.tracedump_filename = "/dev/shm/kafl_%s_pt_trace_dump_%s" % (
            project_name, self.qemu_id)
        self.binary_filename = self.config.argument_values[
            'work_dir'] + "/program"
        self.bitmap_filename = "/dev/shm/kafl_%s_bitmap_%s" % (project_name,
                                                               self.qemu_id)

        self.control_filename = self.config.argument_values[
            'work_dir'] + "/interface_" + self.qemu_id
        self.qemu_trace_log = self.config.argument_values[
            'work_dir'] + "/qemu_trace_%s.log" % self.qemu_id
        self.qemu_serial_log = self.config.argument_values[
            'work_dir'] + "/qemu_serial_%s.log" % self.qemu_id

        self.in_requeen = self.config.argument_values['redqueen']
        self.redqueen_workdir = RedqueenWorkdir(self.qemu_id, config)
        self.redqueen_workdir.init_dir()

        self.exiting = False
        self.start_ticks = 0
        self.end_ticks = 0
        self.tick_timeout_treshold = self.config.config_values[
            "TIMEOUT_TICK_FACTOR"]

        self.cmd = self.config.config_values['QEMU_KAFL_LOCATION']

        self.catch_vm_reboots = self.config.argument_values['catch_resets']

        # TODO: list append should work better than string concatenation, especially for str.replace() and later popen()
        self.cmd += " -serial file:" + self.qemu_serial_log + \
                    " -enable-kvm" \
                    " -m " + str(config.argument_values['mem']) + \
                    " -nographic -net none" \
                    " -chardev socket,server,nowait,path=" + self.control_filename + \
                    ",id=kafl_interface" \
                    " -device kafl,chardev=kafl_interface,bitmap_size=" + str(self.bitmap_size) + ",shm0=" + self.binary_filename + \
                    ",shm1=" + self.payload_filename + \
                    ",bitmap=" + self.bitmap_filename + \
                    ",redqueen_workdir=" + self.redqueen_workdir.base_path

        if False:  # do not emit tracefiles on every execution
            self.cmd += ",dump_pt_trace"

        if self.debug_mode:
            self.cmd += ",debug_mode"

        if not notifiers:
            self.cmd += ",crash_notifier=False"

        # fast reload is not part of redqueen release
        # if not self.config.argument_values.has_key('R') or not self.config.argument_values['R']:
        self.cmd += ",reload_mode=False"

        # qemu snapshots only work in VM mode (disk+ram image)
        if self.config.argument_values[
                'kernel'] or self.config.argument_values['bios']:
            self.cmd += ",disable_snapshot=True"

        for i in range(1):
            key = "ip" + str(i)
            if key in self.config.argument_values and self.config.argument_values[
                    key]:
                range_a = hex(self.config.argument_values[key][0]).replace(
                    "L", "")
                range_b = hex(self.config.argument_values[key][1]).replace(
                    "L", "")
                self.cmd += ",ip" + str(i) + "_a=" + range_a + ",ip" + str(
                    i) + "_b=" + range_b
                #self.cmd += ",filter" + str(i) + "=/dev/shm/kafl_filter" + str(i)

        if self.config.argument_values["target_mem"]:
            self.cmd += ",target=" + self.config.argument_values["target_mem"]

        if self.debug_mode:
            self.cmd += " -d kafl -D " + self.qemu_trace_log

        if self.catch_vm_reboots:
            self.cmd += " -no-reboot"

        if self.config.argument_values['gdbserver']:
            self.cmd += " -s -S"

        if self.config.argument_values['extra']:
            self.cmd += " " + self.config.argument_values['extra']

        # Lauch either as VM snapshot, direct kernel/initrd boot, or -bios boot
        if self.config.argument_values['vm_dir']:
            assert (self.config.argument_values['vm_ram'])
            self.cmd += " -hdb " + self.config.argument_values[
                'vm_ram'] + "_" + self.qemu_id + ".qcow2"
            self.cmd += " -hda " + self.config.argument_values[
                'vm_dir'] + "/overlay_" + self.qemu_id + ".qcow2"
            self.cmd += " -loadvm " + self.config.argument_values["S"]
        elif self.config.argument_values['kernel']:
            self.cmd += " -kernel " + self.config.argument_values['kernel']
            if self.config.argument_values['initrd']:
                self.cmd += " -initrd " + self.config.argument_values[
                    'initrd'] + " -append BOOTPARAM "
        elif self.config.argument_values['bios']:
            self.cmd += " -bios " + self.config.argument_values['bios']
        else:
            assert (
                False
            ), "Must supply either -bios or -kernel or -vm_overlay/-vm_ram option"

        if self.config.argument_values["macOS"]:
            self.cmd = self.cmd.replace(
                "-nographic -net none",
                "-nographic -netdev user,id=hub0port0 -device e1000-82545em,netdev=hub0port0,id=mac_vnet0 -cpu Penryn,kvm=off,vendor=GenuineIntel -device isa-applesmc,osk=\""
                +
                self.config.config_values["APPLE-SMC-OSK"].replace("\"", "") +
                "\" -machine pc-q35-2.4")
            if self.qemu_id == 0:
                self.cmd = self.cmd.replace(
                    "-machine pc-q35-2.4",
                    "-machine pc-q35-2.4 -redir tcp:5901:0.0.0.0:5900 -redir tcp:10022:0.0.0.0:22"
                )
        else:
            self.cmd += " -machine q35 "
            if self.config.argument_values["tp"]:
                self.cmd = self.cmd.replace(
                    "-net none",
                    "-netdev tap,ifname=" + "tap-" + self.qemu_id +
                    ",id=net0,script=no,downscript=no -device rtl8139,netdev=net0"
                )
                self.cmd += " -device usb-tablet -machine usb=on,type=pc,accel=kvm"

        if self.config.argument_values["graphic"]:
            self.cmd = self.cmd.replace("-nographic", "")

        self.kafl_shm_f = None
        self.kafl_shm = None
        self.fs_shm_f = None
        self.fs_shm = None

        self.payload_shm_f = None
        self.payload_shm = None

        self.bitmap_shm_f = None
        self.bitmap_shm = None

        self.crashed = False
        self.timeout = False
        self.kasan = False
        self.shm_problem = False
        self.initial_mem_usage = 0

        self.stat_fd = None

        self.virgin_bitmap = bytes(self.bitmap_size)

        # split cmd into list of arguments for Popen(), replace BOOTPARAM as single element
        self.cmd = [_f for _f in self.cmd.split(" ") if _f]
        c = 0
        for i in self.cmd:
            if i == "BOOTPARAM":
                self.cmd[c] = "\"nokaslr oops=panic nopti mitigations=off\""
                break
            c += 1
Esempio n. 5
0
class qemu:
    CMDS = qemu_protocol.CMDS

    def __init__(self, qid, config, debug_mode=False, notifiers=True):

        self.hprintf_print_mode = True
        self.internal_buffer_overflow_counter = 0

        # True => handshake *not yet done*
        self.handshake_stage_1 = True
        self.handshake_stage_2 = True

        self.debug_mode = debug_mode
        self.patches_enabled = False
        self.needs_execution_for_patches = False
        self.debug_counter = 0
        self.verbose = config.argument_values['v']

        self.bitmap_size = config.config_values['BITMAP_SHM_SIZE']
        self.payload_size = config.config_values['PAYLOAD_SHM_SIZE']
        self.config = config
        self.qemu_id = str(qid)

        self.process = None
        self.control = None
        self.persistent_runs = 0

        project_name = self.config.argument_values['work_dir'].split("/")[-1]
        self.payload_filename = "/dev/shm/kafl_%s_qemu_payload_%s" % (
            project_name, self.qemu_id)
        self.tracedump_filename = "/dev/shm/kafl_%s_pt_trace_dump_%s" % (
            project_name, self.qemu_id)
        self.binary_filename = self.config.argument_values[
            'work_dir'] + "/program"
        self.bitmap_filename = "/dev/shm/kafl_%s_bitmap_%s" % (project_name,
                                                               self.qemu_id)

        self.control_filename = self.config.argument_values[
            'work_dir'] + "/interface_" + self.qemu_id
        self.qemu_trace_log = self.config.argument_values[
            'work_dir'] + "/qemu_trace_%s.log" % self.qemu_id
        self.qemu_serial_log = self.config.argument_values[
            'work_dir'] + "/qemu_serial_%s.log" % self.qemu_id

        self.in_requeen = self.config.argument_values['redqueen']
        self.redqueen_workdir = RedqueenWorkdir(self.qemu_id, config)
        self.redqueen_workdir.init_dir()

        self.exiting = False
        self.start_ticks = 0
        self.end_ticks = 0
        self.tick_timeout_treshold = self.config.config_values[
            "TIMEOUT_TICK_FACTOR"]

        self.cmd = self.config.config_values['QEMU_KAFL_LOCATION']

        self.catch_vm_reboots = self.config.argument_values['catch_resets']

        # TODO: list append should work better than string concatenation, especially for str.replace() and later popen()
        self.cmd += " -serial file:" + self.qemu_serial_log + \
                    " -enable-kvm" \
                    " -m " + str(config.argument_values['mem']) + \
                    " -nographic -net none" \
                    " -chardev socket,server,nowait,path=" + self.control_filename + \
                    ",id=kafl_interface" \
                    " -device kafl,chardev=kafl_interface,bitmap_size=" + str(self.bitmap_size) + ",shm0=" + self.binary_filename + \
                    ",shm1=" + self.payload_filename + \
                    ",bitmap=" + self.bitmap_filename + \
                    ",redqueen_workdir=" + self.redqueen_workdir.base_path

        if False:  # do not emit tracefiles on every execution
            self.cmd += ",dump_pt_trace"

        if self.debug_mode:
            self.cmd += ",debug_mode"

        if not notifiers:
            self.cmd += ",crash_notifier=False"

        # fast reload is not part of redqueen release
        # if not self.config.argument_values.has_key('R') or not self.config.argument_values['R']:
        self.cmd += ",reload_mode=False"

        # qemu snapshots only work in VM mode (disk+ram image)
        if self.config.argument_values[
                'kernel'] or self.config.argument_values['bios']:
            self.cmd += ",disable_snapshot=True"

        for i in range(1):
            key = "ip" + str(i)
            if key in self.config.argument_values and self.config.argument_values[
                    key]:
                range_a = hex(self.config.argument_values[key][0]).replace(
                    "L", "")
                range_b = hex(self.config.argument_values[key][1]).replace(
                    "L", "")
                self.cmd += ",ip" + str(i) + "_a=" + range_a + ",ip" + str(
                    i) + "_b=" + range_b
                #self.cmd += ",filter" + str(i) + "=/dev/shm/kafl_filter" + str(i)

        if self.config.argument_values["target_mem"]:
            self.cmd += ",target=" + self.config.argument_values["target_mem"]

        if self.debug_mode:
            self.cmd += " -d kafl -D " + self.qemu_trace_log

        if self.catch_vm_reboots:
            self.cmd += " -no-reboot"

        if self.config.argument_values['gdbserver']:
            self.cmd += " -s -S"

        if self.config.argument_values['extra']:
            self.cmd += " " + self.config.argument_values['extra']

        # Lauch either as VM snapshot, direct kernel/initrd boot, or -bios boot
        if self.config.argument_values['vm_dir']:
            assert (self.config.argument_values['vm_ram'])
            self.cmd += " -hdb " + self.config.argument_values[
                'vm_ram'] + "_" + self.qemu_id + ".qcow2"
            self.cmd += " -hda " + self.config.argument_values[
                'vm_dir'] + "/overlay_" + self.qemu_id + ".qcow2"
            self.cmd += " -loadvm " + self.config.argument_values["S"]
        elif self.config.argument_values['kernel']:
            self.cmd += " -kernel " + self.config.argument_values['kernel']
            if self.config.argument_values['initrd']:
                self.cmd += " -initrd " + self.config.argument_values[
                    'initrd'] + " -append BOOTPARAM "
        elif self.config.argument_values['bios']:
            self.cmd += " -bios " + self.config.argument_values['bios']
        else:
            assert (
                False
            ), "Must supply either -bios or -kernel or -vm_overlay/-vm_ram option"

        if self.config.argument_values["macOS"]:
            self.cmd = self.cmd.replace(
                "-nographic -net none",
                "-nographic -netdev user,id=hub0port0 -device e1000-82545em,netdev=hub0port0,id=mac_vnet0 -cpu Penryn,kvm=off,vendor=GenuineIntel -device isa-applesmc,osk=\""
                +
                self.config.config_values["APPLE-SMC-OSK"].replace("\"", "") +
                "\" -machine pc-q35-2.4")
            if self.qemu_id == 0:
                self.cmd = self.cmd.replace(
                    "-machine pc-q35-2.4",
                    "-machine pc-q35-2.4 -redir tcp:5901:0.0.0.0:5900 -redir tcp:10022:0.0.0.0:22"
                )
        else:
            self.cmd += " -machine q35 "
            if self.config.argument_values["tp"]:
                self.cmd = self.cmd.replace(
                    "-net none",
                    "-netdev tap,ifname=" + "tap-" + self.qemu_id +
                    ",id=net0,script=no,downscript=no -device rtl8139,netdev=net0"
                )
                self.cmd += " -device usb-tablet -machine usb=on,type=pc,accel=kvm"

        if self.config.argument_values["graphic"]:
            self.cmd = self.cmd.replace("-nographic", "")

        self.kafl_shm_f = None
        self.kafl_shm = None
        self.fs_shm_f = None
        self.fs_shm = None

        self.payload_shm_f = None
        self.payload_shm = None

        self.bitmap_shm_f = None
        self.bitmap_shm = None

        self.crashed = False
        self.timeout = False
        self.kasan = False
        self.shm_problem = False
        self.initial_mem_usage = 0

        self.stat_fd = None

        self.virgin_bitmap = bytes(self.bitmap_size)

        # split cmd into list of arguments for Popen(), replace BOOTPARAM as single element
        self.cmd = [_f for _f in self.cmd.split(" ") if _f]
        c = 0
        for i in self.cmd:
            if i == "BOOTPARAM":
                self.cmd[c] = "\"nokaslr oops=panic nopti mitigations=off\""
                break
            c += 1

    def __debug_hprintf(self):
        try:
            if self.debug_counter < 512:
                data = ""
                for line in open("/tmp/kAFL_printf.txt." +
                                 str(self.debug_counter)):
                    data += line
                self.debug_counter += 1
                if data.endswith('\n'):
                    data = data[:-1]
                if self.hprintf_print_mode:
                    print("[HPRINTF]\t" + '\033[0;33m' + data + '\033[0m')
                else:
                    print('\033[0;33m' + data + '\033[0m')
        except Exception as e:
            print("__debug_hprintf: " + str(e))

    def send_enable_redqueen(self):
        self.__debug_send(qemu_protocol.ENABLE_RQI_MODE)
        self.__debug_recv_expect(qemu_protocol.ENABLE_RQI_MODE)

    def send_disable_redqueen(self):
        self.__debug_send(qemu_protocol.DISABLE_RQI_MODE)
        self.__debug_recv_expect(qemu_protocol.DISABLE_RQI_MODE)

    def send_enable_patches(self):
        if not self.patches_enabled:
            assert (not self.needs_execution_for_patches)
            self.needs_execution_for_patches = True
            self.patches_enabled = True
            self.__debug_send(qemu_protocol.ENABLE_PATCHES)
            self.__debug_recv_expect(qemu_protocol.ENABLE_PATCHES)

    def send_disable_patches(self):
        if self.patches_enabled:
            assert (not self.needs_execution_for_patches)
            self.needs_execution_for_patches = True
            self.patches_enabled = False
            self.__debug_send(qemu_protocol.DISABLE_PATCHES)
            self.__debug_recv_expect(qemu_protocol.DISABLE_PATCHES)
        pass

    def send_enable_trace(self):
        self.__debug_send(qemu_protocol.ENABLE_TRACE_MODE)
        self.__debug_recv_expect(qemu_protocol.ENABLE_TRACE_MODE)

    def send_disable_trace(self):
        self.__debug_send(qemu_protocol.DISABLE_TRACE_MODE)
        self.__debug_recv_expect(qemu_protocol.DISABLE_TRACE_MODE)

    def send_rq_set_light_instrumentation(self):
        self.__debug_send(qemu_protocol.REDQUEEN_SET_LIGHT_INSTRUMENTATION)
        self.__debug_recv_expect(
            qemu_protocol.REDQUEEN_SET_LIGHT_INSTRUMENTATION)

    def send_rq_set_whitelist_instrumentation(self):
        self.__debug_send(qemu_protocol.REDQUEEN_SET_WHITELIST_INSTRUMENTATION)
        self.__debug_recv_expect(
            qemu_protocol.REDQUEEN_SET_WHITELIST_INSTRUMENTATION)

    def send_rq_update_blacklist(self):
        self.__debug_send(qemu_protocol.REDQUEEN_SET_BLACKLIST)
        self.__debug_recv_expect(qemu_protocol.REDQUEEN_SET_BLACKLIST)

    def __debug_send(self, cmd):
        #self.last_bitmap_wrapper.invalidate() # works on a copy, probably obsolete..
        if self.debug_mode:
            info = ""
            if self.handshake_stage_1 and cmd == qemu_protocol.RELEASE:
                info = " (Agent Init)"
                self.handshake_stage_1 = False
            elif self.handshake_stage_2 and cmd == qemu_protocol.RELEASE:
                info = " (Agent Run)"
                self.handshake_stage_2 = False
            try:
                log_qemu(
                    "[SEND] " + '\033[94m' + self.CMDS[cmd] + info + '\033[0m',
                    self.qemu_id)
            except:
                log_qemu("[SEND] " + "unknown cmd '" + res + "'", self.qemu_id)
        try:
            self.control.send(cmd)
        except (BrokenPipeError, OSError):
            if not self.exiting:
                log_qemu("Fatal error in __debug_send()", self.qemu_id)
                self.shutdown()
                raise

    def __dump_recv_res(self, res):
        if res == qemu_protocol.ACQUIRE:
            self.debug_counter = 0
        # try:
        info = ""
        if self.handshake_stage_1 and res == qemu_protocol.RELEASE:
            info = " (Agent Init)"
        elif self.handshake_stage_2 and res == qemu_protocol.ACQUIRE:
            info = " (Agent Ready)"
        elif res == qemu_protocol.INFO:
            log_qemu(
                "[RECV] " + '\033[1m' + '\033[92m' + self.CMDS[res] + info +
                '\033[0m', self.qemu_id)
            log_qemu("------------------------------------------------------",
                     self.qemu_id)
            try:
                for line in open("/tmp/kAFL_info.txt"):
                    log_qemu(line, self.qemu_id)
                os.remove("/tmp/kAFL_info.txt")
            except:
                pass
            log_qemu("------------------------------------------------------",
                     self.qemu_id)
            os._exit(0)
        elif res == qemu_protocol.ABORT:
            #print(common.color.FAIL + self.CMDS[res] + common.color.ENDC)
            log_qemu(
                "[RECV] " + common.color.FAIL + self.CMDS[res] +
                common.color.ENDC, self.qemu_id)
            os._exit(0)
        if res == qemu_protocol.CRASH or res == qemu_protocol.KASAN:
            log_qemu(
                "[RECV] " + '\033[1m' + '\033[91m' + self.CMDS[res] + info +
                '\033[0m', self.qemu_id)
        else:
            try:
                log_qemu(
                    "[RECV] " + '\033[1m' + '\033[92m' + self.CMDS[res] +
                    info + '\033[0m', self.qemu_id)
            except Exception as e:
                log_qemu("[RECV] " + "unknown cmd '" + res + "'" + str(e),
                         self.qemu_id)
                raise e

    def __debug_recv(self):
        while True:
            try:
                res = self.control.recv(1)
            except ConnectionResetError:
                if self.exiting:
                    sys.exit(0)

            if (len(res) == 0):
                # Another case of socket error, apparently on Qemu reset/crash
                if self.catch_vm_reboots:
                    # Treat event as Qemu reset triggered by target, and log as KASAN
                    log_qemu(
                        "Qemu exit? - Assuming target crash/reset (KASAN)",
                        self.qemu_id)
                    return qemu_protocol.KASAN
                else:
                    # Default: assume Qemu exit is fatal bug in harness/setup
                    log_qemu("Fatal error in __debug_recv()", self.qemu_id)
                    sig = self.shutdown()
                    if sig == 0:  # regular shutdown? still report as KASAN
                        return qemu_protocol.KASAN
                    else:
                        raise EOFError("Qemu exited with signal: %s" %
                                       str(sig))

            if res == qemu_protocol.PRINTF:
                self.__debug_hprintf()
                self.hprintf_print_mode = False
            else:
                self.hprintf_print_mode = True

                if self.debug_mode:
                    try:
                        self.__dump_recv_res(res)
                    except:
                        pass

                return res

    def __debug_recv_expect(self, cmd):
        res = ''
        while True:

            res = self.__debug_recv()
            if res in cmd:
                break
            # TODO: the I/O handling here really sucks.
            # Below we are returning OK to set_init_state() in order to silence handshake error message during kafl_info.py.
            # We need to factor out the debug stuff and properly support required vs optional/intermediate control messages...
            elif res == qemu_protocol.INFO:
                break
            elif res is None:
                # Timeout is detected separately in debug_recv(), so we should never get here..
                assert False
            else:
                # Reaching this part typically means there is a bug in the agent or target setup which
                # messes up the expected interaction. Throw an error and exit.
                log_qemu(
                    "Fatal error in debug_recv(): Got " + str(res) +
                    ", Expected: " + str(cmd) + ")", self.qemu_id)
                print_fail(
                    "Slave %d: Error in debug_recv(): Got %s, Expected: %s" %
                    (self.qemu_id, str(res), str(cmd)))
                assert False
        if res == qemu_protocol.PT_TRASHED:
            log_qemu("PT_TRASHED", self.qemu_id)
            return False
        return True

    # Asynchronous exit by slave instance. Note this may be called multiple times
    # while we were in the middle of shutdown(), start(), send_payload(), ..
    def async_exit(self):
        if self.exiting:
            sys.exit(0)

        self.exiting = True
        self.shutdown()

        for tmp_file in [
                self.payload_filename, self.tracedump_filename,
                self.control_filename, self.binary_filename,
                self.bitmap_filename
        ]:
            try:
                os.remove(tmp_file)
            except:
                pass

    def shutdown(self):
        log_qemu("Shutting down Qemu after %d execs.." % self.persistent_runs,
                 self.qemu_id)

        if not self.process:
            # start() has never been called, all files/shm are closed.
            return 0

        # If Qemu exists, try to graciously read its I/O and SIGTERM it.
        # If still alive, attempt SIGKILL or loop-wait on kill -9.
        output = "<no output received>\n"
        try:
            self.process.kill()
            self.process.wait()
            output = strdump(self.process.communicate(timeout=1)[0],
                             verbatim=True)
        except:
            pass

        if self.process.returncode is None:
            try:
                self.process.kill()
            except:
                pass

        log_qemu("Qemu exit code: %s" % str(self.process.returncode),
                 self.qemu_id)
        header = "\n=================<Qemu %s Console Output>==================\n" % self.qemu_id
        footer = "====================</Console Output>======================\n"
        log_qemu(header + output + footer, self.qemu_id)
        header = "\n=================<Qemu %s Serial Output>==================\n" % self.qemu_id
        footer = "====================</Serial Output>======================\n"
        serial_out = strdump(read_binary_file(self.qemu_serial_log),
                             verbatim=True)
        log_qemu(header + serial_out + footer, self.qemu_id)

        try:
            self.kafl_shm.close()
        except:
            pass

        try:
            self.fs_shm.close()
        except:
            pass

        try:
            os.close(self.kafl_shm_f)
        except:
            pass

        try:
            os.close(self.fs_shm_f)
        except:
            pass

        try:
            if self.stat_fd:
                self.stat_fd.close()
        except:
            pass

        try:
            self.control.close()
        except:
            pass

        return self.process.returncode

    def __set_agent(self):
        max_size = (128 << 20)
        agent_bin = self.config.argument_values['agent']
        bin = read_binary_file(agent_bin)
        assert (len(bin) <= max_size)
        atomic_write(self.binary_filename, bin)

    def start(self):

        if self.exiting:
            return False

        if self.qemu_id == "0" or self.qemu_id == "1337":  ## 1337 is debug instance!
            log_qemu("Launching virtual machine...CMD:\n" + ' '.join(self.cmd),
                     self.qemu_id)
        else:
            log_qemu("Launching virtual machine...CMD:\n" + ' '.join(self.cmd),
                     self.qemu_id)
            #log_qemu("Launching virtual machine...", self.qemu_id)

        self.persistent_runs = 0
        # Have not received+send first RELEASE (init handshake)
        self.handshake_stage_1 = True
        # Have not received first ACQUIRE (ready for payload execution)
        self.handshake_stage_2 = True

        # Launch Qemu. stderr to stdout, stdout is logged on VM exit
        # os.setpgrp() prevents signals from being propagated to Qemu, instead allowing an
        # organized shutdown via async_exit()
        if self.verbose:
            self.process = subprocess.Popen(self.cmd,
                                            preexec_fn=os.setpgrp,
                                            stdin=subprocess.PIPE,
                                            stdout=get_log_file(),
                                            stderr=get_log_file())
        else:
            self.process = subprocess.Popen(self.cmd,
                                            preexec_fn=os.setpgrp,
                                            stdin=subprocess.PIPE,
                                            stdout=subprocess.PIPE,
                                            stderr=subprocess.STDOUT)

        try:
            self.stat_fd = open("/proc/" + str(self.process.pid) + "/stat")
            self.init()
            self.set_init_state()
        except:
            if not self.exiting:
                print_fail("Failed to launch Qemu, please see logs.")
                log_qemu("Fatal error: Failed to launch Qemu.", self.qemu_id)
                self.shutdown()
            return False

        self.initial_mem_usage = resource.getrusage(
            resource.RUSAGE_SELF).ru_maxrss
        self.kafl_shm.seek(0x0)
        self.kafl_shm.write(self.virgin_bitmap)
        self.kafl_shm.flush()

        return True

    def set_init_state(self):
        self.start_ticks = 0
        self.end_ticks = 0

        if self.config.argument_values['agent']:
            self.__set_agent()

        self.__debug_recv_expect(qemu_protocol.RELEASE +
                                 qemu_protocol.PT_TRASHED)
        self.__debug_send(qemu_protocol.RELEASE)
        log_qemu("Stage 1 handshake done [INIT]", self.qemu_id)

        # notify user if harness loads slow or not at all..
        #ready = select.select([self.control], [], [], 0.5)
        #while not ready[0]:
        #    print("[Slave %d] Waiting for Qemu handshake..." % self.qemu_id)
        #    ready = select.select([self.control], [], [], 1)

        self.handshake_stage_1 = False
        self.__debug_recv_expect(qemu_protocol.ACQUIRE +
                                 qemu_protocol.PT_TRASHED)
        log_qemu("Stage 2 handshake done [READY]", self.qemu_id)
        self.handshake_stage_2 = False

    def init(self):
        # Note: setblocking() disables the timeout! settimeout() will automatically set blocking!
        self.control = socket.socket(socket.AF_UNIX)
        self.control.settimeout(None)
        self.control.setblocking(1)

        # TODO: Don't try forever, set some timeout..
        while True:
            try:
                self.control.connect(self.control_filename)
                break
            except socket_error:
                if self.process.returncode is not None:
                    raise

        self.kafl_shm_f = os.open(self.bitmap_filename,
                                  os.O_RDWR | os.O_SYNC | os.O_CREAT)
        self.fs_shm_f = os.open(self.payload_filename,
                                os.O_RDWR | os.O_SYNC | os.O_CREAT)

        open(self.tracedump_filename, "wb").close()

        os.ftruncate(self.kafl_shm_f, self.bitmap_size)
        os.ftruncate(self.fs_shm_f, self.payload_size)

        self.kafl_shm = mmap.mmap(self.kafl_shm_f, self.bitmap_size,
                                  mmap.MAP_SHARED,
                                  mmap.PROT_WRITE | mmap.PROT_READ)
        self.c_bitmap = (ctypes.c_uint8 * self.bitmap_size).from_buffer(
            self.kafl_shm)
        self.fs_shm = mmap.mmap(self.fs_shm_f, self.payload_size,
                                mmap.MAP_SHARED,
                                mmap.PROT_WRITE | mmap.PROT_READ)

        return True

    # Restart Qemu after crash/timeout, unless the target runs its own forkserver
    def restart(self):
        if self.config.argument_values['forkserver']:
            return True

        self.shutdown()
        #try twice here
        if not self.start():
            return self.start()
        return True

    # Reload is not part of released Redqueen backend, it seems we can simply disable it here..
    def soft_reload(self):
        return

        log_qemu("soft_reload()", self.qemu_id)
        self.crashed = False
        self.timeout = False
        self.kasan = False
        self.start_ticks = 0
        self.end_ticks = 0

        self.__debug_send(qemu_protocol.RELOAD)
        self.__debug_recv_expect(qemu_protocol.RELOAD)
        success = self.__debug_recv_expect(qemu_protocol.ACQUIRE +
                                           qemu_protocol.PT_TRASHED)

        if not success:
            log_qemu("soft reload failed (ipt ovp quirk)", self.qemu_id)
            self.soft_reload()

    # TODO: can directly return result for handling by caller?
    # TODO: document protocol and meaning/effect of each message
    def check_recv(self, timeout_detection=True):
        if timeout_detection:
            #debugging_code increase waiting time for debugging
            #ready = select.select([self.control], [], [], 0.25)
            ready = select.select([self.control], [], [], 5)
            if not ready[0]:
                return 2
        else:
            ready = select.select([self.control], [], [])
            if not ready[0]:
                return 2

        result = self.__debug_recv()

        if result == qemu_protocol.CRASH:
            return 1
        elif result == qemu_protocol.KASAN:
            return 3
        elif result == qemu_protocol.TIMEOUT:
            return 7
        elif result == qemu_protocol.ACQUIRE:
            return 0
        elif result == qemu_protocol.PT_TRASHED:
            self.internal_buffer_overflow_counter += 1
            return 4
        elif result == qemu_protocol.PT_TRASHED_CRASH:
            self.internal_buffer_overflow_counter += 1
            return 5
        elif result == qemu_protocol.PT_TRASHED_KASAN:
            self.internal_buffer_overflow_counter += 1
            return 6
        else:
            # TODO: detect+log errors without affecting fuzz campaigns
            #raise ValueError("Unhandled Qemu message %s" % repr(result))
            return 0

    # Wait forever on Qemu to execute the payload - useful for interactive debug
    def debug_payload(self, apply_patches=True):
        # TODO: do we care about this?
        if self.in_requeen:
            if apply_patches:
                self.send_enable_patches()
            else:
                self.send_disable_patches()

        self.__debug_send(qemu_protocol.RELEASE)

        while True:
            ready = select.select([self.control], [], [], 0.5)
            if ready[0]:
                break

        result = self.__debug_recv()
        return result

    def send_payload(self,
                     apply_patches=True,
                     timeout_detection=True,
                     max_iterations=10):

        if self.exiting:
            sys.exit(0)

        self.persistent_runs += 1
        start_time = time.time()
        # TODO: added in redqueen - verify what this is doing
        if self.in_requeen:
            if apply_patches:
                self.send_enable_patches()
            else:
                self.send_disable_patches()
        self.__debug_send(qemu_protocol.RELEASE)

        self.crashed = False
        self.timeout = False
        self.kasan = False

        repeat = False
        value = self.check_recv(timeout_detection=timeout_detection)
        if value == 0:
            pass  # all good
        elif value == 1:
            log_qemu("Crash detected!", self.qemu_id)
            self.crashed = True
        elif value == 2:
            log_qemu("Timeout detected!", self.qemu_id)
            self.timeout = True
        elif value == 3:
            log_qemu("Kasan detected!", self.qemu_id)
            self.kasan = True
        elif value == 4:
            repeat = True
        elif value == 5:
            repeat = True
            self.soft_reload()
        elif value == 6:
            repeat = True
            self.soft_reload()
        elif value == 7:
            log_qemu("Timeout detected!", self.qemu_id)
            self.timeout = True
        else:
            # TODO: detect+log errors without affecting fuzz campaigns
            #raise ValueError("Unhandled return code %s" % str(value))
            pass

        self.needs_execution_for_patches = False

        ## repeat logic - enable starting with RQ release..
        if repeat:
            log_qemu("Repeating iteration...", self.qemu_id)
            if max_iterations != 0:
                self.send_payload(apply_patches=apply_patches,
                                  timeout_detection=timeout_detection,
                                  max_iterations=0)
                res = self.send_payload(apply_patches=apply_patches,
                                        timeout_detection=timeout_detection,
                                        max_iterations=max_iterations - 1)
                res.performance = time.time() - start_time
                return res

        return ExecutionResult(self.c_bitmap, self.bitmap_size,
                               self.exit_reason(),
                               time.time() - start_time)

    def exit_reason(self):
        if self.crashed:
            return "crash"
        elif self.timeout:
            return "timeout"
        elif self.kasan:
            return "kasan"
        else:
            return "regular"

    def enable_sampling_mode(self):
        self.__debug_send(qemu_protocol.ENABLE_SAMPLING)

    def disable_sampling_mode(self):
        self.__debug_send(qemu_protocol.DISABLE_SAMPLING)

    def submit_sampling_run(self):
        self.__debug_send(qemu_protocol.COMMIT_FILTER)

    def execute_in_trace_mode(self, timeout_detection):
        log_qemu("Performing trace iteration...", self.qemu_id)
        exec_res = None
        try:
            self.soft_reload()
            self.send_enable_trace()
            exec_res = self.send_payload(timeout_detection=timeout_detection)
            self.soft_reload()
            self.send_disable_trace()
        except Exception as e:
            log_qemu("Error during trace: %s" % str(e), self.qemu_id)
            return None

        return exec_res

    def execute_in_redqueen_mode(self, payload):
        log_qemu("Performing redqueen iteration...", self.qemu_id)
        try:
            self.soft_reload()
            self.send_rq_set_light_instrumentation()
            self.send_enable_redqueen()
            self.set_payload(payload)
            self.send_payload(timeout_detection=False)
        except Exception as e:
            log_qemu("%s" % traceback.format_exc(), self.qemu_id)
            return False

        #log_qemu("Disabling redqueen mode...", self.qemu_id)
        try:
            self.send_disable_redqueen()
            self.set_payload(payload)
            self.send_payload(timeout_detection=False)
            self.soft_reload()
        except Exception as e:
            log_qemu("%s" % traceback.format_exc(), self.qemu_id)
            return False
        return True

    def set_payload(self, payload):
        if self.exiting:
            sys.exit(0)

        # TODO: enforce single global size limit through frontend/mutations/backend
        # PAYLOAD_SIZE-sizeof(uint32)-sizeof(uint8) = 131067!
        payload_limit = self.payload_size - 16
        if len(payload) > payload_limit:
            payload = payload[:payload_limit]

        try:
            self.fs_shm.seek(0)
            input_len = to_string_32(len(payload))
            self.fs_shm.write_byte(input_len[3])
            self.fs_shm.write_byte(input_len[2])
            self.fs_shm.write_byte(input_len[1])
            self.fs_shm.write_byte(input_len[0])
            self.fs_shm.write(payload)
            self.fs_shm.flush()
        except:
            if self.exiting:
                sys.exit(0)
            # Qemu crashed. Could be due to prior payload but more likely harness/config is broken..
            print_fail("Failed to set new payload - Qemu crash?")
            log_qemu("Failed to set new payload - Qemu crash?", self.qemu_id)
            raise
Esempio n. 6
0
def verify_dbg(config, qemu_verbose=False):
    global thread_done

    print("Starting...")

    rq_state = RedqueenState()
    workdir = RedqueenWorkdir(1337)

    if os.path.exists("patches"):
        with open("patches", "r") as f:
            for x in f.readlines():
                rq_state.add_candidate_hash_addr(int(x, 16))
    if not rq_state.get_candidate_hash_addrs():
        print("WARNING: no patches configured\n")
        print("Maybe add ./patches with addresses to patch\n")
    else:
        print("OK: got patches %s\n", rq_state.get_candidate_hash_addrs())
    q = qemu(1337, config, debug_mode=True)

    print("using qemu command:\n%s\n" % q.cmd)

    q.start()

    orig_input = read_binary_file(config.argument_values["input"])
    q.set_payload(orig_input)

    # result = q.send_payload()

    with open(q.redqueen_workdir.whitelist(), "w") as w:
        with open(q.redqueen_workdir.patches(), "w") as p:
            for addr in rq_state.get_candidate_hash_addrs():
                addr = hex(addr).rstrip("L").lstrip("0x") + "\n"
                w.write(addr)
                p.write(addr)

    print("RUN WITH PATCHING:")
    bmp1 = q.send_payload(apply_patches=True)

    print("\nNOT PATCHING:")
    bmp2 = q.send_payload(apply_patches=False)

    if bmp1 == bmp2:
        print(
            "WARNING: patches don't seem to change anything, are checksums present?"
        )
    else:
        print("OK: bitmaps are distinct")

    q.soft_reload()

    hash = HashFixer(q, rq_state)

    print("fixing hashes\n")
    fixed_payload = hash.try_fix_data(orig_input)
    if fixed_payload:

        print("%s\n", repr("".join(map(chr, fixed_payload))))

        q.set_payload(fixed_payload)

        bmp3 = q.send_payload(apply_patches=False)

        if bmp1 == bmp3:
            print("CONGRATZ, BITMAPS ARE THE SAME, all cmps fixed\n")
        else:
            print("Warning, after fixing cmps, bitmaps differ\n")
    else:
        print("couldn't fix payload\n")

    start = time.time()
    return 0
Esempio n. 7
0
    def __init__(self, qid, config, debug_mode=False, notifiers=True):

        self.bb_count = 0
        self.hprintf_print_mode = True
        self.internal_buffer_overflow_counter = 0

        self.handshake_stage_1 = True
        self.handshake_stage_2 = True

        self.debug_mode = debug_mode
        self.patches_enabled = False
        self.needs_execution_for_patches = False
        self.debug_counter = 0

        self.bitmap_size = config.config_values['BITMAP_SHM_SIZE']
        self.config = config
        self.qemu_id = str(qid)

        self.process = None
        self.intervm_tty_write = None
        self.control = None
        self.control_fileno = None

        project_name = self.config.argument_values['work_dir'].split("/")[-1]
        self.payload_filename = "/dev/shm/kafl_%s_qemu_payload_%s" % (project_name, self.qemu_id)
        self.tracedump_filename = "/dev/shm/kafl_%s_pt_trace_dump_%s" % (project_name, self.qemu_id)
        self.binary_filename = self.config.argument_values['work_dir'] + "/program"
        self.bitmap_filename = "/dev/shm/kafl_%s_bitmap_%s" % (project_name, self.qemu_id)

        self.control_filename = self.config.argument_values['work_dir'] + "/interface_" + self.qemu_id

        self.redqueen_workdir = RedqueenWorkdir(self.qemu_id, config)
        self.redqueen_workdir.init_dir()

        self.start_ticks = 0
        self.end_ticks = 0
        self.tick_timeout_treshold = self.config.config_values["TIMEOUT_TICK_FACTOR"]

        self.cmd =  self.config.config_values['QEMU_KAFL_LOCATION'] + " " 


        if self.config.argument_values.has_key("ram_file"):
            self.cmd += "-hdb " + self.config.argument_values['ram_file'] + " " \
                    "-hda " + self.config.argument_values['overlay_dir'] +  "/overlay_" + self.qemu_id + ".qcow2 "

        if self.config.argument_values.has_key("kernel"):
            self.cmd += "-kernel " + self.config.argument_values['kernel'] + " " \
                    "-initrd " + self.config.argument_values['initramfs'] +  " -append BOOTPARAM "

        self.cmd += "-serial mon:stdio " \
                    "-enable-kvm " \
                    "-k de " \
                    "-m " + str(config.argument_values['mem']) + " " \
                    "-nographic " \
                    "-net user " \
                    "-net nic " \
                    "-chardev socket,server,nowait,path=" + self.control_filename + \
                    ",id=kafl_interface " \
                    "-device kafl,chardev=kafl_interface,bitmap_size=" + str(self.bitmap_size) + ",shm0=" + self.binary_filename + \
                    ",shm1=" + self.payload_filename + \
                    ",bitmap=" + self.bitmap_filename +\
                    ",redqueen_workdir="+self.redqueen_workdir.base_path

        if debug_mode:
            self.cmd += ",debug_mode"

        if not notifiers:
            self.cmd += ",crash_notifier=False"

        self.cmd += ",reload_mode=False"

        if self.config.argument_values.has_key("kernel"):
            self.cmd += ",disable_snapshot=True"

        for i in range(1):
            key = "ip" + str(i)
            if self.config.argument_values.has_key(key) and self.config.argument_values[key]:
                range_a = hex(self.config.argument_values[key][0]).replace("L", "")
                range_b = hex(self.config.argument_values[key][1]).replace("L", "") 
                self.cmd += ",ip" + str(i) + "_a=" + range_a + ",ip" + str(i) + "_b=" + range_b
                self.cmd += ",filter" + str(i) + "=/dev/shm/kafl_filter" + str(i)
          
        if self.config.argument_values.has_key("ram_file"):          
            self.cmd += " -loadvm " + self.config.argument_values["S"] + " "

        if self.config.argument_values["macOS"]:
            self.cmd = self.cmd.replace("-net user -net nic", "-netdev user,id=hub0port0 -device e1000-82545em,netdev=hub0port0,id=mac_vnet0 -cpu Penryn,kvm=off,vendor=GenuineIntel -device isa-applesmc,osk=\"" + self.config.config_values["APPLE-SMC-OSK"].replace("\"", "") + "\" -machine pc-q35-2.4")
            if qid == 0:
                self.cmd = self.cmd.replace("-machine pc-q35-2.4", "-machine pc-q35-2.4 -redir tcp:5901:0.0.0.0:5900 -redir tcp:10022:0.0.0.0:22")
        else:
            self.cmd += " -machine pc-i440fx-2.6 "

        self.kafl_shm_f = None
        self.kafl_shm = None
        self.fs_shm_f = None
        self.fs_shm = None

        self.payload_shm_f = None
        self.payload_shm = None

        self.bitmap_shm_f = None
        self.bitmap_shm = None

        self.e = select.epoll()
        self.crashed = False
        self.timeout = False
        self.kasan = False
        self.shm_problem = False
        self.initial_mem_usage = 0

        self.stat_fd = None

        if qid == 0 or qid == 1337:
            log_qemu("Launching Virtual Maschine...CMD:\n" + self.cmd.replace("BOOTPARAM", "nokaslr oops=panic nopti"),
                     self.qemu_id)
        else:
            log_qemu("Launching Virtual Maschine...", self.qemu_id)
        self.virgin_bitmap = ''.join(chr(0xff) for x in range(self.bitmap_size))

        self.__set_binary(self.binary_filename, self.config.argument_values['executable'], (128 << 20))

        self.cmd = self.cmd.split(" ")
        c = 0
        for i in self.cmd:
            if i == "BOOTPARAM":
                self.cmd[c] = "\"nokaslr oops=panic nopti\""
                break
            c += 1
Esempio n. 8
0
class qemu:
    SC_CLK_TCK = os.sysconf(os.sysconf_names['SC_CLK_TCK'])

    CMDS = qemu_protocol.CMDS

    def __init__(self, qid, config, debug_mode=False, notifiers=True):

        self.bb_count = 0
        self.hprintf_print_mode = True
        self.internal_buffer_overflow_counter = 0

        self.handshake_stage_1 = True
        self.handshake_stage_2 = True

        self.debug_mode = debug_mode
        self.patches_enabled = False
        self.needs_execution_for_patches = False
        self.debug_counter = 0

        self.bitmap_size = config.config_values['BITMAP_SHM_SIZE']
        self.config = config
        self.qemu_id = str(qid)

        self.process = None
        self.intervm_tty_write = None
        self.control = None
        self.control_fileno = None

        project_name = self.config.argument_values['work_dir'].split("/")[-1]
        self.payload_filename = "/dev/shm/kafl_%s_qemu_payload_%s" % (project_name, self.qemu_id)
        self.tracedump_filename = "/dev/shm/kafl_%s_pt_trace_dump_%s" % (project_name, self.qemu_id)
        self.binary_filename = self.config.argument_values['work_dir'] + "/program"
        self.bitmap_filename = "/dev/shm/kafl_%s_bitmap_%s" % (project_name, self.qemu_id)

        self.control_filename = self.config.argument_values['work_dir'] + "/interface_" + self.qemu_id

        self.redqueen_workdir = RedqueenWorkdir(self.qemu_id, config)
        self.redqueen_workdir.init_dir()

        self.start_ticks = 0
        self.end_ticks = 0
        self.tick_timeout_treshold = self.config.config_values["TIMEOUT_TICK_FACTOR"]

        self.cmd =  self.config.config_values['QEMU_KAFL_LOCATION'] + " " 


        if self.config.argument_values.has_key("ram_file"):
            self.cmd += "-hdb " + self.config.argument_values['ram_file'] + " " \
                    "-hda " + self.config.argument_values['overlay_dir'] +  "/overlay_" + self.qemu_id + ".qcow2 "

        if self.config.argument_values.has_key("kernel"):
            self.cmd += "-kernel " + self.config.argument_values['kernel'] + " " \
                    "-initrd " + self.config.argument_values['initramfs'] +  " -append BOOTPARAM "

        self.cmd += "-serial mon:stdio " \
                    "-enable-kvm " \
                    "-k de " \
                    "-m " + str(config.argument_values['mem']) + " " \
                    "-nographic " \
                    "-net user " \
                    "-net nic " \
                    "-chardev socket,server,nowait,path=" + self.control_filename + \
                    ",id=kafl_interface " \
                    "-device kafl,chardev=kafl_interface,bitmap_size=" + str(self.bitmap_size) + ",shm0=" + self.binary_filename + \
                    ",shm1=" + self.payload_filename + \
                    ",bitmap=" + self.bitmap_filename +\
                    ",redqueen_workdir="+self.redqueen_workdir.base_path

        if debug_mode:
            self.cmd += ",debug_mode"

        if not notifiers:
            self.cmd += ",crash_notifier=False"

        self.cmd += ",reload_mode=False"

        if self.config.argument_values.has_key("kernel"):
            self.cmd += ",disable_snapshot=True"

        for i in range(1):
            key = "ip" + str(i)
            if self.config.argument_values.has_key(key) and self.config.argument_values[key]:
                range_a = hex(self.config.argument_values[key][0]).replace("L", "")
                range_b = hex(self.config.argument_values[key][1]).replace("L", "") 
                self.cmd += ",ip" + str(i) + "_a=" + range_a + ",ip" + str(i) + "_b=" + range_b
                self.cmd += ",filter" + str(i) + "=/dev/shm/kafl_filter" + str(i)
          
        if self.config.argument_values.has_key("ram_file"):          
            self.cmd += " -loadvm " + self.config.argument_values["S"] + " "

        if self.config.argument_values["macOS"]:
            self.cmd = self.cmd.replace("-net user -net nic", "-netdev user,id=hub0port0 -device e1000-82545em,netdev=hub0port0,id=mac_vnet0 -cpu Penryn,kvm=off,vendor=GenuineIntel -device isa-applesmc,osk=\"" + self.config.config_values["APPLE-SMC-OSK"].replace("\"", "") + "\" -machine pc-q35-2.4")
            if qid == 0:
                self.cmd = self.cmd.replace("-machine pc-q35-2.4", "-machine pc-q35-2.4 -redir tcp:5901:0.0.0.0:5900 -redir tcp:10022:0.0.0.0:22")
        else:
            self.cmd += " -machine pc-i440fx-2.6 "

        self.kafl_shm_f = None
        self.kafl_shm = None
        self.fs_shm_f = None
        self.fs_shm = None

        self.payload_shm_f = None
        self.payload_shm = None

        self.bitmap_shm_f = None
        self.bitmap_shm = None

        self.e = select.epoll()
        self.crashed = False
        self.timeout = False
        self.kasan = False
        self.shm_problem = False
        self.initial_mem_usage = 0

        self.stat_fd = None

        if qid == 0 or qid == 1337:
            log_qemu("Launching Virtual Maschine...CMD:\n" + self.cmd.replace("BOOTPARAM", "nokaslr oops=panic nopti"),
                     self.qemu_id)
        else:
            log_qemu("Launching Virtual Maschine...", self.qemu_id)
        self.virgin_bitmap = ''.join(chr(0xff) for x in range(self.bitmap_size))

        self.__set_binary(self.binary_filename, self.config.argument_values['executable'], (128 << 20))

        self.cmd = self.cmd.split(" ")
        c = 0
        for i in self.cmd:
            if i == "BOOTPARAM":
                self.cmd[c] = "\"nokaslr oops=panic nopti\""
                break
            c += 1

    def __debug_hprintf(self):
        try:
            if self.debug_counter < 512:
                data = ""
                for line in open("/tmp/kAFL_printf.txt." + str(self.debug_counter)):
                    data += line
                self.debug_counter += 1
                if data.endswith('\n'):
                    data = data[:-1]
                if self.hprintf_print_mode:
                    print("[HPRINTF]\t" + '\033[0;33m' + data + '\033[0m')
                else:
                    print('\033[0;33m' + data + '\033[0m')
        except Exception as e:
            print("__debug_hprintf: " + str(e))

    def __debug_print_timeout(self):
        if self.debug_mode:
            print("[EVENT]  \t" + '\033[1m' + '\033[91m' + "TIMEOUT" + '\033[0m')

    def send_enable_redqueen(self):
        self.__debug_send(qemu_protocol.ENABLE_RQI_MODE)
        self.__debug_recv_expect(qemu_protocol.ENABLE_RQI_MODE)

    def send_disable_redqueen(self):
        self.__debug_send(qemu_protocol.DISABLE_RQI_MODE)
        self.__debug_recv_expect(qemu_protocol.DISABLE_RQI_MODE)

    def send_enable_patches(self):
        if not self.patches_enabled:
            assert (not self.needs_execution_for_patches)
            self.needs_execution_for_patches = True
            self.patches_enabled = True
            self.__debug_send(qemu_protocol.ENABLE_PATCHES)
            self.__debug_recv_expect(qemu_protocol.ENABLE_PATCHES)

    def send_disable_patches(self):
        if self.patches_enabled:
            assert (not self.needs_execution_for_patches)
            self.needs_execution_for_patches = True
            self.patches_enabled = False
            self.__debug_send(qemu_protocol.DISABLE_PATCHES)
            self.__debug_recv_expect(qemu_protocol.DISABLE_PATCHES)
        pass

    def send_enable_trace(self):
        self.__debug_send(qemu_protocol.ENABLE_TRACE_MODE)
        self.__debug_recv_expect(qemu_protocol.ENABLE_TRACE_MODE)

    def send_disable_trace(self):
        self.__debug_send(qemu_protocol.DISABLE_TRACE_MODE)
        self.__debug_recv_expect(qemu_protocol.DISABLE_TRACE_MODE)

    def send_rq_set_light_instrumentation(self):
        self.__debug_send(qemu_protocol.REDQUEEN_SET_LIGHT_INSTRUMENTATION)
        self.__debug_recv_expect(qemu_protocol.REDQUEEN_SET_LIGHT_INSTRUMENTATION)

    def send_rq_set_se_instrumentation(self):
        self.__debug_send(qemu_protocol.REDQUEEN_SET_SE_INSTRUMENTATION)
        self.__debug_recv_expect(qemu_protocol.REDQUEEN_SET_SE_INSTRUMENTATION)

    def send_rq_set_whitelist_instrumentation(self):
        self.__debug_send(qemu_protocol.REDQUEEN_SET_WHITELIST_INSTRUMENTATION)
        self.__debug_recv_expect(qemu_protocol.REDQUEEN_SET_WHITELIST_INSTRUMENTATION)

    def send_rq_update_blacklist(self):
        self.__debug_send(qemu_protocol.REDQUEEN_SET_BLACKLIST)
        self.__debug_recv_expect(qemu_protocol.REDQUEEN_SET_BLACKLIST)

    def __debug_send(self, cmd):
        self.last_bitmap_wrapper.invalidate()
        if self.debug_mode:
            try:
                info = ""
                if self.handshake_stage_1 and cmd == qemu_protocol.RELEASE:
                    info = " (Loader Handshake)"
                    self.handshake_stage_1 = False
                elif self.handshake_stage_2 and cmd == qemu_protocol.RELEASE:
                    info = " (Initial Handshake Iteration)"
                    self.handshake_stage_2 = False
                print("[SEND]  \t" + '\033[94m' + self.CMDS[cmd] + info + '\033[0m')
            except:
                print("[SEND]  \t" + "unknown cmd '" + res + "'")
        self.control.send(cmd)

    def __debug_recv(self):
        while True:
            res = self.control.recv(1)
            if (len(res) == 0):
                log_qemu("__debug_recv error?", self.qemu_id)
                break

            if res == qemu_protocol.PRINTF:
                self.__debug_hprintf()
                self.hprintf_print_mode = False
            else:
                self.hprintf_print_mode = True
                if self.debug_mode:
                    if res == qemu_protocol.ACQUIRE:
                        self.debug_counter = 0
                    # try:
                    info = ""
                    if self.handshake_stage_1 and res == qemu_protocol.RELEASE:
                        info = " (Loader Handshake)"
                    elif self.handshake_stage_2 and res == qemu_protocol.ACQUIRE:
                        info = " (Initial Handshake Iteration)"
                    elif res == qemu_protocol.INFO:
                        print("[RECV]  \t" + '\033[1m' + '\033[92m' + self.CMDS[res] + info + '\033[0m')
                        print("------------------------------------------------------")
                        try:
                            for line in open("/tmp/kAFL_info.txt"):
                                print line,
                            os.remove("/tmp/kAFL_info.txt")
                        except:
                            pass
                        print("------------------------------------------------------")
                        os._exit(0)
                    elif res == qemu_protocol.ABORT:
                        print(common.color.FAIL + self.CMDS[res] + common.color.ENDC)
                        # print("[RECV]  \t" + common.color.FAIL + self.CMDS[res] + common.color.ENDC)
                        os._exit(0)
                    if res == qemu_protocol.CRASH or res == qemu_protocol.KASAN:
                        print("[RECV]  \t" + '\033[1m' + '\033[91m' + self.CMDS[res] + info + '\033[0m')
                    else:
                        print("[RECV]  \t" + '\033[1m' + '\033[92m' + self.CMDS[res] + info + '\033[0m')
                    # except Exception as e:
                    #    print("[RECV]  \t" + "unknown cmd '" + res + "'" + str(e))
                return res

    def __debug_recv_expect(self, cmd):
        res = ''
        while True:

            res = self.__debug_recv()
            if res in cmd:
                break
            elif res is None:
                log_qemu("FAIL New Reload!", self.qemu_id)
                # self.__debug_send(qemu_protocol.RELOAD)
            else:
                # Fixme !!!!!
                log_qemu("FAIL RECV: " + str(res) + "  (Exp: " + str(cmd) + ")", self.qemu_id)
        if res == qemu_protocol.PT_TRASHED:
            log_qemu("PT_TRASHED")
            return False
        return True

    def __del__(self):
        #safe_print("killing slave")
        os.system("kill -9 " + str(self.process.pid))

        try:
            if self.process:
                try:
                    self.process.kill()
                except:
                    pass

            if self.e:
                if self.control_fileno:
                    self.e.unregister(self.control_fileno)

            if self.intervm_tty_write:
                self.intervm_tty_write.close()
            # if self.control:
            #    self.control.close()
        except OSError:
            pass

        try:
            self.kafl_shm.close()
        except:
            pass

        try:
            self.fs_shm.close()
        except:
            pass

        try:
            os.close(self.kafl_shm_f)
        except:
            pass

        try:
            os.close(self.fs_shm_f)
        except:
            pass

        try:
            if self.stat_fd:
                self.stat_fd.close()
        except:
            pass

    def __get_pid_guest_ticks(self):
        if self.stat_fd:
            self.stat_fd.seek(0)
            self.stat_fd.flush()
            return int(self.stat_fd.readline().split(" ")[42])
        return 0

    def __set_binary(self, filename, binaryfile, max_size):
        bin = read_binary_file(binaryfile)
        assert (len(bin) <= max_size)
        atomic_write(filename, bin)

    def set_tick_timeout_treshold(self, treshold):
        self.tick_timeout_treshold = treshold

    def start(self, verbose=False, payload=None):
        if verbose:
            self.process = subprocess.Popen(filter(None, self.cmd),
                                            stdin=None,
                                            stdout=None,
                                            stderr=None)
        else:
            self.process = subprocess.Popen(filter(None, self.cmd),
                                            stdin=subprocess.PIPE,
                                            stdout=subprocess.PIPE,
                                            stderr=None)

        self.stat_fd = open("/proc/" + str(self.process.pid) + "/stat")
        self.init()
        try:
            self.set_init_state(payload=payload)
        except:
            return False
        self.initial_mem_usage = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss
        # time.sleep(1)
        self.kafl_shm.seek(0x0)
        self.kafl_shm.write(self.virgin_bitmap)
        # self.kafl_shm.flush()
        return True

    def set_init_state(self, payload=None):
        self.crashed = False
        self.timeout = False
        self.kasan = False
        self.handshake_stage_1 = True
        self.handshake_stage_2 = True
        self.start_ticks = 0
        self.end_ticks = 0

        self.__set_binary(self.binary_filename, self.config.argument_values['executable'], (128 << 20))

        self.__debug_recv_expect(qemu_protocol.RELEASE + qemu_protocol.PT_TRASHED)
        log_qemu("Initial stage 1 handshake done...", self.qemu_id)
        self.__debug_send(qemu_protocol.RELEASE)
        self.__debug_recv_expect(qemu_protocol.ACQUIRE + qemu_protocol.PT_TRASHED)
        log_qemu("Initial stage 2 handshake done...", self.qemu_id)
        if payload:
            self.set_payload(payload)
        self.send_payload(timeout_detection=False, apply_patches=False)
        self.crashed = False
        self.timeout = False
        self.kasan = False

    def init(self):
        self.control = safe_socket(socket.AF_UNIX)
        self.control.settimeout(None)
        self.control.setblocking(1)
        while True:
            try:
                self.control.connect(self.control_filename)
                # self.control.connect(self.control_filename)
                break
            except socket_error:
                pass
                # time.sleep(0.01)

        self.kafl_shm_f = os.open(self.bitmap_filename, os.O_RDWR | os.O_SYNC | os.O_CREAT)
        self.fs_shm_f = os.open(self.payload_filename, os.O_RDWR | os.O_SYNC | os.O_CREAT)

        open(self.tracedump_filename, "wb").close()

        os.symlink(self.tracedump_filename, self.config.argument_values['work_dir'] + "/pt_trace_dump_" + self.qemu_id)

        os.symlink(self.payload_filename, self.config.argument_values['work_dir'] + "/payload_" + self.qemu_id)
        os.symlink(self.bitmap_filename, self.config.argument_values['work_dir'] + "/bitmap_" + self.qemu_id)

        # argv_fd             = os.open(self.argv_filename, os.O_RDWR | os.O_SYNC | os.O_CREAT)
        os.ftruncate(self.kafl_shm_f, self.bitmap_size)
        os.ftruncate(self.fs_shm_f, (128 << 10))
        # os.ftruncate(argv_fd, (4 << 10))

        self.kafl_shm = mmap.mmap(self.kafl_shm_f, self.bitmap_size, mmap.MAP_SHARED, mmap.PROT_WRITE | mmap.PROT_READ)
        self.c_bitmap = (ctypes.c_uint8 * self.bitmap_size).from_buffer(self.kafl_shm)
        self.last_bitmap_wrapper = ExecutionResult(None, None, None, None)
        self.fs_shm = mmap.mmap(self.fs_shm_f, (128 << 10), mmap.MAP_SHARED, mmap.PROT_WRITE | mmap.PROT_READ)

        return True

    def soft_reload(self):
        return

    def check_recv(self, timeout_detection=True):
        result = self.__debug_recv()

        if result == qemu_protocol.CRASH:
            return 1
        elif result == qemu_protocol.KASAN:
            return 3
        elif result == qemu_protocol.TIMEOUT:
            return 7
        elif result == qemu_protocol.ACQUIRE:
            return 0
        elif result == qemu_protocol.PT_TRASHED:
            self.internal_buffer_overflow_counter += 1
            return 4
        elif result == qemu_protocol.PT_TRASHED_CRASH:
            self.internal_buffer_overflow_counter += 1
            return 5
        elif result == qemu_protocol.PT_TRASHED_KASAN:
            self.internal_buffer_overflow_counter += 1
            return 6
        return 0

    def get_bb_delta(self):
        self.fs_shm.seek(0x1F800)

        new_value = struct.unpack("Q", self.fs_shm.read(8))[0]
        delta = new_value - self.bb_count
        self.bb_count = new_value
        return delta

    def send_payload(self, apply_patches=True, timeout_detection=True, max_iterations=10):

        start_time = time.time()
        if apply_patches:
            self.send_enable_patches()
        else:
            self.send_disable_patches()
        self.__debug_send(qemu_protocol.RELEASE)

        self.crashed = False
        self.timeout = False
        self.kasan = False

        repeat = False
        value = self.check_recv(timeout_detection=timeout_detection)
        if value == 1:
            self.crashed = True
            self.__debug_recv_expect(qemu_protocol.ACQUIRE)
        elif value == 2:
            self.timeout = True
            self.__debug_print_timeout()
            cmd = self.__debug_recv()
            self.__debug_recv_expect(qemu_protocol.ACQUIRE)

        elif value == 3:
            self.kasan = True
            self.__debug_recv_expect(qemu_protocol.ACQUIRE)
        elif value == 4:
            repeat = True
        elif value == 5:
            repeat = True
            self.soft_reload()
        elif value == 6:
            repeat = True
            self.soft_reload()
        elif value == 7:
            self.timeout= True

        self.needs_execution_for_patches = False

        if repeat:
            if max_iterations != 0:
                self.send_payload(apply_patches=apply_patches, timeout_detection=timeout_detection, max_iterations=0)
                res = self.send_payload(apply_patches=apply_patches, timeout_detection=timeout_detection,
                                        max_iterations=max_iterations - 1)
                res.performance = time.time() - start_time()
                return res

        self.last_bitmap_wrapper = ExecutionResult(self.c_bitmap, self.bitmap_size, self.exit_reason(),
                                                   time.time() - start_time)
        return self.last_bitmap_wrapper

    def exit_reason(self):
        if self.crashed:
            return "crash"
        elif self.timeout:
            return "timeout"
        elif self.kasan:
            return "kasan"
        else:
            return "regular"

    def enable_sampling_mode(self):
        self.__debug_send(qemu_protocol.ENABLE_SAMPLING)

    def disable_sampling_mode(self):
        self.__debug_send(qemu_protocol.DISABLE_SAMPLING)

    def submit_sampling_run(self):
        self.__debug_send(qemu_protocol.COMMIT_FILTER)

    def execute_in_trace_mode(self, debug_mode, timeout_detection):
        log_qemu("Performing trace iteration...", self.qemu_id)
        if debug_mode:
            print("Performing trace iteration...")
        try:
            self.soft_reload()
            self.send_enable_trace()
            self.send_payload(timeout_detection=timeout_detection)
        except Exception as e:
            if debug_mode:
                print("Fail 1...(" + str(e) + ")")
            log_qemu("Fail 1...(" + str(e) + ")", self.qemu_id)
            return False

        try:
            self.soft_reload()
            self.send_disable_trace()
        except Exception as e:
            log_qemu("Fail 3...(" + str(e) + ")", self.qemu_id)
            log_qemu("%s" % traceback.format_exc(), self.qemu_id)
            return False
        return True

    def execute_in_redqueen_mode(self, payload, debug_mode):
        log_qemu("Performing regulare iteration...", self.qemu_id)
        if debug_mode:
            print("Performing regulare iteration...")
        try:
            self.soft_reload()
            self.set_payload(payload)
            self.send_payload()
        except Exception as e:
            if debug_mode:
                print("Fail 1...(" + str(e) + ")")
            log_qemu("Fail 1...(" + str(e) + ")", self.qemu_id)
            return False

        log_qemu("Enabling redqueen mode...", self.qemu_id)
        if debug_mode:
            print("Enabling redqueen mode...")
        try:
            self.soft_reload()
            self.send_rq_set_light_instrumentation()
            self.send_enable_redqueen()
            self.set_payload(payload)
            self.send_payload(timeout_detection=False)
        except Exception as e:
            log_qemu("Fail 3...(" + str(e) + ")", self.qemu_id)
            log_qemu("%s" % traceback.format_exc(), self.qemu_id)
            return False

        log_qemu("Disabling redqueen mode...", self.qemu_id)
        if debug_mode:
            print("Disabling redqueen mode...")
        try:
            self.send_disable_redqueen()
            self.set_payload(payload)
            self.send_payload(timeout_detection=False)
            self.soft_reload()
        except Exception as e:
            log_qemu("Fail 4...(" + str(e) + ")", self.qemu_id)
            log_qemu("%s" % traceback.format_exc(), self.qemu_id)
            return False
        return True

    def modify_payload_size(self, new_size):
        self.fs_shm.seek(0)
        input_len = to_string_32(new_size)
        self.fs_shm.write_byte(input_len[3])
        self.fs_shm.write_byte(input_len[2])
        self.fs_shm.write_byte(input_len[1])
        self.fs_shm.write_byte(input_len[0])

    def copy_master_payload(self, shm, num, size):
        self.fs_shm.seek(0)
        shm.seek(size * num)
        payload = shm.read(size)
        self.fs_shm.write(payload)
        self.fs_shm.write(''.join(chr(0x00) for x in range((64 << 10) - size)))
        # self.fs_shm.flush()
        return payload, size

    def copy_mapserver_payload(self, shm, num, size):
        self.fs_shm.seek(0)
        shm.seek(size * num)
        shm.write(self.fs_shm.read(size))
        # shm.flush()

    def set_payload(self, payload):
        if len(payload) > 65400:
            payload = payload[:65400]
        self.fs_shm.seek(0)
        input_len = to_string_32(len(payload))
        # Fixed
        self.fs_shm.write_byte(input_len[3])
        self.fs_shm.write_byte(input_len[2])
        self.fs_shm.write_byte(input_len[1])
        self.fs_shm.write_byte(input_len[0])
        self.fs_shm.write(payload)