def setup(self): ''' Make sure the monitor is ready for fuzzing ''' self._cleanup() self.monitor_thread = LoopFuncThread(self._monitor_func) self.monitor_thread.start()
def setup(self): ''' Make sure the monitor is ready for fuzzing ''' super(BaseMonitor, self).setup() self.monitor_thread = LoopFuncThread(self._monitor_func) self.monitor_thread.start()
class BaseMonitor(KittyActorInterface): ''' Base (abstract) monitor class ''' def __init__(self, name, logger=None, victim_alive_check_delay=0.3): ''' :param name: name of the actor :param logger: logger for the actor (default: None) :param victim_alive_check_delay: delay between checks if alive (default: 0.3) ''' super(BaseMonitor, self).__init__(name, logger, victim_alive_check_delay) self.monitor_thread = None def setup(self): ''' Make sure the monitor is ready for fuzzing ''' super(BaseMonitor, self).setup() self.monitor_thread = LoopFuncThread(self._monitor_func) self.monitor_thread.start() def teardown(self): ''' cleanup the monitor data and ''' self.monitor_thread.stop() self.monitor_thread = None super(BaseMonitor, self).teardown() def pre_test(self, test_number): ''' Called when a test is started :param test_number: current test number ''' if not self._is_alive(): self.setup() super(BaseMonitor, self).pre_test(test_number) def _is_alive(self): ''' Check if the monitor is alive ''' if self.monitor_thread is not None: if self.monitor_thread.is_alive(): return True return False def _monitor_func(self): ''' Called in a loop in a separate thread (self.monitor_thread). ''' self.not_implemented('_monitor_func')
def __init__(self, name='ClientFuzzer', logger=None, option_line=None): ''' :param name: name of the object :param logger: logger for the object (default: None) :param option_line: cmd line options to the fuzzer ''' super(ClientFuzzer, self).__init__(name, logger, option_line) self._target_control_thread = LoopFuncThread(self._do_trigger) self._trigger_stop_evt = Event() self._target_control_thread.set_func_stop_event(self._trigger_stop_evt) self._index_in_path = 0 self._requested_stages = [] self._report = None self._done_evt = Event()
def __init__(self, name='ClientFuzzer', logger=None, option_line=None): ''' :param name: name of the object :param logger: logger for the object (default: None) :param option_line: cmd line options to the fuzzer ''' super(ClientFuzzer, self).__init__(name, logger, option_line) self._target_control_thread = LoopFuncThread(self._do_trigger) self._trigger_stop_evt = Event() self._target_control_thread.set_func_stop_event(self._trigger_stop_evt) self._index_in_path = 0
class ClientFuzzer(BaseFuzzer): ''' ClientFuzzer is designed for fuzzing clients. It does not preform an active fuzzing, but rather returns a mutation of a response when in the right state. It is designed to be a module that is integrated into different stacks. You can see its usahe examples in the following places: - examples/02_client_fuzzer_browser_remote - examples/03_client_fuzzer_browser ''' # Wild card for matching any stage STAGE_ANY = '******************' def __init__(self, name='ClientFuzzer', logger=None, option_line=None): ''' :param name: name of the object :param logger: logger for the object (default: None) :param option_line: cmd line options to the fuzzer ''' super(ClientFuzzer, self).__init__(name, logger, option_line) self._target_control_thread = LoopFuncThread(self._do_trigger) self._trigger_stop_evt = Event() self._target_control_thread.set_func_stop_event(self._trigger_stop_evt) self._index_in_path = 0 self._requested_stages = [] self._report = None self._done_evt = Event() def _pre_test(self): self._requested_stages = [] self._report = Report(self.get_name()) super(ClientFuzzer, self)._pre_test() def is_done(self): ''' check if fuzzer is done fuzzing :return: True if done ''' return self._done_evt.is_set() def wait_until_done(self): ''' wait until fuzzer is done ''' self._done_evt.wait() def stop(self): ''' Stop the fuzzing session ''' self.logger.info('Stopping client fuzzer') self._target_control_thread.stop() self.target.signal_mutated() super(ClientFuzzer, self).stop() def _do_trigger(self): self.logger.debug('_do_trigger called') self._check_pause() if self._next_mutation(): self._fuzz_path = self.model.get_sequence() self._index_in_path = 0 self._pre_test() self._test_info() self.target.trigger() self._post_test() else: self._end_message() self._done_evt.set() self._trigger_stop_evt.wait() def _start(self): self._target_control_thread.start() def _test_environment(self): ''' .. todo:: can we do that here somehow? ''' pass def _should_fuzz_node(self, fuzz_node, stage): ''' The matching stage is either the name of the last node, or ClientFuzzer.STAGE_ANY. :return: True if we are in the correct model node ''' if stage == ClientFuzzer.STAGE_ANY: return True if fuzz_node.name.lower() == stage.lower(): if self._index_in_path == len(self._fuzz_path) - 1: return True else: return False def _update_path_index(self, stage): last_index_in_path = len(self._fuzz_path) - 1 if self._index_in_path < last_index_in_path: node = self._fuzz_path[self._index_in_path].dst if node.name.lower() == stage.lower(): self._index_in_path += 1 def get_mutation(self, stage, data): ''' Get the next mutation, if in the correct stage :param stage: current stage of the stack :param data: a dictionary of items to pass to the model :return: mutated payload if in apropriate stage, None otherwise ''' payload = None # Commented out for now: we want to return the same # payload - while inside the same test # if self._keep_running() and self._do_fuzz.is_set(): if self._keep_running(): fuzz_node = self._fuzz_path[self._index_in_path].dst if self._should_fuzz_node(fuzz_node, stage): fuzz_node.set_session_data(data) payload = fuzz_node.render().tobytes() self._last_payload = payload else: self._update_path_index(stage) if payload: self._notify_mutated() self._requested_stages.append((stage, payload)) return payload def _notify_mutated(self): self.target.signal_mutated() def _get_report(self): base_report = super(ClientFuzzer, self)._get_report() if len(self._requested_stages): stages, payloads = zip(*self._requested_stages) else: stages = [] payloads = [] self._report.add('stages', stages) self._report.add('payloads', [ None if payload is None else hexlify(payload) for payload in payloads ]) base_report.add('fuzzer', self._report) return base_report
class BaseMonitor(KittyObject): ''' Base (abstract) monitor class ''' def __init__(self, name, logger=None): ''' :param name: name of the monitor :param logger: logger for the monitor (default: None) ''' super(BaseMonitor, self).__init__(name, logger) self.report = Report(name) self.monitor_thread = None self.test_number = None def setup(self): ''' Make sure the monitor is ready for fuzzing ''' self._cleanup() self.monitor_thread = LoopFuncThread(self._monitor_func) self.monitor_thread.start() def teardown(self): ''' cleanup the monitor data and ''' self.monitor_thread.stop() self.monitor_thread = None def pre_test(self, test_number): ''' Called when a test is started :param test_number: current test number ''' if not self._is_alive(): self.setup() self._cleanup() self.test_number = test_number self.report.add('state', 'STARTED') self.report.add('start_time', time.time()) self.report.add('name', self.name) def post_test(self): ''' Called when a test is completed, prepare the report etc. ''' self.report.add('state', 'STOPPED') self.report.add('stop_time', time.time()) def _is_alive(self): ''' Check if victim/monitor alive ''' if self.monitor_thread is not None: if self.monitor_thread.is_alive(): return True return False def _cleanup(self): ''' perform a monitor cleanup ''' self.report = Report(self.name) def get_report(self): ''' :return: the monitor's report ''' return self.report def _monitor_func(self): ''' Called in a loop in a separate thread (self.monitor_thread). ''' self.not_implemented('_monitor_func')
class ClientFuzzer(BaseFuzzer): ''' ClientFuzzer is designed for fuzzing clients. It does not preform an active fuzzing, but rather returns a mutation of a response when in the right state. It is designed to be a module that is integrated into different stacks. See its usage example in the file examples/client_fuzzer_example.py which designed to fuzz a browser. ''' # Wild card for matching any stage STAGE_ANY = '******************' def __init__(self, name='ClientFuzzer', logger=None, option_line=None): ''' :param name: name of the object :param logger: logger for the object (default: None) :param option_line: cmd line options to the fuzzer ''' super(ClientFuzzer, self).__init__(name, logger, option_line) self._target_control_thread = LoopFuncThread(self._do_trigger) self._trigger_stop_evt = Event() self._target_control_thread.set_func_stop_event(self._trigger_stop_evt) self._index_in_path = 0 self._requested_stages = [] self._report = None self._done_evt = Event() def _pre_test(self): self._requested_stages = [] self._report = Report(self.get_name()) super(ClientFuzzer, self)._pre_test() def is_done(self): ''' check if fuzzer is done fuzzing :return: True if done ''' return self._done_evt.is_set() def wait_until_done(self): ''' wait until fuzzer is done ''' self._done_evt.wait() def stop(self): ''' Stop the fuzzing session ''' self.logger.info('Stopping client fuzzer') self._target_control_thread.stop() self.target.signal_mutated() super(ClientFuzzer, self).stop() def _do_trigger(self): self.logger.debug('_do_trigger called') self._check_pause() if self._keep_running() and self.model.mutate(): self._fuzz_path = self.model.get_sequence() self._index_in_path = 0 self._pre_test() self._test_info() self.target.trigger() self._post_test() else: self._end_message() self._done_evt.set() self._trigger_stop_evt.wait() def _start(self): self._start_message() self.target.setup() self._target_control_thread.start() def _should_fuzz_node(self, fuzz_node, stage): ''' The matching stage is either the name of the last node, or ClientFuzzer.STAGE_ANY. :return: True if we are in the correct model node ''' if stage == ClientFuzzer.STAGE_ANY: return True if fuzz_node.name.lower() == stage.lower(): if self._index_in_path == len(self._fuzz_path) - 1: return True else: return False def get_mutation(self, stage, data): ''' Get the next mutation, if in the correct stage :param stage: current stage of the stack :param data: a dictionary of items to pass to the model :return: mutated payload if in apropriate stage, None otherwise ''' payload = None # Commented out for now: we want to return the same # payload - while inside the same test # if self._keep_running() and self._do_fuzz.is_set(): if self._keep_running(): fuzz_node = self._fuzz_path[self._index_in_path].dst if self._should_fuzz_node(fuzz_node, stage): fuzz_node.set_session_data(data) payload = fuzz_node.render().tobytes() self._last_payload = payload else: self._index_in_path += 1 if self._index_in_path >= len(self._fuzz_path): self._index_in_path = 0 if payload: self._notify_mutated() self._requested_stages.append((stage, payload)) return payload def _notify_mutated(self): self.target.signal_mutated() def _get_report(self): base_report = super(ClientFuzzer, self)._get_report() stages, payloads = zip(*self._requested_stages) self._report.add('stages', stages) self._report.add('payloads', [None if payload is None else hexlify(payload) for payload in payloads]) base_report.add('fuzzer', self._report) return base_report