Beispiel #1
0
def import_annotation(binary: Binary, type_: FileType,
                      path: Path) -> Annotation:
    """Imports functions from annotation file and creates Annotation object.

    Args:
        binary: The Binary to which to import functions.

	Returns:
        the Annotation, with newly created functions.
    """

    if not path.is_file():
        raise FileNotFoundError
    logger.info(f"Importing {type_.name} file from {path}")
    ann_cls, fnc_gen = FileTypeMapping[type_]
    binary.partition()
    annotation = ann_cls(binary=binary, path=str(path))
    meta = fnc_gen(path)
    for name, addr, size, mode in meta:
        if not binary.range_is_valid(addr, addr + size):
            logger.debug(
                f"{name} @{addr:#08X}-{addr+size:#08X} not in valid range")
            continue
        if len(name) > 0 and binary.range_is_valid(addr, addr + size):
            fnc = Function.get(binary=binary, addr=addr)
            if not fnc:
                fnc = binary.functions.create(addr=addr,
                                              size=size,
                                              name=name,
                                              mode=mode)
            annotation.functions.add(fnc)
    binary.annotations.add(annotation)
    return annotation
Beispiel #2
0
def _cli_list(
    list_history: bool,
    list_targets: bool,
):
    def format_binary_list(
            binary_list: Iterable[Binary],
            is_annotated: Optional[bool] = False) -> Iterable[dict]:

        keys = ["id", "name", "filepath"]
        data = []
        for binary in list(binaries):
            b_dict = binary.to_dict(only=keys)
            if is_annotated is True:
                b_dict["#annotations"] = binary.annotations.count()
                b_dict["#functions"] = binary.functions.count()
            data.append(b_dict)

        return data

    if list_history is True:
        typer.echo("History Files")
        binaries = Binary.select_annotated()
        formatted = format_binary_list(binaries, is_annotated=True)
        table = tabulate(formatted, headers="keys")
        typer.echo(table)

    if list_history is True and list_targets is True:
        typer.echo()  # additional newline for readability

    if list_targets is True:
        typer.echo("Target Files")
        binaries = Binary.select_unannotated()
        formatted = format_binary_list(binaries, is_annotated=False)
        table = tabulate(formatted, headers="keys")
        typer.echo(table)
Beispiel #3
0
def _binary_ops(binary: str, comment: str, export_csv: str, remove: bool):
    b = Binary.get(name=binary)
    if comment is not None:
        b.comment = comment
    if export_csv is not None:
        export_csv_combined(b, export_csv)
    if remove is True:
        Binary.delete(b)
Beispiel #4
0
def find_starts(target: Binary, start_cut: int = 8) -> Iterable[Match]:
    match_finder = make_start_scout()
    itree = target.partition_without_matches()
    matches = []
    for interval in itree:
        data = target.read()[interval.begin:interval.end]
        for addr, matcher in match_finder(data, interval.begin):
            match, new = Match.deduplicate(target, addr, matcher.cut_size,
                                           dict(certainty=1))
            match.matched_by.add(matcher)
            if new:
                target.matches.add(match)
                matches.append(match)

    return matches
Beispiel #5
0
def prepare_graph(histories: List[Path], annotations: List[Path],
                  min_size: int, max_rel_fuzz: float) -> Optional[Graph]:

    logger.debug("Importing history")
    for history, annotation in zip(histories, annotations):
        bin_ = get_or_create_binary(history)
        get_or_create_annotation(bin_, annotation)
        logger.debug(f"Imported history {bin_.serialize()}")

    if Binary.select_annotated().count() == 0:
        typer.echo("No history entries in database")
        return None

    if histories:
        logger.debug("Clearing matchers")
        Matcher.reset()
        logger.debug("Grouping function symbols")
        groups = Function.common_functions(min_size, 1)
        logger.debug("finished grouping")
        logger.debug("make matchers")
        matchers = create_matchers(groups, min_size, max_rel_fuzz)
        logger.debug(f"{len(matchers)} matchers generated")
    graph = makeGraph(matchers)
    logger.debug("finish making matchers")
    return graph
Beispiel #6
0
def match_matchers_against(target: Binary,
                           graph=None,
                           parallelize=True) -> Iterable[Match]:
    """match_candidates_against matches all candidates against the given
    Binary.

	Args:
        target: the target binary to match the candidates against
    """

    settings = SettingsStorage.get_settings()
    parallelize = parallelize or settings.get("matcher_parallelization", False)
    if graph is None:
        graph = makeGraph()
    bin_ = target.read()
    partitions = target.partition()
    if parallelize:
        matches = parallel_prepartioned_graph_match(graph, bin_, partitions)
    else:
        matches = prepartioned_graph_match(graph, bin_, partitions)
    match_results = []
    for matchers, size, end in matches:
        start = end - size
        match, new = Match.deduplicate(target, start, size,
                                       dict(certainty=1 / len(matchers)))
        for matcher in matchers:
            match.matched_by.add(matcher)
        if new:
            target.matches.add(match)
            match_results.append(match)
    orm.commit()

    if settings.get("find_fnc_starts", False):
        starts = find_starts(target,
                             start_cut=settings.get("fnc_start_size", 8))
        match_results.extend(starts)
        orm.commit()
    return match_results
Beispiel #7
0
def get_or_create_binary(path: Path, make_target=False) -> Binary:
    """import_binary creates a Binary and stores it in database

	Args:
        binary_path: the file path of the binary

	Returns: Binary
    """

    logger.info(f"retrieving binary for path {path}")
    binary = Binary.get(filepath=str(path))
    if not binary:
        if not path.is_file():
            raise FileNotFoundError
        binary = Binary(filepath=str(path), name=path.name)
    elif make_target:
        binary.is_target = True
    binary.partition()
    return binary