def AFL_choose_block_len(limit): global HAVOC_BLK_SMALL global HAVOC_BLK_MEDIUM global HAVOC_BLK_LARGE global HAVOC_BLK_XL min_value = 1 max_value = 32 # u32 rlim = MIN(queue_cycle, 3); # if (!run_over10m) rlim = 1; rlim = 1 case = rand.int(rlim) if case == 0: min_value = 1 max_value = HAVOC_BLK_SMALL elif case == 1: min_value = HAVOC_BLK_SMALL max_value = HAVOC_BLK_MEDIUM else: case = rand.int(10) if case == 0: min_value = HAVOC_BLK_LARGE max_value = HAVOC_BLK_XL else: min_value = HAVOC_BLK_MEDIUM max_value = HAVOC_BLK_LARGE
def havoc_perform_set_random_byte_value(data): if len(data) < 1: return data pos = rand.int(len(data)) value = data[pos] ^ (1 + rand.int(255)) return b''.join([ data[:pos], value.to_bytes(1, 'little', signed=False), data[pos + 1:] ])
def havoc_perform_byte_addition_32(data): if len(data) < 4: return data order = rand.select(("big", "little")) pos = rand.int(len(data) - 3) value = int.from_bytes(data[pos:pos + 4], order, signed=False) value = (value + 1 + rand.int(AFL_ARITH_MAX)) % 0xffffffff return b''.join( [data[:pos], value.to_bytes(4, order, signed=False), data[pos + 4:]])
def havoc_perform_byte_subtraction_16(data): if len(data) < 2: return data order = rand.select(("big", "little")) pos = rand.int(len(data) - 1) value = int.from_bytes(data[pos:pos + 2], order, signed=False) value = (value - 1 - rand.int(AFL_ARITH_MAX)) % 0xffff return b''.join( [data[:pos], value.to_bytes(2, order, signed=False), data[pos + 2:]])
def havoc_perform_byte_subtraction_8(data): if len(data) < 1: return data pos = rand.int(len(data)) value = int.from_bytes(data[pos:pos + 1], 'little', signed=False) value = (value - 1 - rand.int(AFL_ARITH_MAX)) % 0xff return b''.join([ data[:pos], value.to_bytes(1, 'little', signed=False), data[pos + 1:] ])
def havoc_perform_delete_random_byte(data): if len(data) < 2: return data del_length = AFL_choose_block_len(len(data) - 1) del_from = rand.int(len(data) - del_length + 1) return b''.join([data[:del_from] + data[del_from + del_length:]])
def insert_word(data, chars, term): if len(data) < 2: return data offset = rand.int(len(data)) if rand.int(2) > 1: replen = 0 # plain insert else: replen = rand.int(len(data) - offset) word_length = min(len(data) - offset, rand.int(10) + 1) body = ''.join([term] + [rand.select(chars) for _ in range(word_length - 1)] + [term]) return b''.join([data[:offset], body.encode(), data[offset + replen:]])
def AFL_choose_block_len2(limit): min_value = 1 max_value = 16 if min_value >= limit: min_value = limit return min_value + rand.int(MIN(max_value, limit) - min_value + 1)
def __check_colorization(self, orig_hash, payload_array, min, max): backup = payload_array[min:max] for i in range(min, max): payload_array[i] = rand.int(255) new_hash = self.__get_bitmap_hash(payload_array) if new_hash is not None and new_hash == orig_hash: return True else: payload_array[min:max] = backup return False
def havoc_perform_insert_interesting_value_8(data): if len(data) < 1: return data pos = rand.int(len(data)) value = rand.select(interesting_8_Bit) return b''.join( [data[:pos], value.to_bytes(1, 'little', signed=True), data[pos + 1:]])
def havoc_perform_insert_interesting_value_32(data): if len(data) < 4: return data order = rand.select(("big", "little")) pos = rand.int(len(data) - 3) value = rand.select(interesting_32_Bit) return b''.join( [data[:pos], value.to_bytes(4, order, signed=True), data[pos + 4:]])
def havoc_perform_clone_random_byte(data): data_len = len(data) if data_len < 1 or data_len + HAVOC_BLK_XL >= KAFL_MAX_FILE: return data # clone bytes with p=3/4, else insert block of constant bytes if rand.int(4): clone_len = AFL_choose_block_len(data_len) clone_from = rand.int(data_len - clone_len + 1) body = data[clone_from:clone_from + clone_len] else: clone_len = AFL_choose_block_len(HAVOC_BLK_XL) val = rand.int(256) if rand.int(2) else rand.select(data) body = b''.join([ val.to_bytes(1, 'little', signed=False) for _ in range(clone_len) ]) clone_to = rand.int(data_len) return b''.join([data[:clone_to], body, data[clone_to:]])
def random_generalized(grimoire_inference): rand_generalized = list( grimoire_inference.generalized_inputs.keys())[rand.int( len(grimoire_inference.generalized_inputs))] rand_generalized = pad_generalized_input(rand_generalized) if rand.int(100) > CHOOSE_SUBINPUT and len(rand_generalized) > 0: if rand.int(100) < 50 and len(rand_generalized) > 0: gap_indices = filter_gap_indices(rand_generalized) min_index, max_index = rand.select(gap_indices), rand.select( gap_indices) min_index, max_index = min(min_index, max_index), max(min_index, max_index) rand_generalized = rand_generalized[min_index:max_index + 1] else: random_token = list(grimoire_inference.tokens.keys())[rand.int( len(grimoire_inference.tokens))] rand_generalized = pad_generalized_input(random_token) assert rand_generalized[0] == b'' and rand_generalized[-1] == b'' return rand_generalized
def havoc_perform_bit_flip(data): if len(data) < 1: return data bit = rand.int(len(data) * 8) pos = bit // 8 value = data[pos] ^ (0x80 >> (bit % 8)) return b''.join([ data[:pos], value.to_bytes(1, 'little', signed=False), data[pos + 1:] ])
def mutate_seq_havoc_array(data, func, max_iterations, resize=False): if resize: data = data + data else: data = data stacking = rand.int(AFL_HAVOC_STACK_POW2) stacking = 1 << (stacking) for _ in range(1+max_iterations//stacking): for _ in range(stacking): handler = rand.select(havoc_handler) data = handler(data)[:KAFL_MAX_FILE] func(data)
def havoc_perform_byte_seq_override(data): if len(data) < 2: return data copy_len = AFL_choose_block_len(len(data) - 1) copy_from = rand.int(len(data) - copy_len + 1) copy_to = rand.int(len(data) - copy_len + 1) body = b'' if rand.int(4): if copy_from != copy_to: body = data[copy_from:copy_from + copy_len] else: if rand.int(2): value = rand.int(256) else: value = rand.select(data) body = b''.join( value.to_bytes(1, 'little', signed=False) for _ in range(copy_len)) return b''.join([data[:copy_to], body, data[copy_to + copy_len:]])
def havoc_dict_replace(data): global redqueen_dict global dict_import has_redq = len(redqueen_dict) > 0 has_dict = len(dict_import) > 0 coin = rand.int(2) if not has_dict and has_redq and coin: addr = rand.select(redqueen_addr_list) dict_values = list(redqueen_dict[addr]) dict_entry = rand.select(dict_values) return dict_replace_sequence(data, dict_entry) elif has_dict: dict_entry = rand.select(dict_import) #dict_entry = dict_entry[:len(data)] return dict_replace_sequence(data, dict_entry) return data
def havoc_splicing(data, files): if len(data) < 2 or files is None: return data rand.shuffle(files) retry_limit = 64 for file in files[:retry_limit]: file_data = read_binary_file(file) if len(file_data) < 2: continue first_diff, last_diff = find_diffs(data, file_data) if last_diff < 2 or first_diff == last_diff: continue split_location = first_diff + rand.int(last_diff - first_diff) return data[:split_location] + file_data[split_location:] # none of the files are suitable return None
elif case == 1: min_value = HAVOC_BLK_SMALL max_value = HAVOC_BLK_MEDIUM else: case = rand.int(10) if case == 0: min_value = HAVOC_BLK_LARGE max_value = HAVOC_BLK_XL else: min_value = HAVOC_BLK_MEDIUM max_value = HAVOC_BLK_LARGE if min_value >= limit: min_value = 1; return min_value + rand.int(MIN(max_value, limit) - min_value + 1); # Todo def AFL_choose_block_len2(limit): min_value = 1 max_value = 16 if min_value >= limit: min_value = limit return min_value + rand.int(MIN(max_value, limit) - min_value + 1) def MIN(value_a, value_b): if value_a > value_b:
def dict_replace_sequence(data, entry, entry_pos=None): #logger.debug("HAVOC DICT-REP: %s [%s] -> %s " % (repr(data), repr(entry), repr(newdata))) if entry_pos is None: entry_pos = rand.int(max([0, len(data) - len(entry)])) return b''.join([data[:entry_pos], entry, data[entry_pos:]])