def start_analysis(self, options, monitor): """Start analysis. @param options: options. @return: operation status. """ # TODO Deal with unicode URLs, should probably try URL encoding. # Unicode files are being taken care of. self.timeout = options["timeout"] + config("cuckoo:timeouts:critical") url = "http://{0}:{1}".format(self.ip, CUCKOO_GUEST_PORT) self.server = TimeoutServer(url, allow_none=True, timeout=self.timeout) try: # Wait for the agent to respond. This is done to check the # availability of the agent and verify that it's ready to receive # data. self.wait(CUCKOO_GUEST_INIT) if not self.do_run: return # Invoke the upload of the analyzer to the guest. self.upload_analyzer(monitor) # Give the analysis options to the guest, so it can generate the # analysis.conf inside the guest. try: self.server.add_config(options) except: raise CuckooGuestError( "%s: unable to upload config to analysis machine" % self.id) # If the target of the analysis is a file, upload it to the guest. if options["category"] in ("file", "archive"): try: file_data = open(options["target"], "rb").read() except (IOError, OSError) as e: raise CuckooGuestError("Unable to read %s, error: %s" % (options["target"], e)) data = xmlrpclib.Binary(file_data) try: self.server.add_malware(data, options["file_name"]) except Exception as e: raise CuckooGuestError( "#%s: unable to upload malware to analysis " "machine: %s" % (self.id, e)) # Launch the analyzer. pid = self.server.execute() log.debug("%s: analyzer started with PID %d", self.id, pid) # If something goes wrong when establishing the connection, raise an # exception and abort the analysis. except (socket.timeout, socket.error): raise CuckooGuestError( "%s: guest communication timeout, check networking or try " "to increase timeout" % self.id)
def wait_for_completion(self): if self.is_old: self.old.wait_for_completion() return end = time.time() + self.timeout while db.guest_get_status(self.task_id) == "running": log.debug("%s: analysis still processing", self.vmid) time.sleep(1) # If the analysis hits the critical timeout, just return straight # away and try to recover the analysis results from the guest. if time.time() > end: raise CuckooGuestError("The analysis hit the critical timeout, terminating.") try: status = self.get("/status", timeout=5).json() except Exception as e: log.info("Virtual Machine /status failed (%r)", e) # this might fail due to timeouts or just temporary network issues # thus we don't want to abort the analysis just yet and wait for things to # recover continue if status["status"] == "complete": log.info("%s: analysis completed successfully", self.vmid) return elif status["status"] == "exception": log.warning( "%s: analysis caught an exception\n%s", self.vmid, status["description"] ) return
def analyzer_zipfile(platform, monitor): """Creates the Zip file that is sent to the Guest.""" t = time.time() zip_data = io.BytesIO() zip_file = zipfile.ZipFile(zip_data, "w", zipfile.ZIP_STORED) # Select the proper analyzer's folder according to the operating # system associated with the current machine. root = cwd("analyzer", platform) root_len = len(os.path.abspath(root)) if not os.path.exists(root): log.error("No valid analyzer found at path: %s", root) raise CuckooGuestError( "No valid analyzer found for %s platform!" % platform ) # Walk through everything inside the analyzer's folder and write # them to the zip archive. for root, dirs, files in os.walk(root): archive_root = os.path.abspath(root)[root_len:] for name in files: path = os.path.join(root, name) archive_name = os.path.join(archive_root, name) zip_file.write(path, archive_name) # Include the chosen monitoring component. if platform == "windows": dirpath = cwd("monitor", monitor) # Sometimes we might get a file instead of a symbolic link, in that # case we follow the semi-"symbolic link" manually. if os.path.isfile(dirpath): monitor = os.path.basename(open(dirpath, "rb").read().strip()) dirpath = cwd("monitor", monitor) for name in os.listdir(dirpath): path = os.path.join(dirpath, name) archive_name = os.path.join("/bin", name) zip_file.write(path, archive_name) elif platform == "linux": pass #modify by xuyuu #stpdir = cwd("monitor_linux") #stpfile = os.path.join(stpdir, "strace.stp") #zip_file.write(stpfile) zip_file.close() data = zip_data.getvalue() if time.time() - t > 10: log.warning( "It took more than 10 seconds to build the Analyzer Zip for the " "Guest. This might be a serious performance penalty. Is your " "analyzer/windows/ directory bloated with unnecessary files?" ) return data
def analyzer_zipfile(platform, monitor): """Creates the Zip file that is sent to the Guest.""" t = time.time() zip_data = io.BytesIO() zip_file = zipfile.ZipFile(zip_data, "w", zipfile.ZIP_STORED) # Select the proper analyzer's folder according to the operating # system associated with the current machine. root = cwd("analyzer", platform) root_len = len(os.path.abspath(root)) if not os.path.exists(root): log.error("No valid analyzer found at path: %s", root) raise CuckooGuestError( "No valid analyzer found for %s platform!" % platform ) # Walk through everything inside the analyzer's folder and write # them to the zip archive. for root, dirs, files in os.walk(root): archive_root = os.path.abspath(root)[root_len:] for name in files: path = os.path.join(root, name) archive_name = os.path.join(archive_root, name) zip_file.write(path, archive_name) # Include the chosen monitoring component and any additional files. if platform == "windows": dirpath = cwd("monitor", monitor) # Generally speaking we should no longer be getting symbolic links for # "latest" anymore, so in the case of a file; follow it. if os.path.isfile(dirpath): monitor = os.path.basename(open(dirpath, "rb").read().strip()) dirpath = cwd("monitor", monitor) for name in os.listdir(dirpath): zip_file.write( os.path.join(dirpath, name), os.path.join("bin", name) ) # Dump compiled "dumpmem" Yara rules for zer0m0n usage. zip_file.write(cwd("stuff", "dumpmem.yarac"), "bin/rules.yarac") zip_file.close() data = zip_data.getvalue() if time.time() - t > 10: log.warning( "It took more than 10 seconds to build the Analyzer Zip for the " "Guest. This might be a serious performance penalty. Is your " "analyzer/windows/ directory bloated with unnecessary files?" ) return data
def wait_for_completion(self): """Wait for analysis completion. @return: operation status. """ log.debug("%s: waiting for completion", self.id) end = time.time() + self.timeout self.server._set_timeout(self.timeout) while db.guest_get_status(self.task_id) == "running": time.sleep(1) # If the analysis hits the critical timeout, just return straight # away and try to recover the analysis results from the guest. if time.time() > end: raise CuckooGuestError( "The analysis hit the critical timeout, terminating." ) try: status = self.server.get_status() except Exception as e: log.debug("%s: error retrieving status: %s", self.id, e) continue # React according to the returned status. if status == CUCKOO_GUEST_COMPLETED: log.info("%s: analysis completed successfully", self.id) break elif status == CUCKOO_GUEST_FAILED: error = self.server.get_error() raise CuckooGuestError( "Analysis failed: %s" % (error or "unknown error") ) else: log.debug("%s: analysis not completed yet (status=%s)", self.id, status) self.server._set_timeout(None)
def post(self, method, *args, **kwargs): """Simple wrapper around requests.post().""" url = "http://%s:%s%s" % (self.ipaddr, self.port, method) session = requests.Session() session.trust_env = False session.proxies = None try: r = session.post(url, *args, **kwargs) except requests.ConnectionError: raise CuckooGuestError( "Cuckoo Agent failed without error status, please try " "upgrading to the latest version of agent.py (>= 0.10) and " "notify us if the issue persists.") r.raise_for_status() return r
def upload_analyzer(self, monitor): """Upload analyzer to guest. @return: operation status. """ zip_data = analyzer_zipfile(self.platform, monitor) log.debug( "Uploading analyzer to guest (id=%s, ip=%s, monitor=%s, size=%d)", self.id, self.ip, monitor, len(zip_data)) # Send the zip containing the analyzer to the agent running inside # the guest. try: self.server.add_analyzer(xmlrpclib.Binary(zip_data)) except socket.timeout: raise CuckooGuestError("{0}: guest communication timeout: unable " "to upload agent, check networking or try " "to increase timeout".format(self.id))