Package modules :: Package processing :: Module baseline
[hide private]
[frames] | no frames]

Source Code for Module modules.processing.baseline

  1  # Copyright (C) 2010-2013 Claudio Guarnieri. 
  2  # Copyright (C) 2014-2016 Cuckoo Foundation. 
  3  # This file is part of Cuckoo Sandbox - http://www.cuckoosandbox.org 
  4  # See the file 'docs/LICENSE' for copying permission. 
  5   
  6  import json 
  7  import logging 
  8  import os.path 
  9   
 10  from lib.cuckoo.common.abstracts import Processing 
 11   
 12  log = logging.getLogger(__name__) 
 13   
14 -class Baseline(Processing):
15 """Reduces Baseline results from gathered information.""" 16 order = 2 17
18 - def deep_tuple(self, o, bl=None):
19 if isinstance(o, (tuple, list)): 20 r = [] 21 for x in o: 22 r.append(self.deep_tuple(x)) 23 return tuple(r) 24 25 if isinstance(o, dict): 26 r = [] 27 for k, v in sorted(o.items()): 28 if bl and k in bl: 29 continue 30 r.append((k, self.deep_tuple(v))) 31 return tuple(r) 32 33 return o
34
35 - def normalize(self, plugin, o):
36 plugins = { 37 "pslist": ["num_threads", "num_handles"], 38 } 39 return self.deep_tuple(o, plugins.get(plugin))
40
41 - def memory(self, baseline, report):
42 """Finds the differences between the analysis report and the baseline 43 report. Puts the differences into the baseline part of the report and 44 also marks the existing rows with a `class_` attribute.""" 45 results = {} 46 47 for plugin in baseline.keys() + report.keys(): 48 results[plugin] = { 49 "config": {}, 50 "data": [], 51 } 52 53 # TODO Support having more keys in one report than the other. 54 for plugin in set(baseline.keys() + report.keys()): 55 lr = [self.normalize(plugin, x) for x in report[plugin]["data"]] 56 lb = [self.normalize(plugin, x) for x in baseline[plugin]["data"]] 57 sr, sb = set(lr), set(lb) 58 59 # Baseline vs Analysis. These events were no longer present 60 # after the analysis. 61 for row in sb.difference(sr): 62 row = baseline[plugin]["data"][lb.index(row)] 63 row["class_"] = "warning" 64 results[plugin]["data"].append(row) 65 report[plugin]["data"].append(row) 66 67 # Analysis vs Baseline. These events were added during 68 # the analysis. 69 for row in sr.difference(sb): 70 row = report[plugin]["data"][lr.index(row)] 71 row["class_"] = "danger" 72 results[plugin]["data"].append(row) 73 74 return results
75
76 - def store_baseline(self, machine, baseline):
77 """Store a new baseline report for a particular VM.""" 78 results = { 79 "memory": self.results.get("memory", {}), 80 } 81 82 with open(baseline, "wb") as report: 83 json.dump(results, report, indent=4, encoding="latin-1")
84
85 - def run(self):
86 self.key = "baseline" 87 88 machine = self.results.get("info", {}).get("machine", {}) 89 if not machine or not machine.get("name"): 90 log.warning("Unable to run baseline processing module as we did " 91 "not find the name of the Virtual Machine.") 92 return 93 94 machine = machine["name"] 95 baseline = os.path.join(self.baseline_path, "%s.json" % machine) 96 97 # If this task has the baseline category then we're creating a new 98 # baseline report for a VM (and store it right away). 99 if self.task["category"] == "baseline": 100 self.store_baseline(machine, baseline) 101 return 102 103 if not os.path.exists(baseline): 104 log.info("Could not find a baseline report for machine '%s', " 105 "skipping it.", machine) 106 return 107 108 try: 109 self.baseline = json.load(open(baseline, "rb")) 110 except Exception as e: 111 log.warning("Baseline report for machine '%s' seems corrupted, " 112 "skipping baseline processing: %s.", machine, e) 113 return 114 115 results = {} 116 117 if "memory" in self.results: 118 results["memory"] = \ 119 self.memory(self.baseline["memory"], self.results["memory"]) 120 121 return results
122