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)