def generate_binary_file(byte_array, seed_file_path, gen_file_path=None): byte_list = [] modified_index_list = [] with open(seed_file_path, "rb") as poc_file: byte = poc_file.read(1) while byte: number = int(struct.unpack('>B', byte)[0]) byte_list.append(number) byte = poc_file.read(1) mask_byte_list = values.MASK_BYTE_LIST[seed_file_path] emitter.data("Masked Byte List", mask_byte_list) for index in byte_array: if index not in mask_byte_list: byte_list[index] = byte_array[index] modified_index_list.append(index) emitter.data("Modified Byte List", modified_index_list) file_extension = "" if "." in seed_file_path: file_extension = str(seed_file_path).split(".")[-1] if not gen_file_path: gen_file_path = definitions.DIRECTORY_OUTPUT + "/input-" + str(values.ITERATION_NO) values.FILE_POC_GEN = gen_file_path if file_extension: values.FILE_POC_GEN = values.FILE_POC_GEN + "." + file_extension with open(values.FILE_POC_GEN, "wb") as new_input_file: new_input_file.write(bytearray(byte_list))
def generate_mask_bytes(klee_out_dir, poc_path): mask_byte_list = list() log_path = klee_out_dir + "/concrete.log" concretized_byte_list = reader.collect_concretized_bytes(log_path) smt2_file_path = klee_out_dir + "/test000001.smt2" control_byte_list = reader.collect_bytes_from_smt2(smt2_file_path) emitter.data("Control Byte List", control_byte_list) fixed_byte_list = list() if "A-data" in concretized_byte_list: influence_byte_list = sorted(list(concretized_byte_list["A-data"])) emitter.data("Influencing Byte List", influence_byte_list) fixed_byte_list = control_byte_list if poc_path: byte_length = os.path.getsize(poc_path) for i in range(0, byte_length): if i not in fixed_byte_list: mask_byte_list.append(i) return sorted(mask_byte_list)
def check_path_feasibility(chosen_control_loc, new_path, index): """ This function will check if a selected path is feasible ppc : partial path conditoin at chosen control loc chosen_control_loc: branch location selected for flip returns satisfiability of the negated path """ result = False if chosen_control_loc != values.CONF_LOC_PATCH: result = not is_unsat(new_path) else: result = is_sat(new_path) if result: return True, index else: emitter.data("Path is not satisfiable at " + str(chosen_control_loc), new_path) return False, index
def generate_constant_value_list(sym_path): gen_const_list = dict() gen_var_list = dict() const_val_list = dict() model = generate_model(sym_path) if model is None: return None for var_name in model: var_byte_list = model[var_name] if "const" in var_name: gen_const_list[var_name] = var_byte_list else: gen_var_list[var_name] = var_byte_list for const_name in gen_const_list: bit_vector = gen_const_list[const_name] const_value = utilities.get_signed_value(bit_vector) print(const_name, const_value) const_val_list[const_name] = const_value emitter.data("Generated Constant List", const_val_list) return const_val_list
def generate_new_input(sym_path, argument_list=None, poc_path=None, gen_path=None): gen_arg_list = dict() gen_var_list = dict() input_var_list = list() input_arg_dict = dict() input_arg_list = list() model = generate_model(sym_path) if model is None: return None, None for var_name in model: var_byte_list = model[var_name] if "arg" in var_name: gen_arg_list[var_name] = var_byte_list else: gen_var_list[var_name] = var_byte_list mask_list = values.CONF_MASK_ARG mask_map = dict() if values.CONF_MASK_ARG: min_val = 0 new_idx = 0 max_val = len(argument_list) for idx in range(min_val, max_val): if str(idx) not in mask_list: mask_map[new_idx] = idx new_idx = new_idx + 1 for arg_name in gen_arg_list: bit_vector = gen_arg_list[arg_name] arg_index = int(str(arg_name).replace("arg", "")) arg_str = utilities.get_str_value(bit_vector) arg_value = utilities.get_signed_value(bit_vector) - 48 arg_index_orig = arg_index if values.CONF_MASK_ARG: arg_index_orig = mask_map[arg_index_orig] # print(arg_name, arg_index, arg_value) if str(argument_list[arg_index_orig]).isnumeric() or \ (not str(argument_list[arg_index_orig]).isalpha() and any(op in str(argument_list[arg_index_orig]) for op in ["+", "-", "/", "*"])): input_arg_dict[arg_index] = str(arg_value) # emitter.debug(arg_name, arg_value) else: arg_str_filtered = str(arg_str).replace("<", "a").replace("&", "s").replace(">", "a").replace("'", "a") input_arg_dict[arg_index] = arg_str_filtered # emitter.debug(arg_name, arg_str) # fill random values if not generated offset = 0 for arg in argument_list: index = list(argument_list).index(arg) - offset if "$POC" in arg: input_arg_list.append(str(argument_list[index])) offset = 1 elif str(index) in values.CONF_MASK_ARG: input_arg_list.append(arg) elif index in input_arg_dict: input_arg_list.append(input_arg_dict[index]) else: arg_len = len(str(argument_list[index])) random_value = "" for j in range(0, arg_len): random_value += chr(random.randint(32, 128)) input_arg_list.append(random_value) for var_name in gen_var_list: bit_vector = gen_var_list[var_name] var_value = 0 var_size = len(bit_vector) if var_name in ["A-data", "A-data-stat"]: if var_name == "A-data": generate_binary_file(bit_vector, poc_path, gen_path) continue if bit_vector: var_value = utilities.get_signed_value(bit_vector) # emitter.debug(var_name, var_value) if "angelic" in var_name: input_var_list.append({"identifier": var_name, "value": var_value, "size": 4}) # input_var_list.append({"identifier": var_name, "value": var_value, "size": 4}) # for var_tuple in second_var_list: # var_name = var_tuple['identifier'] # if var_name not in gen_var_list: # emitter.warning("\t[warning] variable " + var_name + " assigned random value") # var_size = var_tuple['size'] # var_value = 0 # for i in range(1, var_size): # var_value += ((2 << 7) << (int(i) - 1)) * random.randint(0, 255) # input_var_list.append({"identifier": var_name, "value": var_value, "size": var_size}) emitter.data("Generated Arg List", input_arg_list) emitter.data("Generated Var List", input_var_list) return input_arg_list, input_var_list
def generate_model(formula): """ This function will invoke PySMT APIs to solve the provided formula and return the byte list of the model Arguments: formula: smtlib formatted formula """ emitter.debug("extracting z3 model") model = get_model(formula) if model is None: return None path_script = "/tmp/z3_script_model" write_smtlib(formula, path_script) with open(path_script, "r") as script_file: script_lines = script_file.readlines() script = "".join(script_lines) var_list = set(re.findall("\(declare-fun (.+?) \(\)", script)) sym_var_list = dict() for var_name in var_list: # sym_var_list[var_name] = dict() if "const_" in var_name and not "const_arr" in var_name: sym_def = Symbol(var_name, BV32) if sym_def not in model: continue x = model[sym_def] byte_list = dict() default_value = x.bv_signed_value() byte_list[0] = default_value else: sym_def = Symbol(var_name, ArrayType(BV32, BV8)) if sym_def not in model: continue x = model[sym_def].simplify() byte_list = dict() value_array_map = x.array_value_assigned_values_map() default_value = int(str(x.array_value_default()).split("_")[0]) if not value_array_map: byte_list[0] = default_value else: for idx, val in value_array_map.items(): index = int(str(idx).split("_")[0]) value = int(str(val).split("_")[0]) byte_list[index] = value max_index = max(list(byte_list.keys())) if var_name in values.LIST_BIT_LENGTH: array_size = values.LIST_BIT_LENGTH[var_name] - 1 if var_name in ["A-data"]: array_size = max_index else: array_size = max_index + 1 # TODO: this could be wrong calculation if max_index == 0: array_size = 2 if var_name not in ["A-data"]: for i in range(0, array_size): if i not in byte_list: byte_list[i] = default_value if var_name not in ["A-data", "A-data-stat"]: for i in range(array_size - 1, -1, -1): if byte_list[i] == 0: byte_list.pop(i) else: break sym_var_list[var_name] = byte_list emitter.data("model var list", sym_var_list) return sym_var_list