def finalize_iteration(self): try: self.control.send('F') self.control.recv(1) except: log_exception() log_qemu("finalize_iteration failed...", self.qemu_id)
def start(self, verbose=False, serout=None): if verbose: self.process = subprocess.Popen(filter(None, self.cmd.split(" ")), stdin=None, stdout=serout, #None, stderr=None) else: if serout is None : serout = subprocess.PIPE self.process = subprocess.Popen(filter(None, self.cmd.split(" ")), stdin=subprocess.PIPE, stdout=serout, #subprocess.PIPE, stderr=subprocess.PIPE) log_qemu("process pid %d" % self.process.pid, self.qemu_id) self.stat_fd = open("/proc/" + str(self.process.pid) + "/stat") self.init() try: self.set_init_state() except: log_exception() 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 __restart_vm(self): if self.comm.slave_termination.value: return False self.comm.reload_semaphore.acquire() try: #raise Exception("!") # QEMU is full of memory leaks...fixing it that way... if self.soft_reload_counter >= 32: self.soft_reload_counter = 0 raise Exception("...") self.q.soft_reload() self.soft_reload_counter += 1 except: log_exception() while True: self.q.__del__() self.q = qemu(self.slave_id, self.config) if self.q.start(): break else: time.sleep(0.5) log_slave("Fail Reload", self.slave_id) self.comm.reload_semaphore.release() self.q.set_tick_timeout_treshold(self.stage_tick_treshold * self.timeout_tick_factor) if self.comm.slave_termination.value: return False return True
def verifiy_input(self, payload, bitmap, payload_size, runs=3): crashed = self.crashed timeout = self.timeout kasan = self.kasan failed = False try: self.enable_sampling_mode() init = True tmp_bitmap1 = bitmap for i in range(runs): if not init: self.fs_shm.seek(0) self.fs_shm.write(payload) self.fs_shm.write(''.join(chr(0x00) for x in range((64 << 10)-payload_size))) self.fs_shm.flush() tmp_bitmap1 = self.send_payload(timeout_detection=False) if (self.crashed or self.kasan or self.timeout): break else: self.submit_sampling_run() self.fs_shm.seek(0) self.fs_shm.write(payload) self.fs_shm.write(''.join(chr(0x00) for x in range((64 << 10)-payload_size))) self.fs_shm.flush() tmp_bitmap2 = self.send_payload(timeout_detection=False) if (self.crashed or self.kasan or self.timeout): break else: self.submit_sampling_run() if tmp_bitmap1 == tmp_bitmap2: break init = False except: log_exception() failed = True self.crashed = crashed or self.crashed self.timeout = timeout or self.timeout self.kasan = kasan or self.kasan try: if not self.timeout: self.submit_sampling_run() self.disable_sampling_mode() if not failed: return tmp_bitmap2 else: return bitmap except: log_exception() self.timeout = True return bitmap
def check_recv(self, timeout_detection=True): log_qemu("check recv", self.qemu_id) if timeout_detection: self.control.settimeout(1.25) try: result = self.control.recv(1) #except socket_error, e: except socket.timeout, e: log_exception() #raise Exception("XXX DEBUG TIMEOUT") return "TIMEOUT"
def __respond_bitmap_req(self, response): self.q.set_payload(response.data) while True: try: bitmap = self.q.send_payload() break except: log_exception() log_slave("__respond_bitmap_req failed...", self.slave_id) self.__restart_vm() send_msg(KAFL_TAG_REQ_BITMAP, bitmap, self.comm.to_master_from_slave_queue, source=self.slave_id)
def __del__(self): log_qemu("kill qemu pid %d" % self.process.pid, self.qemu_id) os.system("kill -9 " + str(self.process.pid)) try: if self.process: try: self.process.kill() except: log_exception() 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: log_exception() pass try: self.kafl_shm.close() except: log_exception() pass try: self.fs_shm.close() except: log_exception() pass try: if self.stat_fd: self.stat_fd.close() except: log_exception() pass if self.global_bitmap is not None : self.global_bitmap.close() self.global_bitmap = None if self.global_bitmap_fd is not None : os.close(self.global_bitmap_fd) self.global_bitmap_fd = None
def send_payload(self, timeout_detection=True): """Send a test case to qemu, wait for a response, and read back the coverage map""" log_qemu("send payload", self.qemu_id) self.start_ticks = self.__get_pid_guest_ticks() try: # vm was waiting for next payload, unlock them now that its been provided self.control.send("R") except OSError: log_exception() log_qemu("Failed to send payload...", self.qemu_id) return None self.crashed = False self.timeout = False self.kasan = False if timeout_detection: counter = 0 while True: value = self.check_recv() if value == "TIMEOUT": self.end_ticks = self.__get_pid_guest_ticks() if (self.end_ticks-self.start_ticks) >= self.tick_timeout_treshold: break if counter >= 10: break counter += 1 else: break self.end_ticks = self.__get_pid_guest_ticks() else: value = self.check_recv(timeout_detection=False) log_qemu("check_recv val %s" % value, self.qemu_id) if value == "CRASH": self.crashed = True self.finalize_iteration() elif value == "TIMEOUT": self.timeout = True self.finalize_iteration() elif value == "KASAN": self.kasan = True self.finalize_iteration() elif value == "EOF": log_qemu("QEMU control channel unexpectedly shut down!", self.qemu_id) self.timeout = True # XXX was really qemu shutting down! self.finalize_iteration() self.kafl_shm.seek(0x0) return self.kafl_shm.read(self.bitmap_size)
def __respond_job_req(self, response): results = [] performance = 0.0 counter = 0 self.comm.slave_locks_A[self.slave_id].acquire() for i in range(len(response.data)): if not self.comm.stage_abortion_notifier.value: new_bits = True vm_reloaded = False self.reloaded = False bitmap = "" payload = "" payload_size = 0 if self.comm.slave_termination.value: self.comm.slave_locks_B[self.slave_id].release() send_msg(KAFL_TAG_RESULT, results, self.comm.to_mapserver_queue, source=self.slave_id) return while True: while True: try: payload, payload_size = self.q.copy_master_payload( self.comm.get_master_payload_shm( self.slave_id), i, self.comm.get_master_payload_shm_size()) start_time = time.time() bitmap = self.q.send_payload() performance = time.time() - start_time break except: log_exception() if not self.__restart_vm(): return self.reloaded = True if not bitmap: log_slave("SHM ERROR....", self.slave_id) if not self.__restart_vm(): self.comm.slave_locks_B[self.slave_id].release() send_msg(KAFL_TAG_RESULT, results, self.comm.to_mapserver_queue, source=self.slave_id) return else: break self.q.finalize_iteration() new_bits = self.q.copy_bitmap( self.comm.get_bitmap_shm(self.slave_id), i, self.comm.get_bitmap_shm_size(), bitmap, payload, payload_size, effector_mode=self.comm.effector_mode.value) 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()) if self.comm.slave_termination.value: self.comm.slave_locks_B[self.slave_id].release() send_msg(KAFL_TAG_RESULT, results, self.comm.to_mapserver_queue, source=self.slave_id) return if self.q.timeout and not (self.q.crashed or self.q.kasan): vm_reloaded = True if mmh3.hash64(bitmap) not in self.false_positiv_map: while True: try: if not self.__restart_vm(): return start_time = time.time() bitmap = self.q.send_payload() performance = time.time() - start_time break except: log_exception() pass if not self.q.timeout: #false positiv timeout self.false_positiv_map.add(mmh3.hash64(bitmap)) self.reloaded = False else: #false positiv timeout (already seen) self.reloaded = False counter += 1 if self.q.crashed or self.q.timeout or self.q.kasan or self.reloaded: vm_reloaded = True results.append( FuzzingResult(i, self.q.crashed, (self.q.timeout or self.reloaded), self.q.kasan, response.data[i], self.slave_id, performance, reloaded=vm_reloaded, qid=self.slave_id)) if not self.__restart_vm(): self.comm.slave_locks_B[self.slave_id].release() send_msg(KAFL_TAG_RESULT, results, self.comm.to_mapserver_queue, source=self.slave_id) return self.reloaded = True else: results.append( FuzzingResult(i, self.q.crashed, (self.q.timeout or self.reloaded), self.q.kasan, response.data[i], self.slave_id, performance, reloaded=vm_reloaded, new_bits=new_bits, qid=self.slave_id)) if new_bits and self.auto_reload: self.__restart_vm() self.reloaded = False else: results.append( FuzzingResult(i, False, False, False, response.data[i], self.slave_id, 0.0, reloaded=False, new_bits=False, qid=self.slave_id)) if self.comm.slave_termination.value: self.comm.slave_locks_B[self.slave_id].release() send_msg(KAFL_TAG_RESULT, results, self.comm.to_mapserver_queue, source=self.slave_id) return self.comm.slave_locks_B[self.slave_id].release() send_msg(KAFL_TAG_RESULT, results, self.comm.to_mapserver_queue, source=self.slave_id)
def __respond_sampling_req(self, response): payload = response.data[0] sampling_rate = response.data[1] self.stage_tick_treshold = 0 sampling_counter = 0 sampling_ticks = 0 error_counter = 0 round_checker = 0 self.__restart_vm() self.q.set_payload(payload) filter_hash = self.__check_filter_bitmaps() while True: error = False while True: try: self.q.enable_sampling_mode() bitmap = self.q.send_payload() break except: log_exception() log_slave("Sampling fail...", self.slave_id) if not self.__restart_vm(): return for i in range(5): try: if error_counter >= 2: log_slave("Abort sampling...", self.slave_id) error = False break new_bitmap = self.q.send_payload() if self.q.crashed or self.q.timeout or self.q.kasan: log_slave("Sampling timeout...", self.slave_id) error_counter += 1 if not self.__restart_vm(): error = False break else: self.q.submit_sampling_run() sampling_counter += 1 sampling_ticks = self.q.end_ticks - self.q.start_ticks except: log_exception() log_slave("Sampling wtf??!", self.slave_id) if not self.__restart_vm(): return while True: try: self.q.disable_sampling_mode() break except: log_exception() if not self.__restart_vm(): return tmp_hash = self.__check_filter_bitmaps() if tmp_hash == filter_hash: round_checker += 1 else: round_checker = 0 filter_hash = tmp_hash if round_checker == 5: break log_slave("Sampling findished!", self.slave_id) if sampling_counter == 0: sampling_counter = 1 self.stage_tick_treshold = sampling_ticks / sampling_counter log_slave("sampling_ticks: " + str(sampling_ticks), self.slave_id) log_slave("sampling_counter: " + str(sampling_counter), self.slave_id) log_slave("STAGE_TICK_TRESHOLD: " + str(self.stage_tick_treshold), self.slave_id) if self.stage_tick_treshold == 0.0: self.stage_tick_treshold = 1.0 self.q.set_tick_timeout_treshold(3 * self.stage_tick_treshold * self.timeout_tick_factor) send_msg(KAFL_TAG_REQ_SAMPLING, bitmap, self.comm.to_master_from_slave_queue, source=self.slave_id)