Exemple #1
0
def get_workspace(path, format):
    import viv_utils

    logger.debug("generating vivisect workspace for: %s", path)
    if format == "auto":
        if not is_supported_file_type(path):
            raise UnsupportedFormatError()
        vw = viv_utils.getWorkspace(path)
    elif format == "pe":
        vw = viv_utils.getWorkspace(path)
    elif format == "sc32":
        vw = get_shellcode_vw(path, arch="i386")
    elif format == "sc64":
        vw = get_shellcode_vw(path, arch="amd64")
    logger.debug("%s", get_meta_str(vw))
    return vw
Exemple #2
0
    def configure(self):
        parser = self.get_OptionParser()
        (self.options, self.args) = parser.parse_args()

        self.set_logging_level()

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

        TRY_HELP_MSG = "Try '%s -h' for more information" % parser.get_prog_name(
        )

        # TODO handle multiple files?
        if len(self.args) != 1:
            parser.error("Please provide a valid file path\n%s" % TRY_HELP_MSG)

        self.sample_file_path = self.args[0]
        # TODO handle directories?
        if not os.path.isfile(self.sample_file_path):
            parser.error("'%s' is not a file\n%s" %
                         (self.sample_file_path, TRY_HELP_MSG))
        if not os.path.exists(self.sample_file_path):
            parser.error("File '%s' does not exist\n%s" %
                         (self.sample_file_path, TRY_HELP_MSG))

        self.vivisect_workspace = viv_utils.getWorkspace(self.sample_file_path)

        self.functions_to_analyze = self.select_functions()

        self.selected_plugins = self.select_plugins()
Exemple #3
0
def sample_39c05b15e9834ac93f206bc114d0a00c357c888db567ba8f5345da0529cbed41():
    path = os.path.join(
        CD,
        "data",
        "39c05b15e9834ac93f206bc114d0a00c357c888db567ba8f5345da0529cbed41.dll_",
    )
    return Sample(viv_utils.getWorkspace(path), path)
Exemple #4
0
    def configure(self):
        parser = self.get_OptionParser()
        (self.options, self.args) = parser.parse_args()

        self.set_logging_level()

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

        TRY_HELP_MSG = "Try '%s -h' for more information" % parser.get_prog_name()

        # TODO handle multiple files?
        if len(self.args) != 1:
            parser.error("Please provide a valid file path\n%s" % TRY_HELP_MSG)

        self.sample_file_path = self.args[0]
        # TODO handle directories?
        if not os.path.isfile(self.sample_file_path):
            parser.error("'%s' is not a file\n%s" % (self.sample_file_path, TRY_HELP_MSG))
        if not os.path.exists(self.sample_file_path):
            parser.error("File '%s' does not exist\n%s" % (self.sample_file_path, TRY_HELP_MSG))

        self.vivisect_workspace = viv_utils.getWorkspace(self.sample_file_path)

        self.functions_to_analyze = self.select_functions()

        self.selected_plugins = self.select_plugins()
Exemple #5
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))
Exemple #6
0
def get_workspace(path, format, sigpaths):
    """
    load the program at the given path into a vivisect workspace using the given format.
    also apply the given FLIRT signatures.

    supported formats:
      - pe
      - elf
      - shellcode 32-bit
      - shellcode 64-bit
      - auto

    this creates and analyzes the workspace; however, it does *not* save the workspace.
    this is the responsibility of the caller.
    """

    # lazy import enables us to not require viv if user wants SMDA, for example.
    import viv_utils

    logger.debug("generating vivisect workspace for: %s", path)
    if format == "auto":
        if not is_supported_format(path):
            raise UnsupportedFormatError()

        # don't analyze, so that we can add our Flirt function analyzer first.
        vw = viv_utils.getWorkspace(path, analyze=False, should_save=False)
    elif format in {"pe", "elf"}:
        vw = viv_utils.getWorkspace(path, analyze=False, should_save=False)
    elif format == "sc32":
        # these are not analyzed nor saved.
        vw = viv_utils.getShellcodeWorkspaceFromFile(path,
                                                     arch="i386",
                                                     analyze=False)
    elif format == "sc64":
        vw = viv_utils.getShellcodeWorkspaceFromFile(path,
                                                     arch="amd64",
                                                     analyze=False)
    else:
        raise ValueError("unexpected format: " + format)

    viv_utils.flirt.register_flirt_signature_analyzers(vw, sigpaths)

    vw.analyze()

    logger.debug("%s", get_meta_str(vw))
    return vw
    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([])
