[ Web Proxy ]
URL:
Viewing: https://raw.githubusercontent.com/Vector35/binaryninja-api/dev/python/examples/bindiff.py [Back]  [Original]

"""Compare two binaries with the Google BinDiff similarity provider (Ultimate only)."""

import argparse
import csv
import time
from pathlib import Path

from binaryninja import (
    BinaryView,
    LogLevel,
    SimilarityProviderType,
    SimilaritySession,
    SimilaritySessionNode,
    load,
)
from binaryninja.log import log_to_stdout
from binaryninja.similarity import SimilarityEntityInfo, SimilarityEntityType, SimilaritySessionCompletion


def wait_for_completion(completion: SimilaritySessionCompletion, timeout: float = 120) -> bool:
    """Wait up to ``timeout`` seconds for a similarity run to finish."""
    deadline = time.monotonic() + timeout
    while not completion.is_finished and time.monotonic() < deadline:
        time.sleep(0.1)
    return completion.is_finished


def diff(primary: BinaryView, secondary: BinaryView, output_csv: Path) -> int:
    """Compare two views and write their function matches to ``output_csv``."""
    provider_type = SimilarityProviderType["Google BinDiff"]
    provider_settings = provider_type.get_default_settings()
    provider = provider_type.create(provider_settings)

    session = SimilaritySession()
    session.add_provider(provider)
    primary_node = SimilaritySessionNode(primary)
    secondary_node = SimilaritySessionNode(secondary)
    session.graph.add_node(primary_node)
    session.graph.add_node(secondary_node)
    session.graph.add_edge(primary_node, secondary_node)

    completion = session.run()
    if not wait_for_completion(completion):
        completion.request_stop()
        wait_for_completion(completion, timeout=10)
        raise TimeoutError("BinDiff did not finish before the timeout")

    match_count = 0
    with output_csv.open("w", newline="") as output:
        writer = csv.writer(output)
        writer.writerow(["Address", "Function", "Matched Function", "Similarity", "Confidence"])
        for function in secondary.functions:
            entity = secondary_node.create_entity(
                SimilarityEntityInfo(SimilarityEntityType.SimilarityEntityFunction, function.start, function.name)
            )
            for result_id in secondary_node.get_results(entity):
                result = secondary_node.get_result(result_id)
                name = provider.get_name(secondary_node, entity, result_id)
                writer.writerow([hex(function.start), function.name, name, result.similarity, result.confidence])
                match_count += 1
    return match_count


def main() -> int:
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument("primary", help="baseline binary")
    parser.add_argument("secondary", help="binary to compare")
    parser.add_argument("output", type=Path, help="output CSV path")
    args = parser.parse_args()

    log_to_stdout(LogLevel.WarningLog)
    with load(args.primary) as primary, load(args.secondary) as secondary:
        count = diff(primary, secondary, args.output)
    print(f"Wrote {count} matches to {args.output}")
    return 0


if __name__ == "__main__":
    raise SystemExit(main())

Web Proxy Viewer  |  New URL  |  Original Page