Beispiel #1
0
 def __init__(self, task_id):
     """@param analysis_path: analysis folder path.
     """
     self.task = Database().view_task(task_id).to_dict()
     self.analysis_path = os.path.join(CUCKOO_ROOT,
                                       "storage",
                                       "analyses",
                                       str(task_id))
     self.cfg = Config(cfg=os.path.join(CUCKOO_ROOT,
                                        "conf",
                                        "reporting.conf"))
    def start(self, interface="eth0", host="", file_path=""):
        """Start sniffing.
        @param interface: network interface name.
        @param host: guest host IP address.
        @param file_path: tcpdump path.
        @return: operation status.
        """
        if not os.path.exists(self.tcpdump):
            log.error("Tcpdump does not exist at path \"%s\", network capture "
                      "aborted" % self.tcpdump)
            return False

        mode = os.stat(self.tcpdump)[stat.ST_MODE]
        if mode and stat.S_ISUID != 2048:
            log.error("Tcpdump is not accessible from this user, network "
                      "capture aborted")
            return False

        if not interface:
            log.error("Network interface not defined, network capture aborted")
            return False

        pargs = [self.tcpdump, '-U', '-q', '-i', interface, '-n']
        pargs.extend(['-w', file_path])
        pargs.extend(['host', host])
        # Do not capture XMLRPC agent traffic.
        pargs.extend([
            'and', 'not', '(', 'host', host, 'and', 'port',
            str(CUCKOO_GUEST_PORT), ')'
        ])
        # Do not capture ResultServer traffic.
        pargs.extend([
            'and', 'not', '(', 'host',
            str(Config().resultserver.ip), 'and', 'port',
            str(Config().resultserver.port), ')'
        ])

        try:
            self.proc = subprocess.Popen(pargs,
                                         stdout=subprocess.PIPE,
                                         stderr=subprocess.PIPE)
        except (OSError, ValueError) as e:
            log.exception("Failed to start sniffer (interface=%s, host=%s, "
                          "dump path=%s)" % (interface, host, file_path))
            return False

        log.info("Started sniffer (interface=%s, host=%s, dump path=%s)" %
                 (interface, host, file_path))

        return True
Beispiel #3
0
def check_version():
    """Checks version of Cuckoo."""
    cfg = Config()

    if not cfg.cuckoo.version_check:
        return

    print(" Checking for updates...")

    url = "http://api.cuckoosandbox.org/checkversion.php"
    data = urllib.urlencode({"version" : CUCKOO_VERSION})

    try:
        request = urllib2.Request(url, data)
        response = urllib2.urlopen(request)
    except (urllib2.URLError, urllib2.HTTPError):
        print(red(" Failed! ") + "Unable to establish connection.\n")
        return

    try:
        response_data = json.loads(response.read())
    except ValueError:
        print(red(" Failed! ") + "Invalid response.\n")
        return

    if not response_data["error"]:
        if response_data["response"] == "NEW_VERSION":
            print(red(" Outdated! ") + "Cuckoo Sandbox version %s is "
                  "available now.\n" % response_data["current"])
        else:
            print(green(" Good! ") + "You have the latest version available.\n")
Beispiel #4
0
def init_logging():
    """Initializes logging."""
    cfg = Config()

    formatter = logging.Formatter("%(asctime)s [%(name)s] %(levelname)s: %(message)s")

    fh = logging.handlers.WatchedFileHandler(os.path.join(CUCKOO_ROOT, "log", "cuckoo.log"))
    fh.setFormatter(formatter)
    log.addHandler(fh)

    ch = ConsoleHandler()
    ch.setFormatter(formatter)
    log.addHandler(ch)

    dh = DatabaseHandler()
    dh.setLevel(logging.ERROR)
    log.addHandler(dh)

    if cfg.graylog.enabled:
        if HAVE_GRAYPY:
            gray = graypy.GELFHandler(cfg.graylog.host, cfg.graylog.port)

            try:
                level = logging.getLevelName(cfg.graylog.level.upper())
            except ValueError:
                level = logging.ERROR

            gray.setLevel(level)
            log.addHandler(gray)
        else:
            raise CuckooDependencyError("Graypy is not installed")

    log.setLevel(logging.INFO)
 def _load_conf(self, conf):
     """Loads a configuration from a string.
     @param conf: configuration string.
     """
     f = open(self.file, "w")
     f.write(conf)
     f.close()
     self.m.set_options(Config(self.file))