Exemple #8
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 obfuscated strings.
    """

    if not find_unicode_device_name():
        print(
            "Unicode device name not found, attempting to find obfuscated and stack based strings."
        )
        try:
            import floss
            import floss.identification_manager
            import floss.main
            import floss.stackstrings
            import viv_utils
        except ImportError:
            print(
                "Please install FLOSS to continue, see: https://github.com/fireeye/flare-floss/"
            )
            return
        logging.basicConfig(
        )  #To avoid logger handler not found errors, from https://github.com/fireeye/flare-floss/blob/66f67a49a38ae028a5e86f1de743c384d5271901/scripts/idaplugin.py#L154
        logging.getLogger('vtrace.platforms.win32').setLevel(logging.ERROR)
        sample_file_path = idc.GetInputFile()

        try:
            vw = viv_utils.getWorkspace(sample_file_path, should_save=False)
        except Exception as 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,
                                                                4,
                                                                no_filter=True)
        for i in stack_strings:
            device_names.add(i)
        dec_func_candidates = floss.identification_manager.identify_decoding_functions(
            vw, plugins, functions)
        decoded_strings = floss.main.decode_strings(vw,
                                                    dec_func_candidates,
                                                    4,
                                                    no_filter=True)
        if len(decoded_strings) > 0:
            for i in decoded_strings:
                device_names.add(str(i.s))
            print("Potential device names from obfuscated or stack strings:")
            for i in device_names:
                print(i)
        else:
            print("No obfuscated or stack strings found :(")
Exemple #9
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)

    if not is_workspace_file(sample_file_path):
        with open(sample_file_path, "rb") as f:
            magic = f.read(2)

        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:
            # we are done
            return 0

        if magic not in SUPPORTED_FILE_MAGIC:
            floss_logger.error("FLOSS currently supports the following formats for string decoding and stackstrings: PE")
            return 1

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

        floss_logger.info("Generating vivisect workspace...")
    else:
        floss_logger.info("Loading existing vivisect workspace...")

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

    try:
        vw = viv_utils.getWorkspace(sample_file_path, should_save=options.save_workspace)
    except Exception, e:
        floss_logger.error("Vivisect failed to load the input file: {0}".format(e.message), exc_info=options.verbose)
        return 1
Exemple #10
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)

    if not is_workspace_file(sample_file_path):
        with open(sample_file_path, "rb") as f:
            magic = f.read(2)

        if not options.no_static_strings:
            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:
            # we are done
            return 0

        if magic not in SUPPORTED_FILE_MAGIC:
            floss_logger.error("FLOSS currently supports the following formats for string decoding and stackstrings: PE")
            return 1

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

        floss_logger.info("Generating vivisect workspace...")
    else:
        floss_logger.info("Loading existing vivisect workspace...")

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

    try:
        vw = viv_utils.getWorkspace(sample_file_path, should_save=options.save_workspace)
    except Exception, e:
        floss_logger.error("Vivisect failed to load the input file: {0}".format(e.message), exc_info=options.verbose)
        return 1
Exemple #11
0
def get_workspace(path, format, should_save=True):
    import viv_utils

    logger.debug("generating vivisect workspace for: %s", path)
    if format == "auto":
        if not is_supported_file_type(path):
            raise UnsupportedFormatError()
        vw = viv_utils.getWorkspace(path, should_save=should_save)
    elif format == "pe":
        vw = viv_utils.getWorkspace(path, should_save=should_save)
    elif format == "sc32":
        vw = get_shellcode_vw(path, arch="i386", should_save=should_save)
    elif format == "sc64":
        vw = get_shellcode_vw(path, arch="amd64", should_save=should_save)
    else:
        raise ValueError("unexpected format: " + format)
    logger.debug("%s", get_meta_str(vw))
    return vw
def test_select_all_functions(samples_path):
    file_path = os.path.join(samples_path, "6ee35da59f92f71e757d4d5b964ecf00")
    vivisect_workspace = viv_utils.getWorkspace(file_path)

    sys.argv = [sys.argv[0], file_path]
    sdc = floss_main.StringDecoderConfig()
    sdc.configure()

    assert cmp(vivisect_workspace.getFunctions(), sdc.select_functions()) == 0
Exemple #13
0
def load_workspace(sample_file_path, save_workspace):
    if is_workspace_file(sample_file_path):
        floss_logger.info("Loading existing vivisect workspace...")
    else:
        if not is_supported_file_type(sample_file_path):
            raise LoadNotSupportedError("FLOSS currently supports the following formats for string decoding and "
                                        "stackstrings: PE\nYou can analyze shellcode using the -s switch. See the "
                                        "help (-h) for more information.")
        floss_logger.info("Generating vivisect workspace...")
    return viv_utils.getWorkspace(sample_file_path, should_save=save_workspace)
def test_FAG_get_caller_vas(samples_path):
    file_path = os.path.join(samples_path, "6ee35da59f92f71e757d4d5b964ecf00.viv")
    vivisect_workspace = viv_utils.getWorkspace(file_path)
    f*g = FunctionArgumentGetter(vivisect_workspace)

    caller_vas = f*g.get_caller_vas(0x40166C)

    answer = set([0x401698, 0x4018AD, 0x401CE0])

    assert answer.issubset(caller_vas) and caller_vas.issubset(answer)
def test_FAG_get_caller_vas(samples_path):
    file_path = os.path.join(samples_path,
                             "6ee35da59f92f71e757d4d5b964ecf00.viv")
    vivisect_workspace = viv_utils.getWorkspace(file_path)
    f*g = FunctionArgumentGetter(vivisect_workspace)

    caller_vas = f*g.get_caller_vas(0x40166C)

    answer = set([0x401698, 0x4018AD, 0x401CE0])

    assert answer.issubset(caller_vas) and caller_vas.issubset(answer)
Exemple #16
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)
    decoded_stackstrings = stackstrings.extract_stackstrings(vw)
    decoded_strings.extend(decoded_stackstrings)
    return [ds.s for ds in decoded_strings]
Exemple #17
0
def load_workspace(sample_file_path, save_workspace):
    # inform user that getWorkspace implicitly loads saved workspace if .viv file exists
    if is_workspace_file(sample_file_path) or os.path.exists("%s.viv" % sample_file_path):
        floss_logger.info("Loading existing vivisect workspace...")
    else:
        if not is_supported_file_type(sample_file_path):
            raise LoadNotSupportedError("FLOSS currently supports the following formats for string decoding and "
                                        "stackstrings: PE\nYou can analyze shellcode using the -s switch. See the "
                                        "help (-h) for more information.")
        floss_logger.info("Generating vivisect workspace...")
    return viv_utils.getWorkspace(sample_file_path, should_save=save_workspace)
Exemple #18
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]
def _test_FunctionArgumentGetter_get_function_end(samples_path):
    file_path = os.path.join(samples_path, "6ee35da59f92f71e757d4d5b964ecf00.viv")
    vivisect_workspace = viv_utils.getWorkspace(file_path)
    f*g = FunctionArgumentGetter(vivisect_workspace)

    answer = {0x4018AD: 0x401CDF, 0x401CE0: 0x402108}

    ends = {}
    for function_start in answer.keys():
        function_end = f*g.get_function_end(function_start)
        ends[function_start] = function_end

    assert cmp(answer, ends) == 0
def test_FAG_get_all_function_contexts_return_addresses(samples_path):
    file_path = os.path.join(samples_path, "6ee35da59f92f71e757d4d5b964ecf00.viv")
    vivisect_workspace = viv_utils.getWorkspace(file_path)
    emu = vivisect_workspace.getEmulator()

    f*g = FunctionArgumentGetter(vivisect_workspace)
    answer = [0x40241B, 0x4023E5]

    all_return_addresses = []
    for function_context in f*g.get_all_function_contexts(0x0040424E):
        all_return_addresses.append(function_context.return_address)

    assert set(answer) == set(all_return_addresses)
def _main(bin_path, fva):
    logging.basicConfig(level=logging.DEBUG)

    vw = viv_utils.getWorkspace(bin_path)
    emu = vw.getEmulator()
    d = viv_utils.emulator_drivers.FunctionRunnerEmulatorDriver(emu)

    m = AMonitor(vw)
    d.add_monitor(m)

    logging.getLogger("trace").debug("%s %s %s %s", vw, emu, d, m)

    d.runFunction(int(fva, 0x10), maxhit=1)
def _test_FunctionArgumentGetter_get_function_end(samples_path):
    file_path = os.path.join(samples_path,
                             "6ee35da59f92f71e757d4d5b964ecf00.viv")
    vivisect_workspace = viv_utils.getWorkspace(file_path)
    f*g = FunctionArgumentGetter(vivisect_workspace)

    answer = {0x4018AD: 0x401CDF, 0x401CE0: 0x402108}

    ends = {}
    for function_start in answer.keys():
        function_end = f*g.get_function_end(function_start)
        ends[function_start] = function_end

    assert cmp(answer, ends) == 0
def test_FAG_get_all_function_contexts_return_addresses(samples_path):
    file_path = os.path.join(samples_path,
                             "6ee35da59f92f71e757d4d5b964ecf00.viv")
    vivisect_workspace = viv_utils.getWorkspace(file_path)
    emu = vivisect_workspace.getEmulator()

    f*g = FunctionArgumentGetter(vivisect_workspace)
    answer = [0x40241B, 0x4023E5]

    all_return_addresses = []
    for function_context in f*g.get_all_function_contexts(0x0040424E):
        all_return_addresses.append(function_context.return_address)

    assert set(answer) == set(all_return_addresses)
Exemple #24
0
    def _test_detection(self, test_path):
        try:
            expected_functions = set(self.spec["Decoding routines"][self.platform][self.arch])
        except KeyError:
            expected_functions = set([])

        if not expected_functions:
            return

        vw = viv_utils.getWorkspace(test_path)
        fs = map(lambda p: p[0], identify_decoding_functions(vw).get_top_candidate_functions())
        found_functions = set(fs)

        if not (expected_functions <= found_functions):
            raise FLOSSDecodingFunctionNotFound(expected_functions, found_functions)
def test_FAG_get_context_via_monitor_return_addresses(samples_path):
    file_path = os.path.join(samples_path, "6ee35da59f92f71e757d4d5b964ecf00.viv")
    vivisect_workspace = viv_utils.getWorkspace(file_path)
    emu = vivisect_workspace.getEmulator()

    f*g = FunctionArgumentGetter(vivisect_workspace)
    caller_va = 0x401698
    function_va = 0x40166C
    all_return_addresses = []
    for function_context in f*g.get_contexts_via_monitor(caller_va, function_va):
        all_return_addresses.append(function_context.return_address)

    answer = set([0x4016C8, 0x4016D3])

    assert answer == set(all_return_addresses)
Exemple #26
0
    def _test_detection(self, test_path):
        try:
            expected_functions = set(self.spec["Decoding routines"][self.platform][self.arch])
        except KeyError:
            expected_functions = set([])

        if not expected_functions:
            return

        vw = viv_utils.getWorkspace(test_path)
        top_functions, _ = identify_decoding_functions(vw)
        found_functions = set(top_functions)

        if not (expected_functions <= found_functions):
            raise FLOSSDecodingFunctionNotFound(expected_functions, found_functions)
Exemple #27
0
    def _test_detection(self, test_path):
        try:
            expected_functions = set(self.spec["Decoding routines"][self.platform][self.arch])
        except KeyError:
            expected_functions = set([])

        if not expected_functions:
            return

        vw = viv_utils.getWorkspace(test_path)
        fs = map(lambda p: p[0], identify_decoding_functions(vw).get_top_candidate_functions())
        found_functions = set(fs)

        if not (expected_functions <= found_functions):
            raise FLOSSDecodingFunctionNotFound(expected_functions, found_functions)
Exemple #28
0
    def _test_strings(self, test_path):
        expected_strings = set(self.spec["Decoded strings"])
        if not expected_strings:
            return

        arch = self.spec.get("Shellcode Architecture")
        if arch in ("i386", "amd64"):
            vw = viv_utils.getShellcodeWorkspaceFromFile(test_path, arch)
            found_strings = set(extract_strings(vw))
        else:
            # default assumes pe
            vw = viv_utils.getWorkspace(test_path)
            found_strings = set(extract_strings(vw))

        if not (expected_strings <= found_strings):
            raise FLOSSStringsNotExtracted(expected_strings, found_strings)
def test_FAG_get_context_via_monitor_return_addresses(samples_path):
    file_path = os.path.join(samples_path,
                             "6ee35da59f92f71e757d4d5b964ecf00.viv")
    vivisect_workspace = viv_utils.getWorkspace(file_path)
    emu = vivisect_workspace.getEmulator()

    f*g = FunctionArgumentGetter(vivisect_workspace)
    caller_va = 0x401698
    function_va = 0x40166C
    all_return_addresses = []
    for function_context in f*g.get_contexts_via_monitor(
            caller_va, function_va):
        all_return_addresses.append(function_context.return_address)

    answer = set([0x4016C8, 0x4016D3])

    assert answer == set(all_return_addresses)
Exemple #30
0
    def _test_strings(self, test_path):
        expected_strings = set(self.spec["Decoded strings"])
        if not expected_strings:
            return

        test_shellcode = self.spec.get("Test shellcode")
        if test_shellcode:
            with open(test_path, "rb") as f:
                shellcode_data = f.read()
            vw = viv_utils.getShellcodeWorkspace(shellcode_data)  # TODO provide arch from test.yml
            found_strings = set(extract_strings(vw))
        else:
            vw = viv_utils.getWorkspace(test_path)
            found_strings = set(extract_strings(vw))

        if not (expected_strings <= found_strings):
            raise FLOSSStringsNotExtracted(expected_strings, found_strings)
Exemple #31
0
    def _test_strings(self, test_path):
        expected_strings = set(self.spec["Decoded strings"])
        if not expected_strings:
            return

        test_shellcode = self.spec.get("Test shellcode")
        if test_shellcode:
            with open(test_path, "rb") as f:
                shellcode_data = f.read()
            vw = viv_utils.getShellcodeWorkspace(shellcode_data)  # TODO provide arch from test.yml
            found_strings = set(extract_strings(vw))
        else:
            vw = viv_utils.getWorkspace(test_path)
            found_strings = set(extract_strings(vw))

        if not (expected_strings <= found_strings):
            raise FLOSSStringsNotExtracted(expected_strings, found_strings)
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 :("
Exemple #33
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
Exemple #34
0
def load_vw(
    sample_path: str,
    format: str,
    sigpaths: str,
    should_save_workspace: bool = False,
) -> VivWorkspace:

    if format not in ("sc32", "sc64"):
        if not is_supported_file_type(sample_path):
            raise WorkspaceLoadError(
                "FLOSS currently supports the following formats for string decoding and stackstrings: PE\n"
                "You can analyze shellcode using the --format sc32|sc64 switch. See the help (-h) for more information."
            )

    # get shellcode type based on sample file extension
    if format == "auto" and sample_path.endswith(EXTENSIONS_SHELLCODE_32):
        format = "sc32"
    elif format == "auto" and sample_path.endswith(EXTENSIONS_SHELLCODE_64):
        format = "sc64"

    if format == "sc32":
        vw = viv_utils.getShellcodeWorkspaceFromFile(sample_path, arch="i386", analyze=False)
    elif format == "sc64":
        vw = viv_utils.getShellcodeWorkspaceFromFile(sample_path, arch="amd64", analyze=False)
    else:
        vw = viv_utils.getWorkspace(sample_path, analyze=False, should_save=False)

    viv_utils.flirt.register_flirt_signature_analyzers(vw, sigpaths)

    vw.analyze()

    if should_save_workspace:
        logger.debug("saving workspace")
        try:
            vw.saveWorkspace()
        except IOError:
            logger.info("source directory is not writable, won't save intermediate workspace")
    else:
        logger.debug("not saving workspace")

    return vw
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
Exemple #36
0
def main(argv=None):
    if argv is None:
        argv = sys.argv[1:]

    parser = argparse.ArgumentParser(description="FLIRT match each function")
    parser.add_argument("sample", type=str, help="Path to sample to analyze")
    parser.add_argument(
        "-F",
        "--function",
        type=lambda x: int(x, 0x10),
        help="match a specific function by VA, rather than add functions",
    )
    parser.add_argument(
        "--signature",
        action="append",
        dest="signatures",
        type=str,
        default=[],
        help=
        "use the given signatures to identify library functions, file system paths to .sig/.pat files.",
    )
    parser.add_argument("-d",
                        "--debug",
                        action="store_true",
                        help="Enable debugging output on STDERR")
    parser.add_argument("-q",
                        "--quiet",
                        action="store_true",
                        help="Disable all output but errors")
    args = parser.parse_args(args=argv)

    if args.quiet:
        logging.basicConfig(level=logging.ERROR)
        logging.getLogger().setLevel(logging.ERROR)
    elif args.debug:
        logging.basicConfig(level=logging.DEBUG)
        logging.getLogger().setLevel(logging.DEBUG)
    else:
        logging.basicConfig(level=logging.INFO)
        logging.getLogger().setLevel(logging.INFO)

    # disable vivisect-related logging, it's verbose and not relevant for capa users
    capa.main.set_vivisect_log_level(logging.CRITICAL)

    analyzers = []
    for sigpath in args.signatures:
        sigs = capa.main.load_flirt_signature(sigpath)

        with capa.main.timing("flirt: compiling sigs"):
            matcher = flirt.compile(sigs)

        analyzer = viv_utils.flirt.FlirtFunctionAnalyzer(matcher, sigpath)
        logger.debug("registering viv function analyzer: %s", repr(analyzer))
        analyzers.append(analyzer)

    vw = viv_utils.getWorkspace(args.sample, analyze=True, should_save=False)

    functions = vw.getFunctions()
    if args.function:
        functions = [args.function]

    for function in functions:
        logger.debug("matching function: 0x%04x", function)
        for analyzer in analyzers:
            name = viv_utils.flirt.match_function_flirt_signatures(
                analyzer.matcher, vw, function)
            if name:
                print("0x%04x: %s" % (function, name))

    return 0
Exemple #37
0
if not find_unicode_device_name():
    print "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))
        sys.exit(1)

    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)
    decoding_functions_candidates = floss.identification_manager.identify_decoding_functions(
        vw, plugins, functions)
    function_index = viv_utils.InstructionFunctionIndex(vw)
    decoded_strings = floss.main.decode_strings(vw, function_index,
Exemple #38
0
def main(argv=None):
    """
    :param argv: optional command line arguments, like sys.argv[1:]
    """
    logging.basicConfig(level=logging.WARNING)

    parser = make_parser()
    if argv is not None:
        options, args = parser.parse_args(argv)
    else:
        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)

    with open(sample_file_path, "rb") as f:
        magic = f.read(2)

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

    if magic not in SUPPORTED_FILE_MAGIC:
        floss_logger.error("FLOSS currently supports the following formats: PE")
        if not options.all_strings:
            floss_logger.error("Recommend passing flag `-a` to extract static strings from any file type.")
        return

    if os.path.getsize(sample_file_path) > MAX_FILE_SIZE:
        floss_logger.error("FLOSS cannot emulate files larger than %d bytes" % (MAX_FILE_SIZE))
        if not options.all_strings:
            floss_logger.error("Recommend passing flag `-a` to extract static strings from any sized file.")
        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))
Exemple #39
0
if not find_unicode_device_name():
    print "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))
        sys.exit(1)
    
    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)
    decoding_functions_candidates  = floss.identification_manager.identify_decoding_functions(vw, plugins, functions)
    function_index = viv_utils.InstructionFunctionIndex(vw)
    decoded_strings = floss.main.decode_strings(vw, function_index, decoding_functions_candidates)
    if len(decoded_strings) > 0:
Exemple #40
0
def sample_bfb9b5391a13d0afd787e87ab90f14f5():
    path = os.path.join(CD, "data", "bfb9b5391a13d0afd787e87ab90f14f5.dll_")
    return Sample(viv_utils.getWorkspace(path), path)
    def run(self):
        db = Database()
        # Get Options

        if "min_length" in self.request.POST:
            min_len = self.request.POST['min_length']
        else:
            min_len = 4

        if 'file_id' in self.request.POST:
            file_id = self.request.POST['file_id']
            # Check to see if we already have strings stored.
            new_strings = db.get_strings(file_id)
            if new_strings:
                string_id = new_strings._id
            else:

                file_object = db.get_filebyid(file_id)

                # Always get ASCII and Unicode

                file_data = file_object.read()

                ascii_strings = self.ascii_strings(file_data, 4)
                unicode_strings = self.unicode_strings(file_data, 4)

                if HAVE_FLOSS:

                    # Advacned Floss needs a file on disk
                    with tempfile.NamedTemporaryFile() as tmp:
                        tmp.write(file_data)

                        file_path = tmp.name

                        if self.is_supported_file_type(file_path):
                            try:
                                vw = viv_utils.getWorkspace(file_path, should_save=False)
                            except Exception:
                                print "ahhhhhhhhhhhhhh"
                                raise

                            # Decode Strings
                            #decoding_functions_candidates = im.identify_decoding_functions(vw, selected_plugins, selected_functions)
                            #function_index = viv_utils.InstructionFunctionIndex(vw)

                            #decoded_strings = decode_strings(vw, function_index, decoding_functions_candidates)

                            # Stack Strings

                # Generate the final output file

                string_list = '##### ASCII Strings #####\n {0} \n ##### Unicode Strings #####\n {1}'.format(ascii_strings, unicode_strings)

                '''
                String lists can get larger than the 16Mb bson limit
                Need to store in GridFS
                '''
                store_data = {'file_id': file_id, 'string_list': string_list}
                string_id = db.create_file(string_list, 'session_id', 'sha256', '{0}_strings.txt'.format(file_id))
                print string_id

            self.render_type = 'html'
            self.render_data = '<td><a class="btn btn-success" role="button" href="/download/file/{0}">Download</a></td>'.format(
                        string_id)
Exemple #42
0
def pma_lab_12_04():
    path = os.path.join(CD, "data",
                        "Practical Malware Analysis Lab 12-04.exe_")
    return Sample(viv_utils.getWorkspace(path), path)
Exemple #43
0
def sample_lab21_01():
    path = os.path.join(CD, "data",
                        "Practical Malware Analysis Lab 21-01.exe_")
    return Sample(viv_utils.getWorkspace(path), path)
Exemple #44
0
def sample_c91887d861d9bd4a5872249b641bc9f9():
    path = os.path.join(CD, "data", "c91887d861d9bd4a5872249b641bc9f9.exe_")
    return Sample(viv_utils.getWorkspace(path), path)