Trace symbol coverage

Purpose

Display a list of executed binaries and symbols in a REVEN scenario, indicating how many transitions where spent in each symbol/binary.

How to use

usage: trace_coverage.py [-h] [--host HOST] [-p PORT] [-m MAX_TRANSITION] 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) -m MAX_TRANSITION, --max-transition MAX_TRANSITION Maximum number of transitions

Known limitations

N/A

Supported versions

REVEN 2.2+

Supported perimeter

Any REVEN scenario.

Dependencies

None.

Source

import argparse import reven2 as reven """ # Trace symbol coverage ## Purpose Display a list of executed binaries and symbols in a REVEN scenario, indicating how many transitions where spent in each symbol/binary. ## How to use ```bash usage: trace_coverage.py [-h] [--host HOST] [-p PORT] [-m MAX_TRANSITION] 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) -m MAX_TRANSITION, --max-transition MAX_TRANSITION Maximum number of transitions ``` # Known limitations N/A ## Supported versions REVEN 2.2+ ## Supported perimeter Any REVEN scenario. ## Dependencies None. """ def trace_coverage(reven_server, max_transition=None): if max_transition is None: max_transition = reven_server.trace.transition_count else: max_transition = min(max_transition, reven_server.trace.transition_count) transition_id = 0 coverages = {} while transition_id < max_transition: ctx = reven_server.trace.context_before(transition_id) transition_id += 1 asid = ctx.read(reven.arch.x64.cr3) loc = ctx.ossi.location() unknown = True if loc is None else False binary = "unknown" if unknown else loc.binary.path symbol = "unknown" if unknown or loc.symbol is None else loc.symbol.name try: asid_coverage = coverages[asid] except KeyError: coverages[asid] = {} asid_coverage = coverages[asid] try: binary_coverage = asid_coverage[binary] binary_coverage[0] += 1 if binary == "unknown": continue except KeyError: if binary == "unknown": asid_coverage[binary] = [1, None] continue asid_coverage[binary] = [1, {}] binary_coverage = asid_coverage[binary] try: binary_coverage[1][symbol] += 1 except KeyError: binary_coverage[1][symbol] = 1 return coverages def print_coverages(coverages): for (asid, asid_coverage) in coverages.items(): print("***** Coverage for CR3 = {:#x} *****\n".format(asid)) for (binary, binary_coverage) in asid_coverage.items(): print("- {}: {}".format(binary, binary_coverage[0])) if binary_coverage[1] is None: continue for (symbol, symbol_coverage) in binary_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("-m", "--max-transition", type=int, help="Maximum number of transitions") args = parser.parse_args() reven_server = reven.RevenServer(args.host, args.port) coverages = trace_coverage(reven_server, args.max_transition) print_coverages(coverages)