Beispiel #6
0
 def setUp(self):
     self.tmp = tempfile.mkdtemp()
     self.cfg = tempfile.mkstemp()[1]
     f = open(self.cfg, "w")
     f.write(self.CONFIG)
     f.close()
     self.r = Reporter(self.tmp)
     self.r.cfg = Config(self.cfg)
    def __init__(self, task):
        """@param task: task object containing the details for the analysis."""
        Thread.__init__(self)
        Thread.daemon = True

        self.task = task
        self.cfg = Config()
        self.storage = ""
        self.binary = ""
Beispiel #8
0
 def __init__(self):
     self.module_name = ""
     self.options = None
     self.options_globals = Config(
         os.path.join(CUCKOO_ROOT, "conf", "cuckoo.conf"))
     # Database pointer.
     self.db = Database()
     # Machine table is cleaned to be filled from configuration file at each start.
     self.db.clean_machines()
Beispiel #9
0
 def _dns_gethostbyname(self, name):
     """Get host by name wrapper.
     @param name: hostname.
     @return: IP address or blank
     """
     if Config().processing.resolve_dns:
         ip = resolve(name)
     else:
         ip = ""
     return ip
Beispiel #10
0
def init_modules():
    """Initializes plugins."""
    log.debug("Importing modules...")

    # Import all processing modules.
    import_package(modules.processing)
    # Import all signatures.
    import_package(modules.signatures)

    # Import only enabled reporting modules.
    report_cfg = Config(cfg=os.path.join(CUCKOO_ROOT,
                                         "conf",
                                         "reporting.conf"))

    prefix = modules.reporting.__name__ + "."
    for loader, name, ispkg in pkgutil.iter_modules(modules.reporting.__path__):
        if ispkg:
            continue

        try:
            options = report_cfg.get(name)
        except AttributeError:
            log.debug("Reporting module %s not found in "
                      "configuration file" % module_name)

        if not options.enabled:
            continue

        import_plugin("%s.%s" % (modules.reporting.__name__, name))

    # Import machine manager.
    import_plugin("modules.machinemanagers.%s"
                  % Config().cuckoo.machine_manager)

    for category, mods in list_plugins().items():
        log.debug("Imported \"%s\" modules:" % category)

        for mod in mods:
            if mod == mods[-1]:
                log.debug("\t `-- %s" % mod.__name__)
            else:
                log.debug("\t |-- %s" % mod.__name__)
Beispiel #11
0
    def __init__(self, vm_id, ip, platform="windows"):
        """@param ip: guest's IP address.
        @param platform: guest's operating system type.
        """
        self.id = vm_id
        self.ip = ip
        self.platform = platform

        self.cfg = Config()
        self.timeout = self.cfg.timeouts.critical
        self.server = TimeoutServer("http://{0}:{1}".format(ip, CUCKOO_GUEST_PORT),
                                    allow_none=True, 
                                    timeout=self.timeout)
Beispiel #12
0
    def __init__(self, *args, **kwargs):
        self.cfg = Config()
        self.analysistasks = {}
        self.analysishandlers = {}

        try:
            SocketServer.ThreadingTCPServer.__init__(
                self, (self.cfg.resultserver.ip, self.cfg.resultserver.port),
                Resulthandler, *args, **kwargs)
        except Exception as e:
            log.error("Unable to bind result server on %s:%s: %s",
                      self.cfg.resultserver.ip, self.cfg.resultserver.port, e)
        else:
            self.servethread = Thread(target=self.serve_forever)
            self.servethread.setDaemon(True)
            self.servethread.start()
