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

Source Code for Module modules.processing.platform.linux

  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 os 
  7  import logging 
  8  import datetime 
  9  import re 
 10   
 11  import dateutil.parser 
 12   
 13  from lib.cuckoo.common.abstracts import BehaviorHandler 
 14   
 15  log = logging.getLogger(__name__) 
 16   
17 -class FilteredProcessLog(list):
18 - def __init__(self, eventstream, **kwfilters):
19 self.eventstream = eventstream 20 self.kwfilters = kwfilters
21
22 - def __iter__(self):
23 for event in self.eventstream: 24 for k, v in self.kwfilters.items(): 25 if event[k] != v: 26 continue 27 28 del event["type"] 29 yield event
30
31 - def __nonzero__(self):
32 return True
33
34 -class LinuxSystemTap(BehaviorHandler):
35 """Parses systemtap generated plaintext logs (see data/strace.stp).""" 36 37 key = "processes" 38
39 - def __init__(self, *args, **kwargs):
40 super(LinuxSystemTap, self).__init__(*args, **kwargs) 41 42 self.processes = [] 43 self.pids_seen = set() 44 self.forkmap = {} 45 self.matched = False 46 47 self._check_for_probelkm()
48
49 - def _check_for_probelkm(self):
50 path_lkm = os.path.join(self.analysis.logs_path, "all.lkm") 51 if os.path.exists(path_lkm): 52 lines = open(path_lkm).readlines() 53 54 forks = [re.findall("task (\d+)@0x[0-9a-f]+ forked to (\d+)@0x[0-9a-f]+", line) for line in lines] 55 self.forkmap = dict((j, i) for i, j in reduce(lambda x, y: x+y, forks, []))
56 57 # self.results["source"].append("probelkm") 58
59 - def handles_path(self, path):
60 if path.endswith(".stap"): 61 self.matched = True 62 return True
63
64 - def parse(self, path):
65 parser = StapParser(open(path)) 66 67 for event in parser: 68 pid = event["pid"] 69 if pid not in self.pids_seen: 70 self.pids_seen.add(pid) 71 ppid = self.forkmap.get(pid, -1) 72 73 process = { 74 "pid": pid, 75 "ppid": ppid, 76 "process_name": event["process_name"], 77 "first_seen": event["time"], 78 } 79 80 # create a process event as we don't have those with linux+systemtap 81 pevent = dict(process) 82 pevent["type"] = "process" 83 yield pevent 84 85 process["calls"] = FilteredProcessLog(parser, pid=pid) 86 self.processes.append(process) 87 88 yield event
89
90 - def run(self):
91 if not self.matched: 92 return 93 94 self.processes.sort(key=lambda process: process["first_seen"]) 95 return self.processes
96
97 -class StapParser(object):
98 """Handle .stap logs from the Linux analyzer.""" 99
100 - def __init__(self, fd):
101 self.fd = fd
102
103 - def __iter__(self):
104 self.fd.seek(0) 105 106 for line in self.fd: 107 # 'Thu May 7 14:58:43 2015.390178 python@7f798cb95240[2114] close(6) = 0\n' 108 # datetime is 31 characters 109 datetimepart, rest = line[:31], line[32:] 110 111 # incredibly sophisticated date time handling 112 dtms = datetime.timedelta(0, 0, int(datetimepart.split(".", 1)[1])) 113 dt = dateutil.parser.parse(datetimepart.split(".", 1)[0]) + dtms 114 115 parts = re.match("^(.+)@([a-f0-9]+)\[(\d+)\] (\w+)\((.*)\) = (\S+){0,1}\s{0,1}(\(\w+\)){0,1}$", rest) 116 if not parts: 117 log.warning("Could not parse syscall trace line: %s", line) 118 continue 119 120 pname, ip, pid, fn, arguments, retval, ecode = parts.groups() 121 argsplit = arguments.split(", ") 122 arguments = dict(("p%u" % pos, argsplit[pos]) for pos in range(len(argsplit))) 123 124 pid = int(pid) if pid.isdigit() else -1 125 126 yield { 127 "time": dt, "process_name": pname, "pid": pid, 128 "instruction_pointer": ip, "api": fn, "arguments": arguments, 129 "return_value": retval, "status": ecode, 130 "type": "apicall", "raw": line, 131 }
132