def analysis_stop(self): G.dir_remove(self.local_path) # Stop our analysis self.mem_analysis.stop() del self.mem_analysis # Then stop data handlers self.data_handler.stop() self.rabbitmq.stop()
def analysis_start(self): """ Commands to execute when starting analysis. Once this returns the analysis will wait for commands from the user. NOTE: Any threads will continue execute until a stop command is received """ # Analysis is done after this function returns self.CONTINUE_EXECUTION = False # Extract some important variables volatility_profile = self.lophi_command.volatility_profile lophi_command = self.lophi_command machine = self.machine sample_doc_id = lophi_command.sample_doc_id db_analysis_id = lophi_command.db_analysis_id # Initialize our database DB_samples = DatastoreSamples(lophi_command.services_host) DB_analysis = DatastoreAnalysis(lophi_command.services_host) # Copy the sample to the ftp server temporarily so that the SUA can # download it # store the temp directory name local_path = DB_samples.copy_sample_to_ftp(sample_doc_id) remote_path = os.path.relpath(local_path, G.FTP_ROOT) lophi_command.ftp_info['dir'] = remote_path # Create a tmp directory tmp_dir = G.dir_create_tmp() # Keep retrying in case any step fails while True: # Make sure that our machine is in the state that we expect. # Reversion can fail, make sure we actually revert the disk! timestamps = [] print "* %s: Timestamp: %f"%(self.machine.config.name,time.time()) print "* %s: Resetting machine..."%self.machine.config.name reset_start = time.time() if not machine.machine_reset(): continue reset_stop = time.time() timestamps.append((reset_start, reset_stop)) # Start our machine up # print "* %s: Timestamp: %f"%(self.machine.config.name,time.time()) print "* %s: Powering on machine..."%self.machine.config.name boot_start = time.time() machine.power_on() if machine.type == G.MACHINE_TYPES.PHYSICAL: print "* %s: Ensuring that the disk sensor is up. (Bugfix)"%( self.machine.config.name) while True: time.sleep(5) if machine.disk.is_up(): break machine.power_off() time.sleep(5) machine.power_on() # Wait for the machine to appear on the network print "* %s: Timestamp: %f"%(self.machine.config.name, time.time()) print "* %s: Waiting for OS to boot..."%self.machine.config.name bad_disk_image = False for os_attempt in xrange(self.OS_BOOT_ATTEMPTS+1): if os_attempt == self.OS_BOOT_ATTEMPTS: bad_disk_image = True break start = time.time() os_timed_out = False while not self.machine.network_get_status(): time.sleep(1) if time.time() - start > self.OS_TIMEOUT: os_timed_out = True break # Did we timeout? if os_timed_out: logger.error("%s: OS boot timeout! (%d/%d)" % ( self.machine.config.name, os_attempt+1, self.OS_BOOT_ATTEMPTS)) self.machine.power_reset() continue else: break # Do we have a bad image on the disk? if bad_disk_image: logger.error("%s: Bad disk image! (Starting over)" % self.machine.config.name) continue boot_stop = time.time() timestamps.append((boot_start,boot_stop)) # Wait a bit before doing stuff (Allow the OS to finish booting print "* %s: Timestamp: %f"%(self.machine.config.name, time.time()) print "* %s: Waiting for the OS to stabilize" % \ self.machine.config.name osstable_start = time.time() time.sleep(self.OS_BOOT_WAIT) osstable_stop = time.time() timestamps.append((osstable_start,osstable_stop)) # Start our disk capturing # print "* %s: Timestamp: %f"%(self.machine.config.name,time.time()) print "* %s: Starting disk capture..."%self.machine.config.name disk_pcap_file = os.path.join(tmp_dir,"sut_disk_io.dcap") disk_queue = multiprocessing.Queue() dcap_writer = CaptureWriter(disk_pcap_file, disk_queue) disk_tap = DiskCaptureEngine(machine, disk_queue) # Start disk capture disk_tap.start() dcap_writer.start() # Send keypresses to download binary print "* %s: Timestamp: %f"%(self.machine.config.name,time.time()) print "* %s: Sending keypresses..."%self.machine.config.name # Get our keypress generator kpg = machine.keypress_get_generator() # Check ftp info, and send commands to execute malware keypress_start = time.time() if lophi_command.ftp_info['ip'] is not None and \ lophi_command.ftp_info['dir'] is not None: print "* %s: Executing ftp commands..."%self.machine.config.name ftp_script = kpg.get_ftp_script(volatility_profile, lophi_command.ftp_info, hit_enter=False) machine.keypress_send(ftp_script) else: print "* %s:* No ftp info given."%self.machine.config.name keypress_stop = time.time() timestamps.append((keypress_start,keypress_stop)) # At this the point machine has the binary on it, and is one # ENTER key away from executing it. # Dump our memory print "* %s: Timestamp: %f"%(self.machine.config.name,time.time()) print "* %s: Dumping memory (Clean)..."%self.machine.config.name memory_file_clean = os.path.join(tmp_dir,"sut_memory_clean.mfd") cleandump_start = time.time() if not machine.memory_dump(memory_file_clean): # Stop everything, and start over. dcap_writer.stop() disk_tap.stop() logger.error("%s: Memory Dump Failed! (Starting over)"% self.machine.config.name) continue cleandump_stop = time.time() timestamps.append((cleandump_start, cleandump_stop)) # Compress clean file memory_file_clean_gz = os.path.join(tmp_dir, "sut_memory_clean.tar.gz") memory_file_clean_tmp = memory_file_clean+".tmp" shutil.copy(memory_file_clean, memory_file_clean_tmp) memory_clean_compress = multiprocessing.Process( target=self.compress_file, args=(memory_file_clean, memory_file_clean_gz)) memory_clean_compress.start() timestamps.append((0, 0)) # Place holder for mem compression # Start our network capturing # Setup a capture thread and thread to write the pcap print "* %s: Timestamp: %f"%(self.machine.config.name,time.time()) print "* %s: Starting network capture"%self.machine.config.name network_pcap_file = os.path.join(tmp_dir,"sut_network.pcap") network_queue = multiprocessing.Queue() pcap_writer = PcapWriter(network_pcap_file, network_queue) net_tap = NetworkCaptureEngine(machine, network_queue) # Start network capture pcap_writer.start() net_tap.start() print "* %s: Getting a list of current buttons" % \ self.machine.config.name start_time = time.time() # Start binary and click buttons try: # Initialize our button clicker instance on our clean mem. image vol_uri = "file://"+memory_file_clean_tmp bc = ButtonClicker(vol_uri, machine.config.volatility_profile, machine.memory_get_size(), machine.control) # Get our current button list cleanbuttons_start = time.time() bc.update_buttons() cleanbuttons_stop = time.time() timestamps.append((cleanbuttons_start, cleanbuttons_stop)) # # Start our binary! # print "* %s: Timestamp: %f"%(self.machine.config.name, time.time()) print "* %s: Running binary!"%self.machine.config.name machine.keypress_send(kpg.text_to_script("SPECIAL:RETURN")) # Start wiggling our mouse to emulate a human print "* %s: Wiggling mouse."%self.machine.config.name self.machine.control.mouse_wiggle(True) start_time = time.time() # Wait a bit for it to open executewait_start = time.time() time.sleep(60) executewait_stop = time.time() timestamps.append((executewait_start, executewait_stop)) # Take another memory dump print "* %s: Timestamp: %f"%(self.machine.config.name, time.time()) print "* %s: Dumping memory (Interim)..." % \ self.machine.config.name interimdump_start = time.time() if not machine.memory_dump(memory_file_clean_tmp): raise Exception("Bad memory read.") interimdump_stop = time.time() timestamps.append((interimdump_start,interimdump_stop)) # Let's take a screenshot screenshot1_start = time.time() try: print "* %s: Timestamp: %f"%(self.machine.config.name, time.time()) print "* %s: Taking a screenshot."%self.machine.config.name screenshot_file = os.path.join(tmp_dir,"sut_screenshot") screenshot_file = self.machine.screenshot( screenshot_file, vol_uri=vol_uri) DB_analysis.append_analysis_file(db_analysis_id, screenshot_file, "screenshot") except: import traceback traceback.print_exc() logger.error("Could not take a screenshot.") pass screenshot1_stop = time.time() timestamps.append((screenshot1_start, screenshot1_stop)) # Click any new buttons that appeared print "* %s: Timestamp: %f"%(self.machine.config.name, time.time()) print "* %s: Clicking buttons..."%self.machine.config.name dirtybuttons_start = time.time() clicked = bc.click_buttons(new_only=True) for c in clicked: print "* %s: Clicked: %s:%s"%(self.machine.config.name, c['process'],c['name']) dirtybuttons_stop = time.time() timestamps.append((dirtybuttons_start, dirtybuttons_stop)) # Clean up the file on disk os.remove(memory_file_clean_tmp) # Save which buttons that we clicked DB_analysis.update_analysis(db_analysis_id, "buttons_clicked", clicked) except: logger.error("%s: Failed to start binary and click buttons. " "(Starting over)"% self.machine.config.name) import traceback traceback.print_exc() self.machine.control.mouse_wiggle(False) dcap_writer.stop() disk_tap.stop() pcap_writer.stop() net_tap.stop() continue # Run binary for as long as we see fit sleep_time = self.MALWARE_EXECUTION_TIME-(time.time()-start_time) print "* %s: Timestamp: %f"%(self.machine.config.name,time.time()) executeend_start = time.time() if sleep_time > 0: print "* %s: Sleeping for %d seconds." % ( self.machine.config.name, sleep_time) time.sleep(sleep_time) executeend_stop = time.time() timestamps.append((executeend_start,executeend_stop)) # Dump our memory again print "* %s: Timestamp: %f"%(self.machine.config.name,time.time()) print "* %s: Dumping memory..."%self.machine.config.name memory_file_dirty = os.path.join(tmp_dir,"sut_memory_dirty.mfd") dirtydump_start = time.time() if not machine.memory_dump(memory_file_dirty): # Stop everything, and start over. self.machine.control.mouse_wiggle(False) dcap_writer.stop() disk_tap.stop() pcap_writer.stop() net_tap.stop() logger.error("%s: Memory Dump Failed! (Starting over)"% self.machine.config.name) continue dirtydump_stop = time.time() timestamps.append((dirtydump_start, dirtydump_stop)) # Let's take a screenshot screenshot2_start = time.time() try: print "* %s: Timestamp: %f"%(self.machine.config.name, time.time()) print "* %s: Taking a screenshot."%self.machine.config.name screenshot_file_final = os.path.join(tmp_dir, "sut_screenshot_final") vol_uri = "file://"+memory_file_dirty screenshot_file_final = self.machine.screenshot( screenshot_file_final, vol_uri=vol_uri) DB_analysis.append_analysis_file(db_analysis_id, screenshot_file_final, "screenshot_final") except: logger.error("Could not take a screenshot.") pass screenshot2_stop = time.time() timestamps.append((screenshot2_start, screenshot2_stop)) # Join our clean compression memory_clean_compress.join() memory_clean_compress.terminate() # Compress dirty file dirtycompress_start = time.time() memory_file_dirty_gz = os.path.join(tmp_dir, "sut_memory_dirty.tar.gz") self.compress_file(memory_file_dirty, memory_file_dirty_gz) dirtycompress_stop = time.time() timestamps.append((dirtycompress_start, dirtycompress_stop)) # Power down the machine (Will also flush disk caches) print "* %s: Timestamp: %f"%(self.machine.config.name, time.time()) print "* Shutting down machine." shutdown_start = time.time() self.machine.power_shutdown() # Wait for machine to power off start = time.time() offs= 0 while True: # power status status = self.machine.power_status() if status != G.SENSOR_CONTROL.POWER_STATUS.ON: offs += 1 else: offs = 0 # Make sure the machien is really off if offs > 3: # machine is powered off print "* Shutdown successful." break if time.time()-start > 60: print "* Shutdown failed." break shutdown_stop = time.time() timestamps.append((shutdown_start, shutdown_stop)) # Stop wiggeling our mouse self.machine.control.mouse_wiggle(False) # Stop Disk Capture dcap_writer.stop() disk_tap.stop() # Stop network capture pcap_writer.stop() net_tap.stop() storeresults_start = time.time() # Save all of our generated fields to the database print "* %s: Timestamp: %f"%(self.machine.config.name,time.time()) print "* %s: Storing results in database..." % \ self.machine.config.name DB_analysis.append_analysis_file(db_analysis_id, memory_file_clean_gz, "memory_dump_clean") DB_analysis.append_analysis_file(db_analysis_id, memory_file_dirty_gz, "memory_dump_dirty") # Save pcap and dcap files DB_analysis.append_analysis_file(db_analysis_id, network_pcap_file, "network_capture") DB_analysis.append_analysis_file(db_analysis_id, disk_pcap_file, "disk_capture") storeresults_stop = time.time() timestamps.append((storeresults_start, storeresults_stop)) # Clean up files on disk G.dir_remove(local_path) G.dir_remove(tmp_dir) print "* %s: Timestamp: %f"%(self.machine.config.name, time.time()) print "* %s: Done!"%self.machine.config.name print "** %s: Times "%self.machine.config.name, timestamps # Break out of our "try forever" loop break
def analysis_start(self): """ Commands to execute when starting analysis. Once this returns the analysis will wait for commands from the user. NOTE: Any threads will continue execute until a stop command is received """ # Analysis is done after this function returns self.CONTINUE_EXECUTION = False # Extract some important variables volatility_profile = self.lophi_command.volatility_profile lophi_command = self.lophi_command machine = self.machine sample_doc_id = lophi_command.sample_doc_id db_analysis_id = lophi_command.db_analysis_id # Initialize our database DB_samples = DatastoreSamples(lophi_command.services_host) DB_analysis = DatastoreAnalysis(lophi_command.services_host) # Copy the sample to the ftp server temporarily so that the SUA can # download it # store the temp directory name local_path = DB_samples.copy_sample_to_ftp(sample_doc_id) remote_path = os.path.relpath(local_path, G.FTP_ROOT) lophi_command.ftp_info['dir'] = remote_path # Create a tmp directory tmp_dir = G.dir_create_tmp() # Keep retrying in case any step fails while True: # Make sure that our machine is in the state that we expect. # Reversion can fail, make sure we actually revert the disk! timestamps = [] print "* %s: Timestamp: %f" % (self.machine.config.name, time.time()) print "* %s: Resetting machine..." % self.machine.config.name reset_start = time.time() if not machine.machine_reset(): continue reset_stop = time.time() timestamps.append((reset_start, reset_stop)) # Start our machine up # print "* %s: Timestamp: %f"%(self.machine.config.name,time.time()) print "* %s: Powering on machine..." % self.machine.config.name boot_start = time.time() machine.power_on() if machine.type == G.MACHINE_TYPES.PHYSICAL: print "* %s: Ensuring that the disk sensor is up. (Bugfix)" % ( self.machine.config.name) while True: time.sleep(5) if machine.disk.is_up(): break machine.power_off() time.sleep(5) machine.power_on() # Wait for the machine to appear on the network print "* %s: Timestamp: %f" % (self.machine.config.name, time.time()) print "* %s: Waiting for OS to boot..." % self.machine.config.name bad_disk_image = False for os_attempt in xrange(self.OS_BOOT_ATTEMPTS + 1): if os_attempt == self.OS_BOOT_ATTEMPTS: bad_disk_image = True break start = time.time() os_timed_out = False while not self.machine.network_get_status(): time.sleep(1) if time.time() - start > self.OS_TIMEOUT: os_timed_out = True break # Did we timeout? if os_timed_out: logger.error("%s: OS boot timeout! (%d/%d)" % (self.machine.config.name, os_attempt + 1, self.OS_BOOT_ATTEMPTS)) self.machine.power_reset() continue else: break # Do we have a bad image on the disk? if bad_disk_image: logger.error("%s: Bad disk image! (Starting over)" % self.machine.config.name) continue boot_stop = time.time() timestamps.append((boot_start, boot_stop)) # Wait a bit before doing stuff (Allow the OS to finish booting print "* %s: Timestamp: %f" % (self.machine.config.name, time.time()) print "* %s: Waiting for the OS to stabilize" % \ self.machine.config.name osstable_start = time.time() time.sleep(self.OS_BOOT_WAIT) osstable_stop = time.time() timestamps.append((osstable_start, osstable_stop)) # Start our disk capturing # print "* %s: Timestamp: %f"%(self.machine.config.name,time.time()) print "* %s: Starting disk capture..." % self.machine.config.name disk_pcap_file = os.path.join(tmp_dir, "sut_disk_io.dcap") disk_queue = multiprocessing.Queue() dcap_writer = CaptureWriter(disk_pcap_file, disk_queue) disk_tap = DiskCaptureEngine(machine, disk_queue) # Start disk capture disk_tap.start() dcap_writer.start() # Send keypresses to download binary print "* %s: Timestamp: %f" % (self.machine.config.name, time.time()) print "* %s: Sending keypresses..." % self.machine.config.name # Get our keypress generator kpg = machine.keypress_get_generator() # Check ftp info, and send commands to execute malware keypress_start = time.time() if lophi_command.ftp_info['ip'] is not None and \ lophi_command.ftp_info['dir'] is not None: print "* %s: Executing ftp commands..." % self.machine.config.name ftp_script = kpg.get_ftp_script(volatility_profile, lophi_command.ftp_info, hit_enter=False) machine.keypress_send(ftp_script) else: print "* %s:* No ftp info given." % self.machine.config.name keypress_stop = time.time() timestamps.append((keypress_start, keypress_stop)) # At this the point machine has the binary on it, and is one # ENTER key away from executing it. # Dump our memory print "* %s: Timestamp: %f" % (self.machine.config.name, time.time()) print "* %s: Dumping memory (Clean)..." % self.machine.config.name memory_file_clean = os.path.join(tmp_dir, "sut_memory_clean.mfd") cleandump_start = time.time() if not machine.memory_dump(memory_file_clean): # Stop everything, and start over. dcap_writer.stop() disk_tap.stop() logger.error("%s: Memory Dump Failed! (Starting over)" % self.machine.config.name) continue cleandump_stop = time.time() timestamps.append((cleandump_start, cleandump_stop)) # Compress clean file memory_file_clean_gz = os.path.join(tmp_dir, "sut_memory_clean.tar.gz") memory_file_clean_tmp = memory_file_clean + ".tmp" shutil.copy(memory_file_clean, memory_file_clean_tmp) memory_clean_compress = multiprocessing.Process( target=self.compress_file, args=(memory_file_clean, memory_file_clean_gz)) memory_clean_compress.start() timestamps.append((0, 0)) # Place holder for mem compression # Start our network capturing # Setup a capture thread and thread to write the pcap print "* %s: Timestamp: %f" % (self.machine.config.name, time.time()) print "* %s: Starting network capture" % self.machine.config.name network_pcap_file = os.path.join(tmp_dir, "sut_network.pcap") network_queue = multiprocessing.Queue() pcap_writer = PcapWriter(network_pcap_file, network_queue) net_tap = NetworkCaptureEngine(machine, network_queue) # Start network capture pcap_writer.start() net_tap.start() print "* %s: Getting a list of current buttons" % \ self.machine.config.name start_time = time.time() # Start binary and click buttons try: # Initialize our button clicker instance on our clean mem. image vol_uri = "file://" + memory_file_clean_tmp bc = ButtonClicker(vol_uri, machine.config.volatility_profile, machine.memory_get_size(), machine.control) # Get our current button list cleanbuttons_start = time.time() bc.update_buttons() cleanbuttons_stop = time.time() timestamps.append((cleanbuttons_start, cleanbuttons_stop)) # # Start our binary! # print "* %s: Timestamp: %f" % (self.machine.config.name, time.time()) print "* %s: Running binary!" % self.machine.config.name machine.keypress_send(kpg.text_to_script("SPECIAL:RETURN")) # Start wiggling our mouse to emulate a human print "* %s: Wiggling mouse." % self.machine.config.name self.machine.control.mouse_wiggle(True) start_time = time.time() # Wait a bit for it to open executewait_start = time.time() time.sleep(60) executewait_stop = time.time() timestamps.append((executewait_start, executewait_stop)) # Take another memory dump print "* %s: Timestamp: %f" % (self.machine.config.name, time.time()) print "* %s: Dumping memory (Interim)..." % \ self.machine.config.name interimdump_start = time.time() if not machine.memory_dump(memory_file_clean_tmp): raise Exception("Bad memory read.") interimdump_stop = time.time() timestamps.append((interimdump_start, interimdump_stop)) # Let's take a screenshot screenshot1_start = time.time() try: print "* %s: Timestamp: %f" % (self.machine.config.name, time.time()) print "* %s: Taking a screenshot." % self.machine.config.name screenshot_file = os.path.join(tmp_dir, "sut_screenshot") screenshot_file = self.machine.screenshot(screenshot_file, vol_uri=vol_uri) DB_analysis.append_analysis_file(db_analysis_id, screenshot_file, "screenshot") except: import traceback traceback.print_exc() logger.error("Could not take a screenshot.") pass screenshot1_stop = time.time() timestamps.append((screenshot1_start, screenshot1_stop)) # Click any new buttons that appeared print "* %s: Timestamp: %f" % (self.machine.config.name, time.time()) print "* %s: Clicking buttons..." % self.machine.config.name dirtybuttons_start = time.time() clicked = bc.click_buttons(new_only=True) for c in clicked: print "* %s: Clicked: %s:%s" % (self.machine.config.name, c['process'], c['name']) dirtybuttons_stop = time.time() timestamps.append((dirtybuttons_start, dirtybuttons_stop)) # Clean up the file on disk os.remove(memory_file_clean_tmp) # Save which buttons that we clicked DB_analysis.update_analysis(db_analysis_id, "buttons_clicked", clicked) except: logger.error("%s: Failed to start binary and click buttons. " "(Starting over)" % self.machine.config.name) import traceback traceback.print_exc() self.machine.control.mouse_wiggle(False) dcap_writer.stop() disk_tap.stop() pcap_writer.stop() net_tap.stop() continue # Run binary for as long as we see fit sleep_time = self.MALWARE_EXECUTION_TIME - (time.time() - start_time) print "* %s: Timestamp: %f" % (self.machine.config.name, time.time()) executeend_start = time.time() if sleep_time > 0: print "* %s: Sleeping for %d seconds." % ( self.machine.config.name, sleep_time) time.sleep(sleep_time) executeend_stop = time.time() timestamps.append((executeend_start, executeend_stop)) # Dump our memory again print "* %s: Timestamp: %f" % (self.machine.config.name, time.time()) print "* %s: Dumping memory..." % self.machine.config.name memory_file_dirty = os.path.join(tmp_dir, "sut_memory_dirty.mfd") dirtydump_start = time.time() if not machine.memory_dump(memory_file_dirty): # Stop everything, and start over. self.machine.control.mouse_wiggle(False) dcap_writer.stop() disk_tap.stop() pcap_writer.stop() net_tap.stop() logger.error("%s: Memory Dump Failed! (Starting over)" % self.machine.config.name) continue dirtydump_stop = time.time() timestamps.append((dirtydump_start, dirtydump_stop)) # Let's take a screenshot screenshot2_start = time.time() try: print "* %s: Timestamp: %f" % (self.machine.config.name, time.time()) print "* %s: Taking a screenshot." % self.machine.config.name screenshot_file_final = os.path.join(tmp_dir, "sut_screenshot_final") vol_uri = "file://" + memory_file_dirty screenshot_file_final = self.machine.screenshot( screenshot_file_final, vol_uri=vol_uri) DB_analysis.append_analysis_file(db_analysis_id, screenshot_file_final, "screenshot_final") except: logger.error("Could not take a screenshot.") pass screenshot2_stop = time.time() timestamps.append((screenshot2_start, screenshot2_stop)) # Join our clean compression memory_clean_compress.join() memory_clean_compress.terminate() # Compress dirty file dirtycompress_start = time.time() memory_file_dirty_gz = os.path.join(tmp_dir, "sut_memory_dirty.tar.gz") self.compress_file(memory_file_dirty, memory_file_dirty_gz) dirtycompress_stop = time.time() timestamps.append((dirtycompress_start, dirtycompress_stop)) # Power down the machine (Will also flush disk caches) print "* %s: Timestamp: %f" % (self.machine.config.name, time.time()) print "* Shutting down machine." shutdown_start = time.time() self.machine.power_shutdown() # Wait for machine to power off start = time.time() offs = 0 while True: # power status status = self.machine.power_status() if status != G.SENSOR_CONTROL.POWER_STATUS.ON: offs += 1 else: offs = 0 # Make sure the machien is really off if offs > 3: # machine is powered off print "* Shutdown successful." break if time.time() - start > 60: print "* Shutdown failed." break shutdown_stop = time.time() timestamps.append((shutdown_start, shutdown_stop)) # Stop wiggeling our mouse self.machine.control.mouse_wiggle(False) # Stop Disk Capture dcap_writer.stop() disk_tap.stop() # Stop network capture pcap_writer.stop() net_tap.stop() storeresults_start = time.time() # Save all of our generated fields to the database print "* %s: Timestamp: %f" % (self.machine.config.name, time.time()) print "* %s: Storing results in database..." % \ self.machine.config.name DB_analysis.append_analysis_file(db_analysis_id, memory_file_clean_gz, "memory_dump_clean") DB_analysis.append_analysis_file(db_analysis_id, memory_file_dirty_gz, "memory_dump_dirty") # Save pcap and dcap files DB_analysis.append_analysis_file(db_analysis_id, network_pcap_file, "network_capture") DB_analysis.append_analysis_file(db_analysis_id, disk_pcap_file, "disk_capture") storeresults_stop = time.time() timestamps.append((storeresults_start, storeresults_stop)) # Clean up files on disk G.dir_remove(local_path) G.dir_remove(tmp_dir) print "* %s: Timestamp: %f" % (self.machine.config.name, time.time()) print "* %s: Done!" % self.machine.config.name print "** %s: Times " % self.machine.config.name, timestamps # Break out of our "try forever" loop break
def analysis_start(self): """ Commands to execute when starting analysis. Once this returns the analysis will wait for commands from the user. NOTE: Any threads will continue execute until a stop command is received """ # Analysis is done after this function returns self.CONTINUE_EXECUTION = False # Extract some important variables volatility_profile = self.lophi_command.volatility_profile lophi_command = self.lophi_command machine = self.machine sample_doc_id = lophi_command.sample_doc_id db_analysis_id = lophi_command.db_analysis_id # Initialize our database DB_samples = DatastoreSamples(self.services_host) DB_analysis = DatastoreAnalysis(self.services_host) # Copy the sample to the ftp server temporarily so that the SUA can download it # store the temp directory name # 'sc stop rootkit','sc delete rootkit', setup_commands=['start taskmgr'] local_path = DB_samples.copy_sample_to_ftp(sample_doc_id,commands=setup_commands) remote_path = os.path.relpath(local_path, G.FTP_ROOT) lophi_command.ftp_info['dir'] = remote_path # Keep retrying in case any step fails while True: # Make sure that our machine is in the state that we expect. # Reversion can fail, make sure we actually revert the disk! print "* Resetting machine..." machine.power_off() # Start our machine up print "* Powering on machine..." machine.power_on() # Wait for the machine to appear on the network print "* Waiting for OS to boot..." start = time.time() os_timed_out = False while not self.machine.network_get_status(): time.sleep(1) if time.time() - start > self.OS_TIMEOUT: os_timed_out = True break # Did we timeout? if os_timed_out: print "** OS boot timeout! (Starting over)" continue # Create a queue and data handler # This enables us to do many to many data flows self.data_queue = multiprocessing.Queue() self.data_handler = DataHandler(self.data_queue) # RabbitMQ queue name self.rabbitmq = LOPHI_RabbitMQ_Producer(self.services_host, self.data_handler.new_queue(), G.RabbitMQ.SENSOR, exchange_type=G.RabbitMQ.TYPE_FANOUT, exchange=G.RabbitMQ.EXCHANGE_FANOUT) # Start data paths self.data_handler.start() self.rabbitmq.start() # Memory Analysis print "Starting memory analysis..." self.mem_analysis = MemoryAnalysisEngine(self.machine, self.data_queue, plugins=['pslist','ssdt']) self.mem_analysis.start() # Wait a bit before doing stuff (Allow the OS to finish booting print "* Waiting for the OS to stabilize..." time.sleep(self.OS_BOOT_WAIT) # Send keypresses to download binary print "* Sending keypresses..." # Get our keypress generator kpg = machine.keypress_get_generator() # Check ftp info, and send commands to execute malware if lophi_command.ftp_info['ip'] is not None and lophi_command.ftp_info['dir'] is not None: print "* Executing ftp commands..." ftp_script = kpg.get_ftp_script(volatility_profile, lophi_command.ftp_info) machine.keypress_send(ftp_script) else: print "** No ftp info given." # At this the point machine has the binary on it, and is one ENTER key # away from executing it. # Run binary for as long as we see fit time.sleep(self.MALWARE_EXECUTION_TIME) # Stop our analysis self.mem_analysis.stop() del self.mem_analysis # Then stop data handlers self.data_handler.stop() self.rabbitmq.stop() # Wait for things to clean up time.sleep(10) # Turn the machine off print "* Shutting down machine..." self.machine.power_shutdown() time.sleep(30) print "* Done!" # Break out of our "try forever" loop # break # Clean up files on disk G.dir_remove(local_path)