Beispiel #13
0
    def _run_report(self, module, results):
        """Run a single reporting module.
        @param module: reporting module.
        @param results: results results from analysis.
        """
        # Initialize current reporting module.
        current = module()
        # Give it the path to the analysis results folder.
        current.set_path(self.analysis_path)
        # Load the content of the analysis.conf file.
        current.cfg = Config(current.conf_path)

        # Extract the module name.
        module_name = inspect.getmodule(current).__name__
        if "." in module_name:
            module_name = module_name.rsplit(".", 1)[1]

        options = self.cfg.get(module_name)

        # If the reporting module is disabled in the config, skip it.
        if not options.enabled:
            return

        # Give it the content of the relevant section from the reporting.conf
        # configuration file.
        current.set_options(options)
        current.set_task(self.task)

        try:
            # Run report, for each report a brand new copy of results is
            # created, to prevent a reporting module to edit global
            # result set and affect other reporting modules.
            current.run(results)
            log.debug("Executed reporting module \"%s\""
                      % current.__class__.__name__)
        except CuckooReportError as e:
            log.warning("The reporting module \"%s\" returned the following "
                        "error: %s" % (current.__class__.__name__, e))
        except Exception as e:
            log.exception("Failed to run the reporting module \"%s\":"
                          % (current.__class__.__name__))
class TestConfig:
    CONF_EXAMPLE = """
[cuckoo]
debug = off
analysis_timeout = 120
critical_timeout = 600
delete_original = off
machine_manager = kvm
use_sniffer = no
tcpdump = /usr/sbin/tcpdump
interface = vboxnet0
"""

    def setUp(self):
        self.file = tempfile.mkstemp()[1]
        self._load_conf(self.CONF_EXAMPLE)
        self.c = Config(self.file)

    def _load_conf(self, conf):
        """Loads a configuration from a string.
        @param conf: configuration string.
        """
        f = open(self.file, "w")
        f.write(conf)
        f.close()

    def test_get_option_exist(self):
        """Fetch an option of each type from default config file."""
        assert_equals(self.c.get("cuckoo")["debug"], False)
        assert_equals(self.c.get("cuckoo")["tcpdump"], "/usr/sbin/tcpdump")
        assert_equals(self.c.get("cuckoo")["critical_timeout"], 600)

    def test_config_file_not_found(self):
        assert Config("foo")

    @raises(CuckooOperationalError)
    def test_get_option_not_found(self):
        self.c.get("foo")

    @raises(CuckooOperationalError)
    def test_get_option_not_found_in_file_not_found(self):
        self.c = Config("bar")
        self.c.get("foo")
    def __init__(self, dsn=None):
        """@param dsn: database connection string."""
        cfg = Config()

        if dsn:
            self.engine = create_engine(dsn, poolclass=NullPool)
        elif cfg.database.connection:
            self.engine = create_engine(cfg.database.connection,
                                        poolclass=NullPool)
        else:
            db_file = os.path.join(CUCKOO_ROOT, "db", "cuckoo.db")
            if not os.path.exists(db_file):
                db_dir = os.path.dirname(db_file)
                if not os.path.exists(db_dir):
                    try:
                        create_folder(folder=db_dir)
                    except CuckooOperationalError as e:
                        raise CuckooDatabaseError("Unable to create database "
                                                  "directory: %s" % e)
            self.engine = create_engine("sqlite:///%s" % db_file,
                                        poolclass=NullPool)

        # Disable SQL logging. Turn it on for debugging.
        self.engine.echo = False
        # Connection timeout.
        if cfg.database.timeout:
            self.engine.pool_timeout = cfg.database.timeout
        else:
            self.engine.pool_timeout = 60
        # Create schema.
        try:
            Base.metadata.create_all(self.engine)
        except SQLAlchemyError as e:
            raise CuckooDatabaseError("Unable to create or connect to "
                                      "database: %s" % e)

        # Get db session.
        self.Session = sessionmaker(bind=self.engine)
    def initialize(self):
        """Initialize the machine manager."""
        global mmanager

        mmanager_name = self.cfg.cuckoo.machine_manager

        log.info("Using \"%s\" machine manager", mmanager_name)

        # Get registered class name. Only one machine manager is imported,
        # therefore there should be only one class in the list.
        plugin = list_plugins("machinemanagers")[0]
        # Initialize the machine manager.
        mmanager = plugin()

        # Find its configuration file.
        conf = os.path.join(CUCKOO_ROOT, "conf", "%s.conf" % mmanager_name)

        if not os.path.exists(conf):
            raise CuckooCriticalError(
                "The configuration file for machine "
                "manager \"{0}\" does not exist at path: "
                "{1}".format(mmanager_name, conf))

        # Provide a dictionary with the configuration options to the
        # machine manager instance.
        mmanager.set_options(Config(conf))
        # Initialize the machine manager.
        mmanager.initialize(mmanager_name)

        # At this point all the available machines should have been identified
        # and added to the list. If none were found, Cuckoo needs to abort the
        # execution.
        if mmanager.machines().count() == 0:
            raise CuckooCriticalError("No machines available")
        else:
            log.info("Loaded %s machine/s", mmanager.machines().count())
 def test_get_option_not_found_in_file_not_found(self):
     self.c = Config("bar")
     self.c.get("foo")
 def test_config_file_not_found(self):
     assert Config("foo")
 def setUp(self):
     self.file = tempfile.mkstemp()[1]
     self._load_conf(self.CONF_EXAMPLE)
     self.c = Config(self.file)
 def __init__(self):
     self.running = True
     self.cfg = Config()
     self.db = Database()
