Binary Coverage

Purpose

This script is designed to build the coverage of a binary executed in a REVEN scenario.

How to use

usage: bin_coverage.py [-h] [--host HOST] [-p PORT] binary positional arguments: binary Binary on which to compute coverage optional arguments: -h, --help show this help message and exit --host HOST Reven host, as a string (default: "localhost") -p PORT, --port PORT Reven port, as an int (default: 13370)

Known limitations

N/A

Supported versions

REVEN 2.2+

Supported perimeter

Any REVEN scenario.

Dependencies

None.

Source

import argparse import builtins from collections import defaultdict import reven2 as reven # %% [markdown] # # Binary Coverage # # ## Purpose # # This script is designed to build the coverage of a binary executed in a REVEN scenario. # # ## How to use # # ```bash # usage: bin_coverage.py [-h] [--host HOST] [-p PORT] binary # # positional arguments: # binary Binary on which to compute coverage # # optional arguments: # -h, --help show this help message and exit # --host HOST Reven host, as a string (default: "localhost") # -p PORT, --port PORT Reven port, as an int (default: 13370) # ``` # # ## Known limitations # # N/A # # ## Supported versions # # REVEN 2.2+ # # ## Supported perimeter # # Any REVEN scenario. # # ## Dependencies # # None. def find_and_choose_binary(ossi, requested_binary): binaries = list(ossi.executed_binaries(requested_binary)) if len(binaries) == 0: raise RuntimeError('Binary "{}" not executed in the trace.'.format(requested_binary)) if len(binaries) == 1: return binaries[0] print('Multiple matches for "{}":'.format(requested_binary)) for (index, binary) in enumerate(binaries): print("{}: {}".format(index, binary.path)) answer = builtins.input("Please choose one binary: ") return binaries[int(answer)] def compute_binary_coverages(trace, binary): coverages = {} for ctx in trace.search.binary(binary): asid = ctx.read(reven.arch.x64.cr3) loc = ctx.ossi.location() symbol = "unknown" if loc.symbol is None else loc.symbol.name asid_coverage = coverages.setdefault(asid, [loc.base_address, defaultdict(int)])[1] asid_coverage[symbol] += 1 return coverages def binary_coverage(reven_server, binary): binary = find_and_choose_binary(reven_server.ossi, binary) return compute_binary_coverages(reven_server.trace, binary) def print_binary_coverages(coverages): for (asid, asid_coverage) in coverages.items(): print("***** Coverage for CR3 = {:#x}: base address = {:#x} *****\n".format(asid, asid_coverage[0])) for (symbol, symbol_coverage) in asid_coverage[1].items(): print(" {}: {}".format(symbol, symbol_coverage)) print("\n") if __name__ == "__main__": parser = argparse.ArgumentParser() parser.add_argument("--host", type=str, default="localhost", help='Reven host, as a string (default: "localhost")') parser.add_argument("-p", "--port", type=int, default="13370", help="Reven port, as an int (default: 13370)") parser.add_argument("binary", type=str, help="Binary on which to compute coverage") args = parser.parse_args() reven_server = reven.RevenServer(args.host, args.port) coverages = binary_coverage(reven_server, args.binary) print_binary_coverages(coverages)