Cb Reporting released

Posted on August 8, 2017

We are pleased to announce the release of an updated Cb Reporting script.


The incident report script is an example python program that demonstrates how to build a basic incident report using the Cb API bindings for python.

The incident report uses the Cb API to trace information about the lifetime of a process of interest:

  1. Target process event information: module loads, cross process interactions, file modifications, registry modifications (windows) as well as intelligence feed hits, and the hosts/paths on which the target was seen
  2. The tree of execution that lead to the target process - binary information about each
  3. A list of processes that have written to the target process/binary, details about each
  4. The child processes of the target process + corresponding binaries

The only dependencies are on the Jinja2 templating engine module for python (2.6+), and the Cb API bindings for python V1.3.1+ - available via pip/pypi

At a high level, Incident_report.py defines a IncidentReportGenerator class that manipulates the Cb API bindings and exposes a generate_report(guid) method for generating reports as HTML.

Report generation begins by using the Cb API to retrieve Process information from the server for the Target GUID.

#build the report directory path and lookup the target process by GUID
output_directory = os.path.join("reports", guid)
process = self.cb.select(Process, guid)

Most of the information needed for this report can be accessed directly from the ProcessModel object.

Walking the child-process tree for this target process is as easy as iterating over the children generator (Here used to write the icons for each child)

# walk children of the target process and write icons
for child in process.children:
    write_iconfile(output_directory, child.process)

… similar syntax is used to quickly walk the tree of execution up to its top:

# walk execution tree/parents and write icons
for parent in process.parents:
    write_iconfile(output_directory, parent)   

A query with a where-clause is used to find the writers - or processes which have written to the target process’s binary.

# find processes that have written to the target process's binary
writers = []
writers.extend(self.cb.select(Process).where("filemod:{} and hostname:{} and process_md5:*"
                                                     .format(process.path, process.hostname)))

The report uses the facets associated with the process to capture what hosts and paths the target has been seen on.

# build a list of hostname/filepath facets for this process-binary-by-md5
facets = self.cb.select(Process).where("process_md5:" + process.process_md5).facets()
filepaths = [{"filepath": e['name'], "percentage": e['ratio']} for e in facets.get('path_full')]
hostnames = [{'hostname': e['name'], 'percentage': e['ratio']} for e in facets.get('hostname')]

A list of intelligence feed hits is calculated on the fly:

# process alliance threat intelligence feed hits + write icons for feeds
feed_hits = []
for feed_name in process.tags:
    # A Process has fields like "alliance_score_tor,alliance_data_tor" for each
    alliance_score_n = "alliance_score_{}".format(feed_name)
    alliance_data_n = "alliance_data_{}".format(feed_name)
    feed = self.cb.select(Feed).where("name:" + feed_name).first()
    write_file(output_directory, feed.name, ".png", feed.icon_small)
    feed_hits.append({"feed": feed.name,
                      "url": feed.provider_url,
                      "score": getattr(process, alliance_score_n),
                      "data": getattr(process, alliance_data_n)})

After using the Cb API to query information about the process of interest, the aggregated metadata is used to generate a report from the provided incident report template:

def output_report_from_template(cbserver, output_directory, process, writers=None,
                                feed_hits=None, hostnames=None, filepaths=None):
    template_vars = {"process": process,
                     "sensor": process.sensor,
                     "writers": writers if writers else [],
                     "children": [child for child in process.children],
                     "parents": [p for p in process.parents],
                     "modloads": [modload for modload in process.modloads],
                     "netconns": [nc for nc in process.netconns],
                     "regmods": [rm for rm in process.regmods],
                     "crossprocs": [cp for cp in process.crossprocs],
                     "binary": process.binary,
                     "feed_hits": feed_hits if feed_hits else [],
                     "time_generated": datetime.now(),
                     "cbserver": cbserver,
                     "hostnames": hostnames if hostnames else [],
                     "filepaths": filepaths if filepaths else []}

    j2_env = Environment(loader=FileSystemLoader("."),

    report_htmlfile = file(os.path.join(output_directory, "index.html"), 'wb')

The file incident_report.j2 is a jinja2 template that outlines a generic incident report format in html. Here is a snippet showing how the section listing child processes is built. The existing template can be easily modified to change the format and contents of the report.

  • How to run

    $ ./incident-report  --guid <process-guid>
  • Example

    $ ./incident-report  --guid <process-guid>

  • How to build from source

  • clone cb-reporting.git

    $ git clone https://github.com/carbonblack/cb-reporting.git
  • Install all needed requirements:

    $ sudo pip install -r requirements.txt
  • Run the script with specified parameters

    $ python incident_report.py -guid <process-guid>

A report will be generated in ./reports/<process-guid>/index.html for the specified process GUID.

comments powered by Disqus