Ejemplo n.º 1
0
 def __init__(self, vivisect_workspace):
     viv_utils.LoggingObject.__init__(self)
     self.vivisect_workspace = vivisect_workspace
     self.emu = makeEmulator(vivisect_workspace)
     self.driver = viv_utils.emulator_drivers.FunctionRunnerEmulatorDriver(
         self.emu)
     self.index = viv_utils.InstructionFunctionIndex(vivisect_workspace)
Ejemplo n.º 2
0
def decode_strings(vw,
                   decoding_functions_candidates,
                   min_length,
                   no_filter=False):
    """
    FLOSS string decoding algorithm
    :param vw: vivisect workspace
    :param decoding_functions_candidates: identification manager
    :param min_length: minimum string length
    :param no_filter: do not filter decoded strings
    :return: list of decoded strings ([DecodedString])
    """
    decoded_strings = []
    function_index = viv_utils.InstructionFunctionIndex(vw)
    # TODO pass function list instead of identification manager
    for fva, _ in decoding_functions_candidates.get_top_candidate_functions(
            10):
        for ctx in string_decoder.extract_decoding_contexts(vw, fva):
            for delta in string_decoder.emulate_decoding_routine(
                    vw, function_index, fva, ctx):
                for delta_bytes in string_decoder.extract_delta_bytes(
                        delta, ctx.decoded_at_va, fva):
                    for decoded_string in string_decoder.extract_strings(
                            delta_bytes, min_length, no_filter):
                        decoded_strings.append(decoded_string)
    return decoded_strings
Ejemplo n.º 3
0
def main():
    # default to INFO, unless otherwise changed
    logging.basicConfig(level=logging.WARNING)

    parser = make_parser()
    options, args = parser.parse_args()

    set_logging_level(options.debug, options.verbose)

    if options.list_plugins:
        print_plugin_list()
        sys.exit(0)

    sample_file_path = parse_sample_file_path(parser, args)
    min_length = parse_min_length_option(options.min_length)

    if options.all_strings:
        floss_logger.info("Extracting static strings...")
        print_all_strings(sample_file_path, min_length=min_length, quiet=options.quiet)

    with open(sample_file_path, "rb") as f:
        magic = f.read(2)
    if magic != "MZ":
        floss_logger.error("FLOSS currently supports the following formats: PE")
        return

    floss_logger.info("Generating vivisect workspace")
    vw = viv_utils.getWorkspace(sample_file_path)

    selected_functions = select_functions(vw, options.functions)
    floss_logger.debug("Selected the following functions: %s", ", ".join(map(hex, selected_functions)))

    selected_plugin_names = select_plugins(options.plugins)
    floss_logger.debug("Selected the following plugins: %s", ", ".join(map(str, selected_plugin_names)))
    selected_plugins = filter(lambda p: str(p) in selected_plugin_names, get_all_plugins())

    time0 = time()

    floss_logger.info("Identifying decoding functions...")
    decoding_functions_candidates = im.identify_decoding_functions(vw, selected_plugins, selected_functions)
    if not options.quiet:
        print_identification_results(sample_file_path, decoding_functions_candidates)

    floss_logger.info("Decoding strings...")
    function_index = viv_utils.InstructionFunctionIndex(vw)
    decoded_strings = decode_strings(vw, function_index, decoding_functions_candidates)
    print_decoding_results(decoded_strings, min_length, options.group_functions, quiet=options.quiet)

    floss_logger.info("Extracting stackstrings...")
    print_stack_strings(stackstrings.extract_stackstrings(vw, selected_functions), min_length, quiet=options.quiet)

    if options.ida_python_file:
        floss_logger.info("Creating IDA script...")
        create_script(sample_file_path, options.ida_python_file, decoded_strings)


    time1 = time()
    if not options.quiet:
        print("Finished execution after %f seconds" % (time1 - time0))
Ejemplo n.º 4
0
    def __init__(self, sample_file_path):
        viv_utils.LoggingObject.__init__(self)
        self.vivisect_workspace = viv_utils.getWorkspace(sample_file_path)

        self.function_index = viv_utils.InstructionFunctionIndex(
            self.vivisect_workspace)
        # TODO do we need a set for the decoded strings?
        self.decoded_strings = set([])
Ejemplo n.º 5
0
def extract_strings(sample_path):
    """
    Deobfuscate strings from sample_path
    """
    vw = viv_utils.getWorkspace(sample_path)
    function_index = viv_utils.InstructionFunctionIndex(vw)
    decoding_functions_candidates = identify_decoding_functions(vw)
    decoded_strings = floss_main.decode_strings(vw, function_index, decoding_functions_candidates)
    selected_functions = floss_main.select_functions(vw, None)
    decoded_stackstrings = stackstrings.extract_stackstrings(vw, selected_functions)
    decoded_strings.extend(decoded_stackstrings)
    return [ds.s for ds in decoded_strings]
