def negotiate_protocol(self): # read until newline buf = self.read_newline() if "NETLOG" in buf: self.protocol = NetlogParser(self) elif "FILE" in buf: self.protocol = FileUpload(self) elif "LOG" in buf: self.protocol = LogHandler(self) else: raise CuckooOperationalError( "Netlog failure, unknown protocol requested.")
def parse_first_and_reset(self): self.fd = open(self._log_path, "rb") self.parser = NetlogParser(self) self.parser.read_next_message() self.fd.seek(0)
class ParseProcessLog(list): """Parses process log file.""" def __init__(self, log_path): """@param log_path: log file path.""" self._log_path = log_path self.fd = None self.parser = None self.process_id = None self.process_name = None self.parent_id = None self.first_seen = None self.calls = self self.lastcall = None if os.path.exists(log_path) and os.stat(log_path).st_size > 0: self.parse_first_and_reset() def parse_first_and_reset(self): self.fd = open(self._log_path, "rb") self.parser = NetlogParser(self) self.parser.read_next_message() self.fd.seek(0) def read(self, length): if length == 0: return b'' buf = self.fd.read(length) if not buf or len(buf) != length: raise EOFError() return buf def __iter__(self): #log.debug('iter called by this guy: {0}'.format(inspect.stack()[1])) return self def __getitem__(self, key): return getattr(self, key) def __repr__(self): return 'ParseProcessLog {0}'.format(self._log_path) def __nonzero__(self): return True def compare_calls(self, a, b): """Compare two calls for equality. Same implementation as before netlog. @param a: call a @param b: call b @return: True if a == b else False """ if a["api"] == b["api"] and \ a["status"] == b["status"] and \ a["arguments"] == b["arguments"] and \ a["return"] == b["return"]: return True return False def wait_for_lastcall(self): while not self.lastcall: r = None try: r = self.parser.read_next_message() except EOFError: return False if not r: return False return True def next(self): x = self.wait_for_lastcall() if not x: self.fd.seek(0) raise StopIteration() nextcall, self.lastcall = self.lastcall, None x = self.wait_for_lastcall() while self.lastcall and self.compare_calls(nextcall, self.lastcall): nextcall['repeated'] += 1 self.lastcall = None x = self.wait_for_lastcall() return nextcall def log_process(self, context, timestring, pid, ppid, modulepath, procname): self.process_id, self.parent_id, self.process_name = pid, ppid, procname self.first_seen = timestring def log_thread(self, context, pid): pass def log_call(self, context, apiname, modulename, arguments): apiindex, status, returnval, tid, timediff = context current_time = self.first_seen + datetime.timedelta(0,0, timediff*1000) timestring = logtime(current_time) self.lastcall = self._parse([timestring, tid, modulename, apiname, status, returnval] + arguments) def _parse(self, row): """Parse log row. @param row: row data. @return: parsed information dict. """ call = {} arguments = [] try: timestamp = row[0] # Timestamp of current API call invocation. thread_id = row[1] # Thread ID. category = row[2] # Win32 function category. api_name = row[3] # Name of the Windows API. status_value = row[4] # Success or Failure? return_value = row[5] # Value returned by the function. except IndexError as e: log.debug("Unable to parse process log row: %s", e) return None # Now walk through the remaining columns, which will contain API # arguments. for index in range(6, len(row)): argument = {} # Split the argument name with its value based on the separator. try: (arg_name, arg_value) = row[index] except ValueError as e: log.debug("Unable to parse analysis row argument (row=%s): %s", row[index], e) continue argument["name"] = arg_name argument["value"] = convert_to_printable(str(arg_value)).lstrip("\\??\\") arguments.append(argument) call["timestamp"] = timestamp call["thread_id"] = str(thread_id) call["category"] = category call["api"] = api_name call["status"] = bool(int(status_value)) if isinstance(return_value, int): call["return"] = "0x%.08x" % return_value else: call["return"] = convert_to_printable(str(return_value)) call["arguments"] = arguments call["repeated"] = 0 return call
class ParseProcessLog(list): """Parses process log file.""" def __init__(self, log_path): """@param log_path: log file path.""" self._log_path = log_path self.fd = None self.parser = None self.process_id = None self.process_name = None self.parent_id = None self.first_seen = None self.calls = self self.lastcall = None if os.path.exists(log_path) and os.stat(log_path).st_size > 0: self.parse_first_and_reset() def parse_first_and_reset(self): self.fd = open(self._log_path, "rb") self.parser = NetlogParser(self) self.parser.read_next_message() self.fd.seek(0) def read(self, length): if length == 0: return b'' buf = self.fd.read(length) if not buf or len(buf) != length: raise EOFError() return buf def __iter__(self): #log.debug('iter called by this guy: {0}'.format(inspect.stack()[1])) return self def __getitem__(self, key): return getattr(self, key) def __repr__(self): return 'ParseProcessLog {0}'.format(self._log_path) def __nonzero__(self): return True def compare_calls(self, a, b): """Compare two calls for equality. Same implementation as before netlog. @param a: call a @param b: call b @return: True if a == b else False """ if a["api"] == b["api"] and \ a["status"] == b["status"] and \ a["arguments"] == b["arguments"] and \ a["return"] == b["return"]: return True return False def wait_for_lastcall(self): while not self.lastcall: r = None try: r = self.parser.read_next_message() except EOFError: return False if not r: return False return True def next(self): x = self.wait_for_lastcall() if not x: self.fd.seek(0) raise StopIteration() nextcall, self.lastcall = self.lastcall, None x = self.wait_for_lastcall() while self.lastcall and self.compare_calls(nextcall, self.lastcall): nextcall['repeated'] += 1 self.lastcall = None x = self.wait_for_lastcall() return nextcall def log_process(self, context, timestring, pid, ppid, modulepath, procname): self.process_id, self.parent_id, self.process_name = pid, ppid, procname self.first_seen = timestring def log_thread(self, context, pid): pass def log_call(self, context, apiname, modulename, arguments): apiindex, status, returnval, tid, timediff = context current_time = self.first_seen + datetime.timedelta( 0, 0, timediff * 1000) timestring = logtime(current_time) self.lastcall = self._parse( [timestring, tid, modulename, apiname, status, returnval] + arguments) def _parse(self, row): """Parse log row. @param row: row data. @return: parsed information dict. """ call = {} arguments = [] try: timestamp = row[0] # Timestamp of current API call invocation. thread_id = row[1] # Thread ID. category = row[2] # Win32 function category. api_name = row[3] # Name of the Windows API. status_value = row[4] # Success or Failure? return_value = row[5] # Value returned by the function. except IndexError as e: log.debug("Unable to parse process log row: %s", e) return None # Now walk through the remaining columns, which will contain API # arguments. for index in range(6, len(row)): argument = {} # Split the argument name with its value based on the separator. try: (arg_name, arg_value) = row[index] except ValueError as e: log.debug("Unable to parse analysis row argument (row=%s): %s", row[index], e) continue argument["name"] = arg_name argument["value"] = convert_to_printable( str(arg_value)).lstrip("\\??\\") arguments.append(argument) call["timestamp"] = timestamp call["thread_id"] = str(thread_id) call["category"] = category call["api"] = api_name call["status"] = bool(int(status_value)) if isinstance(return_value, int): call["return"] = "0x%.08x" % return_value else: call["return"] = convert_to_printable(str(return_value)) call["arguments"] = arguments call["repeated"] = 0 return call