def extract_byte_code(binary_path): emitter.normal("\textracting bytecode") directory_path = "/".join(binary_path.split("/")[:-1]) binary_name = binary_path.split("/")[-1] extract_command = "cd " + directory_path + ";" extract_command += "extract-bc " + binary_name utilities.execute_command(extract_command)
def soft_restore_project(project_path): restore_command = "cd " + project_path + ";" if os.path.exists(project_path + "/.git"): restore_command += "git reset --hard HEAD" elif os.path.exists(project_path + "/.svn"): restore_command += "svn revert -R .; " elif os.path.exists(project_path + "/.hg"): restore_command += "hg update --clean" else: return # print(restore_command) execute_command(restore_command)
def restore_project(project_path): restore_command = "cd " + project_path + ";" if os.path.exists(project_path + "/.git"): restore_command += "git clean -fd; git reset --hard HEAD" elif os.path.exists(project_path + "/.svn"): restore_command += "svn revert -R .; svn status --no-ignore | grep '^\?' | sed 's/^\? //' | xargs rm -rf" elif os.path.exists(project_path + "/.hg"): restore_command += "hg update --clean; hg st -un0 | xargs -0 rm" else: return # print(restore_command) execute_command(restore_command)
def clean_project(project_path, binary_path): emitter.normal("\tcleaning files") binary_dir_path = "/".join(str(binary_path).split("/")[:-1]) if values.CONF_COMMAND_BUILD != "skip": clean_command = "cd " + project_path clean_command += "; make clean" clean_command += "; rm compile_commands.json" clean_command += "; rm CMakeCache.txt" clean_command += "; rm -rf CMakeFiles" execute_command(clean_command) clean_residues = "cd " + binary_dir_path + ";" + "rm -rf ./patches/*;" + "rm -rf ./klee*" execute_command(clean_residues)
def build_project(project_path, build_command=None): emitter.normal("\tbuilding program") dir_command = "cd " + project_path + ";" if build_command is None: build_command = "CC=" + CC + " CXX=" + CXX + " " if values.CONF_BUILD_FLAGS == "disable": build_command += "bear make -j`nproc` " else: build_command += "bear make CFLAGS=\"" + C_FLAGS + "\" " build_command += "CXXFLAGS=\"" + CXX_FLAGS + " LDFLAGS=" + LD_FLAGS + "\" -j`nproc` > " else: if build_command == "skip": emitter.warning("\t[warning] skipping build") return if not os.path.isfile(project_path + "/compile_commands.json"): build_command = build_command.replace("make ", "bear make ") if CC == "wllvm": build_command = remove_fsanitize(build_command) build_command = apply_flags(build_command) if not build_command: error_exit("[Not Found] Build Command") build_command = dir_command + build_command build_command = build_command + " > " + definitions.FILE_MAKE_LOG ret_code = execute_command(build_command) if int(ret_code) != 0: emitter.error(build_command) error_exit("BUILD FAILED!!\nExit Code: " + str(ret_code))
def generate_model_cli(formula): """ This function will invoke the Z3 Cli interface to solve the provided formula and return the model byte list Arguments: formula: smtlib formatted formula """ emitter.normal("\textracting z3 model") path_script = "/tmp/z3_script_model_cli" path_result = "/tmp/z3_output_model_cli" write_smtlib(formula, path_script) with open(path_script, "a") as script_file: script_file.writelines(["(get-model)\n", "(exit)\n"]) z3_command = "z3 " + path_script + " > " + path_result utilities.execute_command(z3_command) with open(path_result, "r") as result_file: z3_output = result_file.readlines() model_byte_list = parser.parse_z3_output(z3_output) return model_byte_list
def run_concrete_execution(program, argument_list, print_output=False, output_dir=None): """ This function will execute the program in concrete mode using the concrete inputs program: the absolute path of the bitcode of the program argument_list : a list containing each argument in the order that should be fed to the program second_var_list: a list of tuples where a tuple is (var identifier, var size, var value) """ logger.info("running concolic execution") emitter.normal("\texecuting klee in concrete mode") global File_Log_Path current_dir = os.getcwd() directory_path = "/".join(str(program).split("/")[:-1]) emitter.debug("changing directory:" + directory_path) os.chdir(directory_path) binary_name = str(program).split("/")[-1] input_argument = "" runtime_lib_path = definitions.DIRECTORY_LIB + "/libtrident_runtime.bca" for argument in argument_list: if "$POC" in argument: argument = values.FILE_POC_GEN # if "_" in argument: # file_index = "_".join(str(argument).split("_")[1:]) # argument = values.LIST_TEST_FILES[file_index] # else: # argument = values.CONF_PATH_POC # if values.FILE_POC_GEN: # argument = values.FILE_POC_GEN input_argument += " " + str(argument) if output_dir: klee_command = "klee --output-dir=" + str(output_dir) + " " else: klee_command = "klee " klee_command += "--posix-runtime " \ "--libc=uclibc " \ "--search=dfs " \ "--write-smt2s " \ "--external-calls=all " \ "--max-forks {0} ".format(values.DEFAULT_MAX_FORK) \ + values.CONF_KLEE_FLAGS + " " \ + "--link-llvm-lib={0} ".format(runtime_lib_path) \ + "{0} ".format(binary_name) \ + input_argument if not print_output: klee_command += " > " + File_Log_Path + " 2>&1 " return_code = utilities.execute_command(klee_command) emitter.debug("changing directory:" + current_dir) os.chdir(current_dir) return return_code
def build_normal(): global CC, CXX, CXX_FLAGS, C_FLAGS, LD_FLAGS emitter.sub_title("Building Program") emitter.normal("\tsetting environment variables") execute_command("export TRIDENT_CC=" + definitions.DIRECTORY_TOOLS + "/trident-cc") execute_command("export TRIDENT_CXX=" + definitions.DIRECTORY_TOOLS + "/trident-cxx") clean_project(values.CONF_DIR_SRC, values.CONF_PATH_PROGRAM) CC = "$TRIDENT_CC" CXX = "$TRIDENT_CXX" C_FLAGS = "-g -O0" CXX_FLAGS = "-g -O0" config_project(values.CONF_DIR_SRC, False, values.CONF_COMMAND_CONFIG) C_FLAGS = "" LD_FLAGS = "" CXX_FLAGS = C_FLAGS if values.CONF_STATIC: C_FLAGS += " -static" CXX_FLAGS += " -static" build_project(values.CONF_DIR_SRC, values.CONF_COMMAND_BUILD)
def generate_ktest(argument_list, second_var_list, print_output=False): """ This function will generate the ktest file provided the argument list and second order variable list argument_list : a list containing each argument in the order that should be fed to the program second_var_list: a list of tuples where a tuple is (var identifier, var size, var value) """ global File_Ktest_Path emitter.normal("\tgenerating ktest file") ktest_path = File_Ktest_Path ktest_command = "gen-bout --out-file {0}".format(ktest_path) for argument in argument_list: index = list(argument_list).index(argument) if "$POC" in argument: binary_file_path = values.FILE_POC_GEN # if "_" in argument: # file_index = "_".join(str(argument).split("_")[1:]) # binary_file_path = values.LIST_TEST_FILES[file_index] # else: # binary_file_path = values.CONF_PATH_POC # if values.FILE_POC_GEN: # binary_file_path = values.FILE_POC_GEN # elif values.FILE_POC_SEED: # binary_file_path = values.FILE_POC_SEED ktest_command += " --sym-file " + binary_file_path elif str(index) in values.CONF_MASK_ARG: continue else: if argument in ["''"]: argument = "" if "\"" in argument: ktest_command += " --sym-arg '" + str(argument) + "'" continue ktest_command += " --sym-arg \"" + str(argument) + "\"" for var in second_var_list: ktest_command += " --second-var \'{0}\' {1} {2}".format( var['identifier'], var['size'], var['value']) return_code = utilities.execute_command(ktest_command) return ktest_path, return_code
def run_concolic_execution(program, argument_list, second_var_list, print_output=False, klee_out_dir=None): """ This function will execute the program in concolic mode using the generated ktest file program: the absolute path of the bitcode of the program argument_list : a list containing each argument in the order that should be fed to the program second_var_list: a list of tuples where a tuple is (var identifier, var size, var value) """ logger.info("running concolic execution") global File_Log_Path current_dir = os.getcwd() directory_path = "/".join(str(program).split("/")[:-1]) emitter.debug("changing directory:" + directory_path) project_path = values.CONF_DIR_SRC os.chdir(directory_path) binary_name = str(program).split("/")[-1] input_argument = "" # argument_list = str(argument_str).split(" ") for argument in argument_list: index = list(argument_list).index(argument) if "$POC" in argument: file_path = values.FILE_POC_GEN # if "_" in argument: # file_index = "_".join(str(argument).split("_")[1:]) # file_path = values.LIST_TEST_FILES[file_index] # else: # file_path = values.CONF_PATH_POC # if values.FILE_POC_GEN: # file_path = values.FILE_POC_GEN # elif values.FILE_POC_SEED: # file_path = values.FILE_POC_SEED concrete_file = open(file_path, 'rb') bit_size = os.fstat(concrete_file.fileno()).st_size input_argument += " A --sym-files 1 " + str(bit_size) + " " elif str(index) in values.CONF_MASK_ARG: input_argument += " " + argument else: input_argument += " --sym-arg " + str(len(str(argument))) ktest_path, return_code = generator.generate_ktest(argument_list, second_var_list) ktest_log_file = "/tmp/ktest.log" ktest_command = "ktest-tool " + ktest_path + " > " + ktest_log_file utilities.execute_command(ktest_command) bit_length_list = reader.read_bit_length(ktest_log_file) if values.LIST_BIT_LENGTH: for var in bit_length_list: if var in values.LIST_BIT_LENGTH: if values.LIST_BIT_LENGTH[var] < bit_length_list[var]: values.LIST_BIT_LENGTH[var] = bit_length_list[var] else: values.LIST_BIT_LENGTH[var] = bit_length_list[var] else: values.LIST_BIT_LENGTH = bit_length_list emitter.normal("\texecuting klee in concolic mode") # hit_location_flag = " " runtime_lib_path = definitions.DIRECTORY_LIB + "/libtrident_runtime.bca" # if values.CONF_DISTANCE_METRIC == "control-loc": hit_location_flag = "--hit-locations " + values.CONF_LOC_BUG + "," + values.CONF_LOC_PATCH if values.CONF_LOC_LIST_CRASH: crash_locations = ', '.join( ['{}'.format(loc) for loc in values.CONF_LOC_LIST_CRASH]) hit_location_flag += "," + crash_locations + " " else: hit_location_flag += " " ppc_log_flag = "" if values.DEFAULT_DISTANCE_METRIC != values.OPTIONS_DIST_METRIC[2]: ppc_log_flag = "--log-ppc " klee_command = "timeout " + str(values.DEFAULT_TIMEOUT_KLEE_CONCOLIC) + " " if klee_out_dir: klee_command += "klee --output-dir=" + str(klee_out_dir) + " " values.KLEE_LAST_DIR = klee_out_dir else: klee_command += "klee " klee_command += "--posix-runtime " \ "--libc=uclibc " \ "--write-smt2s " \ "-allow-seed-extension " \ "-named-seed-matching " \ "--log-trace " \ + "--external-calls=all " \ + "--link-llvm-lib={0} " .format(runtime_lib_path) \ + "--max-time={0} ".format(values.DEFAULT_TIMEOUT_KLEE_CONCOLIC) \ + "{0}".format(ppc_log_flag) \ + "{0}".format(hit_location_flag) \ + "--max-forks {0} ".format(values.DEFAULT_MAX_FORK) \ + values.CONF_KLEE_FLAGS + " " \ + "--seed-out={0} ".format(ktest_path) \ + "{0} ".format(binary_name) \ + input_argument if not print_output: klee_command += " > " + File_Log_Path + " 2>&1 " return_code = utilities.execute_command(klee_command) emitter.debug("changing directory:" + current_dir) os.chdir(current_dir) # collect artifacts ppc_log_path = klee_out_dir + "/ppc.log" trace_log_path = klee_out_dir + "/trace.log" if values.DEFAULT_DISTANCE_METRIC != values.OPTIONS_DIST_METRIC[2]: ppc_list, path_formula = reader.collect_symbolic_path( ppc_log_path, project_path) values.LIST_PPC = values.LIST_PPC = ppc_list values.LAST_PPC_FORMULA = path_formula values.PREFIX_PPC_STR = reader.collect_symbolic_path_prefix( ppc_log_path, project_path) else: values.LAST_PPC_FORMULA = extractor.extract_largest_path_condition( klee_out_dir) if values.LAST_PPC_FORMULA: ppc_list = generator.generate_ppc_from_formula( values.LAST_PPC_FORMULA) values.LIST_PPC = values.LIST_PPC + ppc_list # else: # values.LIST_PPC = [] values.PREFIX_PPC_FORMULA = generator.generate_formula( values.PREFIX_PPC_STR) values.LIST_TRACE = reader.collect_trace(trace_log_path, project_path) if oracle.is_loc_in_trace(values.CONF_LOC_BUG) and oracle.is_loc_in_trace( values.CONF_LOC_PATCH): if values.DEFAULT_DISTANCE_METRIC != values.OPTIONS_DIST_METRIC[2]: values.NEGATED_PPC_FORMULA = generator.generate_path_for_negation() else: if values.LAST_PPC_FORMULA: values.NEGATED_PPC_FORMULA = generator.generate_negated_path( values.LAST_PPC_FORMULA) else: values.NEGATED_PPC_FORMULA = None return return_code
def config_project(project_path, is_llvm, custom_config_command=None): emitter.normal("\tconfiguring program") dir_command = "cd " + project_path + ";" config_command = None if custom_config_command is not None: if custom_config_command == "skip": emitter.warning("\t[warning] skipping configuration") return else: if os.path.exists(project_path + "/" + "aclocal.m4"): pre_config_command = "rm aclocal.m4;aclocal" execute_command(pre_config_command) if CC == "wllvm": custom_config_command = remove_fsanitize(custom_config_command) if "cmake" in custom_config_command: custom_config_command = custom_config_command.replace( "clang", "wllvm") custom_config_command = custom_config_command.replace( "clang++", "wllvm++") # print(custom_config_command) # config_command = "CC=" + CC + " " # config_command += "CXX=" + CXX + " " config_command = custom_config_command if "--cc=" in config_command: config_command = config_command.replace( "--cc=clang-7", "--cc=" + CC) # print(config_command) elif os.path.exists(project_path + "/autogen.sh"): config_command = "./autogen.sh;" config_command += "CC=" + CC + " " config_command += "CXX=" + CXX + " " config_command += "./configure " config_command += "CFLAGS=\"" + C_FLAGS + "\" " config_command += "CXXFLAGS=\"" + CXX_FLAGS + "\"" elif os.path.exists(project_path + "/configure.ac"): config_command = "autoreconf -i;" config_command += "CC=" + CC + " " config_command += "CXX=" + CXX + " " config_command += "./configure " config_command += "CFLAGS=\"" + C_FLAGS + "\" " config_command += "CXXFLAGS=\"" + CXX_FLAGS + "\"" elif os.path.exists(project_path + "/configure.in"): config_command = "autoreconf -i;" config_command += "CC=" + CC + " " config_command += "CXX=" + CXX + " " config_command += "./configure " config_command += "CFLAGS=\"" + C_FLAGS + "\" " config_command += "CXXFLAGS=\"" + CXX_FLAGS + "\"" elif os.path.exists(project_path + "/configure"): config_command = "CC=" + CC + " " config_command += "CXX=" + CXX + " " config_command += "./configure " config_command += "CFLAGS=\"" + C_FLAGS + "\" " config_command += "CXXFLAGS=\"" + CXX_FLAGS + "\"" elif os.path.exists(project_path + "/CMakeLists.txt"): config_command = "cmake -DCMAKE_C_COMPILER=" + CC + " " config_command += "-DCMAKE_CPP_COMPILER=" + CXX + " " config_command += "-DCMAKE_C_FLAGS=\"" + C_FLAGS + "\" " config_command += "-DCMAKE_CXX_FLAGS=\"" + CXX_FLAGS + "\" . " if is_llvm: config_command = "LLVM_COMPILER=clang;" + config_command if not config_command: error_exit("[Not Found] Configuration Command") config_command = dir_command + config_command ret_code = execute_command(config_command) if int(ret_code) != 0: emitter.error(config_command) error_exit("CONFIGURATION FAILED!!\nExit Code: " + str(ret_code))