Ejemplo n.º 6
0
def search():
    """
    Attempts to find potential device names in the currently opened binary, it starts by searching for unicode device names,
    if this fails then it utilises FLOSS to search for stack based and obsfucated strings.
    """

    if not find_unicode_device_name():
        print "Unicode device name not found, attempting to find obsfucated and stack based strings."
        try:
            import floss
            import floss.identification_manager
            import floss.main
            import floss.stackstrings
            import viv_utils
        except:
            print "Please install FLOSS to continue, see: https://github.com/fireeye/flare-floss/"

        sample_file_path = idc.GetInputFile()

        try:
            vw = viv_utils.getWorkspace(sample_file_path, should_save=False)
        except Exception, e:
            print("Vivisect failed to load the input file: {0}".format(
                e.message))
            return

        functions = set(vw.getFunctions())
        plugins = floss.main.get_all_plugins()
        device_names = set()

        stack_strings = floss.stackstrings.extract_stackstrings(vw, functions)
        for i in stack_strings:
            device_names.add(i)
        dec_func_candidates = floss.identification_manager.identify_decoding_functions(
            vw, plugins, functions)
        func_index = viv_utils.InstructionFunctionIndex(vw)
        decoded_strings = floss.main.decode_strings(vw, func_index,
                                                    dec_func_candidates)
        if len(decoded_strings) > 0:
            for i in decoded_strings:
                device_names.add(str(i.s))
            print "Potential device names from obsfucated or stack strings:"
            for i in device_names:
                print i
        else:
            print "No obsfucated or stack strings found :("
Ejemplo n.º 7
0
def _main(bin_path, ofva):
    fva = int(ofva, 0x10)
    logging.basicConfig(level=logging.DEBUG)

    vw = viv_utils.getWorkspace(bin_path)

    index = viv_utils.InstructionFunctionIndex(vw)

    # optimization: avoid re-processing the same function repeatedly
    called_fvas = set([])
    for callerva in vw.getCallers(fva):
        callerfva = index[
            callerva]  # the address of the function that contains this instruction
        if callerfva in called_fvas:
            continue

        emulate_function(vw, index[callerva], fva)

        called_fvas.add(callerfva)

    return
Ejemplo n.º 8
0
    def floss_decode_strings(self,
                             vw,
                             decoders,
                             min_length=4,
                             no_filter=False,
                             max_insn=2000,
                             max_hits=1):
        decoded_strings = []
        function_index = viv_utils.InstructionFunctionIndex(vw)

        for fva in decoders:
            for ctx in floss.string_decoder.extract_decoding_contexts(
                    vw, fva, max_hits):
                for delta in floss.string_decoder.emulate_decoding_routine(
                        vw, function_index, fva, ctx, max_insn):
                    for delta_bytes in floss.string_decoder.extract_delta_bytes(
                            delta, ctx.decoded_at_va, fva):
                        for decoded_string in floss.string_decoder.extract_strings(
                                delta_bytes, min_length, no_filter):
                            decoded_strings.append(decoded_string)

        return decoded_strings