Beispiel #21
0
class Reporter:
    """Reporting Engine.

    This class handles the loading and execution of the enabled reporting
    modules. It receives the analysis results dictionary from the Processing
    Engine and pass it over to the reporting modules before executing them.
    """

    def __init__(self, task_id):
        """@param analysis_path: analysis folder path.
        """
        self.task = Database().view_task(task_id).to_dict()
        self.analysis_path = os.path.join(CUCKOO_ROOT,
                                          "storage",
                                          "analyses",
                                          str(task_id))
        self.cfg = Config(cfg=os.path.join(CUCKOO_ROOT,
                                           "conf",
                                           "reporting.conf"))

    def _run_report(self, module, results):
        """Run a single reporting module.
        @param module: reporting module.
        @param results: results results from analysis.
        """
        # Initialize current reporting module.
        current = module()
        # Give it the path to the analysis results folder.
        current.set_path(self.analysis_path)
        # Load the content of the analysis.conf file.
        current.cfg = Config(current.conf_path)

        # Extract the module name.
        module_name = inspect.getmodule(current).__name__
        if "." in module_name:
            module_name = module_name.rsplit(".", 1)[1]

        options = self.cfg.get(module_name)

        # If the reporting module is disabled in the config, skip it.
        if not options.enabled:
            return

        # Give it the content of the relevant section from the reporting.conf
        # configuration file.
        current.set_options(options)
        current.set_task(self.task)

        try:
            # Run report, for each report a brand new copy of results is
            # created, to prevent a reporting module to edit global
            # result set and affect other reporting modules.
            current.run(results)
            log.debug("Executed reporting module \"%s\""
                      % current.__class__.__name__)
        except CuckooReportError as e:
            log.warning("The reporting module \"%s\" returned the following "
                        "error: %s" % (current.__class__.__name__, e))
        except Exception as e:
            log.exception("Failed to run the reporting module \"%s\":"
                          % (current.__class__.__name__))

    def run(self, results):
        """Generates all reports.
        @param results: analysis results.
        @raise CuckooReportError: if a report module fails.
        """
        # In every reporting module you can specify a numeric value that
        # represents at which position that module should be executed among
        # all the available ones. It can be used in the case where a
        # module requires another one to be already executed beforehand.
        modules_list = list_plugins(group="reporting")

        # Return if no reporting modules are loaded.
        if not modules_list:
            log.debug("No reporting modules loaded")
            return

        modules_list.sort(key=lambda module: module.order)

        # Run every loaded reporting module.
        for module in modules_list:
            self._run_report(module, results)