Advertisement
opexxx

agent.py

Mar 26th, 2015
366
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 6.24 KB | None | 0 0
  1. # Copyright (C) 2010-2014 Cuckoo Foundation.
  2. # This file is part of Cuckoo Sandbox - http://www.cuckoosandbox.org
  3. # See the file 'docs/LICENSE' for copying permission.
  4.  
  5. import os
  6. import sys
  7. import time
  8. import socket
  9. import string
  10. import random
  11. import platform
  12. import subprocess
  13. import ConfigParser
  14. from StringIO import StringIO
  15. from zipfile import ZipFile
  16. from SimpleXMLRPCServer import SimpleXMLRPCServer
  17.  
  18. BIND_IP = "0.0.0.0"
  19. BIND_PORT = 8000
  20.  
  21. STATUS_INIT = 0x0001
  22. STATUS_RUNNING = 0x0002
  23. STATUS_COMPLETED = 0x0003
  24. STATUS_FAILED = 0x0004
  25. CURRENT_STATUS = STATUS_INIT
  26.  
  27. ERROR_MESSAGE = ""
  28. ANALYZER_FOLDER = ""
  29. RESULTS_FOLDER = ""
  30.  
  31. class Agent:
  32.     """Cuckoo agent, it runs inside guest."""
  33.    
  34.     def __init__(self):
  35.         self.system = platform.system().lower()
  36.         self.analyzer_path = ""
  37.         self.analyzer_pid = 0
  38.  
  39.     def _initialize(self):
  40.         global ERROR_MESSAGE
  41.         global ANALYZER_FOLDER
  42.  
  43.         if not ANALYZER_FOLDER:
  44.             random.seed(time.time())
  45.             container = "".join(random.choice(string.ascii_lowercase) for x in range(random.randint(5, 10)))
  46.  
  47.             if self.system == "windows":
  48.                 system_drive = os.environ["SYSTEMDRIVE"] + os.sep
  49.                 ANALYZER_FOLDER = os.path.join(system_drive, container)
  50.             elif self.system == "linux" or self.system == "darwin":
  51.                 ANALYZER_FOLDER = os.path.join(os.environ["HOME"], container)
  52.             else:
  53.                 ERROR_MESSAGE = "Unable to identify operating system"
  54.                 return False
  55.  
  56.             try:
  57.                 os.makedirs(ANALYZER_FOLDER)
  58.             except OSError as e:
  59.                 ERROR_MESSAGE = e
  60.                 return False
  61.  
  62.         return True
  63.  
  64.     def get_status(self):
  65.         """Get current status.
  66.        @return: status.
  67.        """
  68.         return CURRENT_STATUS
  69.  
  70.     def get_error(self):
  71.         """Get error message.
  72.        @return: error message.
  73.        """
  74.         return str(ERROR_MESSAGE)
  75.  
  76.     def add_malware(self, data, name):
  77.         """Get analysis data.
  78.        @param data: analysis data.
  79.        @param name: file name.
  80.        @return: operation status.
  81.        """
  82.         global ERROR_MESSAGE
  83.         data = data.data
  84.  
  85.         if self.system == "windows":
  86.             root = os.environ["TEMP"]
  87.         elif self.system == "linux" or self.system == "darwin":
  88.             root = "/tmp"
  89.         else:
  90.             ERROR_MESSAGE = "Unable to write malware to disk because of " \
  91.                             "failed identification of the operating system"
  92.             return False
  93.  
  94.         file_path = os.path.join(root, name)
  95.  
  96.         try:
  97.             with open(file_path, "wb") as malware:
  98.                 malware.write(data)
  99.         except IOError as e:
  100.             ERROR_MESSAGE = "Unable to write malware to disk: {0}".format(e)
  101.             return False
  102.  
  103.         return True
  104.  
  105.     def add_config(self, options):
  106.         """Creates analysis.conf file from current analysis options.
  107.        @param options: current configuration options, dict format.
  108.        @return: operation status.
  109.        """
  110.         global ERROR_MESSAGE
  111.  
  112.         if type(options) != dict:
  113.             return False
  114.  
  115.         config = ConfigParser.RawConfigParser()
  116.         config.add_section("analysis")
  117.  
  118.         try:
  119.             for key, value in options.items():
  120.                 # Options can be UTF encoded.
  121.                 if isinstance(value, basestring):
  122.                     try:
  123.                         value = value.encode("utf-8")
  124.                     except UnicodeEncodeError:
  125.                         pass
  126.  
  127.                 config.set("analysis", key, value)
  128.  
  129.             config_path = os.path.join(ANALYZER_FOLDER, "analysis.conf")
  130.        
  131.             with open(config_path, "wb") as config_file:
  132.                 config.write(config_file)
  133.         except Exception as e:
  134.             ERROR_MESSAGE = str(e)
  135.             return False
  136.  
  137.         return True
  138.  
  139.     def add_analyzer(self, data):
  140.         """Add analyzer.
  141.        @param data: analyzer data.
  142.        @return: operation status.
  143.        """
  144.         data = data.data
  145.  
  146.         if not self._initialize():
  147.             return False
  148.  
  149.         try:
  150.             zip_data = StringIO()
  151.             zip_data.write(data)
  152.  
  153.             with ZipFile(zip_data, "r") as archive:
  154.                 archive.extractall(ANALYZER_FOLDER)
  155.         finally:
  156.             zip_data.close()
  157.  
  158.         self.analyzer_path = os.path.join(ANALYZER_FOLDER, "analyzer.py")
  159.  
  160.         return True
  161.  
  162.     def execute(self):
  163.         """Execute analysis.
  164.        @return: analyzer PID.
  165.        """
  166.         global ERROR_MESSAGE
  167.         global CURRENT_STATUS
  168.  
  169.         if not self.analyzer_path or not os.path.exists(self.analyzer_path):
  170.             return False
  171.  
  172.         try:
  173.             proc = subprocess.Popen([sys.executable, self.analyzer_path],
  174.                                     cwd=os.path.dirname(self.analyzer_path))
  175.             self.analyzer_pid = proc.pid
  176.         except OSError as e:
  177.             ERROR_MESSAGE = str(e)
  178.             return False
  179.  
  180.         CURRENT_STATUS = STATUS_RUNNING
  181.  
  182.         return self.analyzer_pid
  183.  
  184.     def complete(self, success=True, error="", results=""):
  185.         """Complete analysis.
  186.        @param success: success status.
  187.        @param error: error status.
  188.        """
  189.         global ERROR_MESSAGE
  190.         global CURRENT_STATUS
  191.         global RESULTS_FOLDER
  192.  
  193.         if success:
  194.             CURRENT_STATUS = STATUS_COMPLETED
  195.         else:
  196.             if error:
  197.                 ERROR_MESSAGE = str(error)
  198.  
  199.             CURRENT_STATUS = STATUS_FAILED
  200.  
  201.         RESULTS_FOLDER = results
  202.  
  203.         return True
  204.  
  205. if __name__ == "__main__":
  206.     try:
  207.         if not BIND_IP:
  208.             BIND_IP = socket.gethostbyname(socket.gethostname())
  209.  
  210.         print("[+] Starting agent on %s:%s ..." % (BIND_IP, BIND_PORT))
  211.  
  212.         # Disable DNS lookup, by Scott D.
  213.         def FakeGetFQDN(name=""):
  214.             return name
  215.         socket.getfqdn = FakeGetFQDN
  216.  
  217.         server = SimpleXMLRPCServer((BIND_IP, BIND_PORT), allow_none=True)
  218.         server.register_instance(Agent())
  219.         server.serve_forever()
  220.     except KeyboardInterrupt:
  221.         server.shutdown()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement