Ejemplo n.º 1
0
def main(target: str, delphi_version: int):
    # Just disable some features for large binaries
    opts = {
        'analysis.mode': 'full',
        'analysis.linearSweep.autorun': False,
        'analysis.linearSweep.controlFlowGraph': False,
    }

    bv = BinaryViewType.get_view_of_file_with_options(target, options=opts)

    if bv is None:
        print(f'Invalid binary path: {target}')
        exit(-1)

    BNLogger.init_console()
    BNLogger.log('File loaded')
    BNLogger.log('-----------------------------')
    BNLogger.log('Searching for VMT...')

    analyzer = DelphiAnalyzer(bv, delphi_version)
    analyzer.update_analysis_and_wait(lambda vmt: analyze_callback(vmt, bv))

    bv.update_analysis_and_wait()

    BNLogger.log(f'Saving database: `{target}.bndb`...')
    bv.create_database(f'{target}.bndb')
Ejemplo n.º 2
0
def run_fs_test(fpath):
    bv = BinaryViewType.get_view_of_file(fpath)
    bv.update_analysis_and_wait()

    fs_finder = FormatStringFinder(bv, False)
    fs_finder.find_format_strings()

    # ====================
    # Prepare what should be found
    success = True
    printf_like_funcs = [x for x in bv.symbols if x.startswith("PRINTF_LIKE")]
    vuln_funcs = [x for x in bv.symbols if x.startswith("VULN")]
    safe_funcs = [x for x in bv.symbols if x.startswith("SAFE")]

    def test_helper(should_be_found, found, msg_type):
        nonlocal success

        for i in should_be_found:
            if i not in found:
                log_error(f"'{i}' was not detected as a {msg_type}.")
                success = False
            else:
                log_info(f"'{i}' successfully detected as a {msg_type}.")

    # ====================
    # Check that every printf like function was found
    found_printf_like_funcs = [x.name for x in fs_finder.new_printf_like_funcs]
    test_helper(printf_like_funcs, found_printf_like_funcs,
                "printf like function")

    # ====================
    # Check that all safe/vuln results are in safe/vuln functions
    found_vuln_funcs = [
        x.ref.function.name for x in fs_finder.results if x.is_vuln
    ]
    found_safe_funcs = [
        x.ref.function.name for x in fs_finder.results if not x.is_vuln
    ]
    test_helper(vuln_funcs, found_vuln_funcs, "vuln function")
    test_helper(safe_funcs, found_safe_funcs, "safe function")

    bv.file.close()
    return success
Ejemplo n.º 3
0
    def __init__(self,
                 filename: Optional[str] = None,
                 debug_root: Optional[str] = None,
                 debug_file: Optional[str] = None,
                 binary_view: Optional[BinaryView] = None,
                 logger=None):
        if filename is None and binary_view is None:
            raise ValueError('Must specify either a filename or binary view.')

        self.model: AnalysisModel
        self.binary_view: BinaryView
        self.debug_root = debug_root
        self.debug_file = debug_file

        if binary_view is None:
            bv = BinaryViewType.get_view_of_file(filename,
                                                 update_analysis=True)
            if bv is None:
                raise Exception(
                    f'Unable to get binary view for file: {filename}')
            self.binary_view = bv
        else:
            self.binary_view = binary_view

        if self.binary_view.arch is None:
            raise Exception('The binary view has no valid architecture.')

        # Create the root module with the binary name as the module name.
        if filename is None:
            filename = self.binary_view.file.original_filename
            assert (isinstance(filename, str))
        binary_name = os.path.basename(filename)

        debug_source = filename
        if self.debug_file is not None:
            debug_source = self.debug_file
        m = AnalysisModel.from_dwarf(debug_source,
                                     self.debug_root,
                                     name=binary_name,
                                     logger=logger)
        self.model = m if m else AnalysisModel(binary_name)

        self.mapping = BinjaMap(self.binary_view)
Ejemplo n.º 4
0
def main(target: str, delphi_version: int):
    # Just disable some features for large binaries
    opts = {
        'analysis.mode': 'controlFlow',
        'analysis.linearSweep.autorun': False,
        'analysis.linearSweep.controlFlowGraph': False,
    }

    bv = BinaryViewType.get_view_of_file_with_options(target, options=opts)

    if bv is None:
        print(f'Invalid binary path: {target}')
        exit(-1)

    BNLogger.init_console()
    BNLogger.log('File loaded')
    BNLogger.log('Searching for VMT...')

    analyzer = DelphiAnalyzer(bv, delphi_version)
    analyzer.update_analysis_and_wait()

    BNLogger.log('Creating Graph...')
    vmt_map = {vmt.start: vmt for vmt in analyzer.vmt_list}
    create_graph(vmt_map)
Ejemplo n.º 5
0
    possible_sizes = size_param.possible_values

    # Dataflow won't combine multiple possible values from
    # shifted bytes, so any value we care about will be
    # undetermined at this point. This might change in the future?
    if possible_sizes.type != RegisterValueType.UndeterminedValue:
        return False

    model = ByteSwapModeler(size_param, bv.address_size)

    return model.is_byte_swap()


if __name__ == '__main__':
    filename = sys.argv[1]
    bv = BinaryViewType.get_view_of_file(filename)
    bv.update_analysis_and_wait()

    print "{} loaded...".format(filename)

    memcpy_refs = [
        (ref.function, ref.address)
        for ref in bv.get_code_refs(bv.symbols['_memcpy'].address)
    ]

    print 'Checking {} memcpy calls'.format(len(memcpy_refs))

    dangerous_calls = []

    for function, addr in tqdm(memcpy_refs):
        call_instr = function.get_low_level_il_at(addr).medium_level_il
Ejemplo n.º 6
0
def open_bv(path, **kw):
    # Note: This is now a context manager, hurrah!
    return BinaryViewType.get_view_of_file(path, **kw)
Ejemplo n.º 7
0
    print("[*] Syntax: {} <path to analysis directory> <output file>".format(
        sys.argv[0]))
    exit(0)

# parse arguments
analysis_directory = sys.argv[1]
output_file_path = sys.argv[2]

# global ngrams counter
ngrams = Counter()
# set n as default to 3
n = 3

# walk over all binaries in the provided directory
for binary_file_path in glob.glob(f"{analysis_directory}/*"):
    print(f"Analyzing file {binary_file_path}.")
    # init binary ninja
    bv = BinaryViewType.get_view_of_file(binary_file_path)
    # wait until analysis finishes
    bv.update_analysis_and_wait()
    # count ngrams
    ngrams.update(calc_global_ngrams(bv, n))

# prepare output string -- the most common 1k ngrams in a set
output_string = pformat({k for k, v in ngrams.most_common(1000)})

# write output file
with open(output_file_path, 'w') as output_file:
    output_file.write(output_string)
    output_file.close()