Ejemplo n.º 9
0
                       ", ".join(map(str, selected_plugin_names)))
    selected_plugins = filter(lambda p: str(p) in selected_plugin_names,
                              get_all_plugins())

    time0 = time()

    if not options.no_decoded_strings:
        floss_logger.info("Identifying decoding functions...")
        decoding_functions_candidates = im.identify_decoding_functions(
            vw, selected_plugins, selected_functions)
        if options.expert:
            print_identification_results(sample_file_path,
                                         decoding_functions_candidates)

        floss_logger.info("Decoding strings...")
        function_index = viv_utils.InstructionFunctionIndex(vw)
        decoded_strings = decode_strings(vw, function_index,
                                         decoding_functions_candidates)
        if not options.expert:
            decoded_strings = filter_unique_decoded(decoded_strings)
        print_decoding_results(decoded_strings,
                               min_length,
                               options.group_functions,
                               quiet=options.quiet,
                               expert=options.expert)
    else:
        decoded_strings = []

    if not options.no_stack_strings:
        floss_logger.info("Extracting stackstrings...")
        stack_strings = stackstrings.extract_stackstrings(
Ejemplo n.º 10
0
def decode_strings(
    vw: VivWorkspace,
    functions: List[int],
    min_length: int,
    max_insn_count: int = DS_MAX_INSN_COUNT,
    max_hits: int = DS_MAX_ADDRESS_REVISITS_CTX_EXTRACTION,
    verbosity: int = floss.render.default.Verbosity.DEFAULT,
    disable_progress: bool = False,
) -> List[DecodedString]:
    """
    FLOSS string decoding algorithm

    arguments:
        vw: the workspace
        functions: addresses of the candidate decoding routines
        min_length: minimum string length
        max_insn_count: max number of instructions to emulate per function
        max_hits: max number of emulations per instruction
        verbosity: verbosity level
        disable_progress: no progress bar
    """
    logger.info("decoding strings")

    decoded_strings = list()
    function_index = viv_utils.InstructionFunctionIndex(vw)

    pb = floss.utils.get_progress_bar(functions,
                                      disable_progress,
                                      desc="decoding strings",
                                      unit=" functions")
    with tqdm.contrib.logging.logging_redirect_tqdm(
    ), floss.utils.redirecting_print_to_tqdm():
        for fva in pb:
            seen: Set[str] = set()
            ctxs = extract_decoding_contexts(vw, fva, function_index)
            n_calls = len(ctxs)
            for n, ctx in enumerate(ctxs, 1):
                if isinstance(pb, tqdm.tqdm):
                    pb.set_description(
                        f"emulating function 0x{fva:x} (call {n}/{n_calls})")

                if should_shortcut(fva, n, n_calls, len(seen)):
                    break

                for delta in emulate_decoding_routine(vw, function_index, fva,
                                                      ctx, max_insn_count):
                    for delta_bytes in extract_delta_bytes(
                            delta, ctx.decoded_at_va, fva):
                        for s in floss.utils.extract_strings(
                                delta_bytes.bytes, min_length, seen):
                            ds = DecodedString(
                                delta_bytes.address + s.offset,
                                delta_bytes.address_type,
                                s.string,
                                s.encoding,
                                delta_bytes.decoded_at,
                                delta_bytes.decoding_routine,
                            )
                            floss.results.log_result(ds, verbosity)
                            seen.add(ds.string)
                            decoded_strings.append(ds)
        return decoded_strings
Ejemplo n.º 11
0
def main(argv=None):
    """
    :param argv: optional command line arguments, like sys.argv[1:]
    :return: 0 on success, non-zero on failure
    """
    logging.basicConfig(level=logging.WARNING)

    parser = make_parser()
    if argv is not None:
        options, args = parser.parse_args(argv[1:])
    else:
        options, args = parser.parse_args()

    set_logging_level(options.debug, options.verbose)

    if options.list_plugins:
        print_plugin_list()
        return 0

    sample_file_path = parse_sample_file_path(parser, args)
    min_length = parse_min_length_option(options.min_length)

    # expert profile settings
    if options.expert:
        options.save_workspace = True
        options.group_functions = True
        options.quiet = False

    if not is_workspace_file(sample_file_path):
        if not options.no_static_strings and not options.functions:
            floss_logger.info("Extracting static strings...")
            print_static_strings(sample_file_path, min_length=min_length, quiet=options.quiet)

        if options.no_decoded_strings and options.no_stack_strings and not options.should_show_metainfo:
            # we are done
            return 0

    if os.path.getsize(sample_file_path) > MAX_FILE_SIZE:
        floss_logger.error("FLOSS cannot extract obfuscated strings or stackstrings from files larger than"
                           " %d bytes" % MAX_FILE_SIZE)
        return 1

    try:
        vw = load_vw(sample_file_path, options.save_workspace, options.verbose, options.is_shellcode,
                     options.shellcode_entry_point, options.shellcode_base)
    except WorkspaceLoadError:
        return 1

    try:
        selected_functions = select_functions(vw, options.functions)
    except Exception as e:
        floss_logger.error(str(e))
        return 1

    floss_logger.debug("Selected the following functions: %s", get_str_from_func_list(selected_functions))

    selected_plugin_names = select_plugins(options.plugins)
    floss_logger.debug("Selected the following plugins: %s", ", ".join(map(str, selected_plugin_names)))
    selected_plugins = filter(lambda p: str(p) in selected_plugin_names, get_all_plugins())

    if options.should_show_metainfo:
        meta_functions = None
        if options.functions:
            meta_functions = selected_functions
        print_file_meta_info(vw, meta_functions)

    time0 = time()

    if not options.no_decoded_strings:
        floss_logger.info("Identifying decoding functions...")
        decoding_functions_candidates = im.identify_decoding_functions(vw, selected_plugins, selected_functions)
        if options.expert:
            print_identification_results(sample_file_path, decoding_functions_candidates)

        floss_logger.info("Decoding strings...")
        function_index = viv_utils.InstructionFunctionIndex(vw)
        decoded_strings = decode_strings(vw, function_index, decoding_functions_candidates)
        if not options.expert:
            decoded_strings = filter_unique_decoded(decoded_strings)
        print_decoding_results(decoded_strings, min_length, options.group_functions, quiet=options.quiet, expert=options.expert)
    else:
        decoded_strings = []

    if not options.no_stack_strings:
        floss_logger.info("Extracting stackstrings...")
        stack_strings = stackstrings.extract_stackstrings(vw, selected_functions)
        if not options.expert:
            stack_strings = list(set(stack_strings))
        print_stack_strings(stack_strings, min_length, quiet=options.quiet, expert=options.expert)
    else:
        stack_strings = []

    if options.x64dbg_database_file:
        imagebase = vw.filemeta.values()[0]['imagebase']
        floss_logger.info("Creating x64dbg database...")
        create_x64dbg_database(sample_file_path, options.x64dbg_database_file, imagebase, decoded_strings)

    if options.ida_python_file:
        floss_logger.info("Creating IDA script...")
        create_ida_script(sample_file_path, options.ida_python_file, decoded_strings, stack_strings)

    if options.radare2_script_file:
        floss_logger.info("Creating r2script...")
        create_r2_script(sample_file_path, options.radare2_script_file, decoded_strings, stack_strings)

    time1 = time()
    if not options.quiet:
        print("\nFinished execution after %f seconds" % (time1 - time0))

    return 0