def test_pidfile_exists_true():
    set_cwd(tempfile.mkdtemp())
    cuckoo_create()

    p = Pidfile("test4")
    p.create()
    assert p.exists() and p.pid == os.getpid()
Beispiel #2
0
def test_proc_exists():
    assert Pidfile("hello").proc_exists(os.getpid())
    # Chances are possible, but slim.
    assert not Pidfile("hello").proc_exists(13337)

    assert not Pidfile("hello)").proc_exists(None)
    assert not Pidfile("hello)").proc_exists("")
Beispiel #3
0
def test_pidfile_exists_true():
    set_cwd(tempfile.mkdtemp())
    cuckoo_create()

    p = Pidfile("test4")
    p.create()
    assert p.exists() and p.pid == os.getpid()
def test_active_pids():
    set_cwd(tempfile.mkdtemp())
    cuckoo_create()

    Pidfile("test6").create()
    assert Pidfile.get_active_pids() == {
        "test6": os.getpid(),
    }
def test_remove_pidfile():
    set_cwd(tempfile.mkdtemp())
    cuckoo_create()

    Pidfile("test2").create()
    assert os.path.exists(cwd("pidfiles", "test2.pid"))

    Pidfile("test2").remove()
    assert not os.path.exists(cwd("pidfiles", "test2.pid"))
Beispiel #6
0
def test_pidfile_none():
    set_cwd(tempfile.mkdtemp())
    cuckoo_create()

    p = Pidfile("test5")
    p.create()

    open(cwd("pidfiles", "test5.pid"), "wb").write("notapid")
    assert p.read() is None
def test_pidfile_none():
    set_cwd(tempfile.mkdtemp())
    cuckoo_create()

    p = Pidfile("test5")
    p.create()

    open(cwd("pidfiles", "test5.pid"), "wb").write("notapid")
    assert p.read() is None
Beispiel #8
0
def process(ctx, instance, report, maxcount):
    """Process raw task data into reports."""
    init_console_logging(level=ctx.parent.level)

    if instance:
        pidfile = Pidfile(instance)
        if pidfile.exists():
            log.error(red(
                "Cuckoo process instance '%s' already exists. PID: %s\n"
            ), instance, pidfile.pid)
            sys.exit(1)

        pidfile.create()

        init_logfile("process-%s.json" % instance)

    Database().connect()

    # Load additional Signatures.
    load_signatures()

    try:
        # Initialize all modules & Yara rules.
        init_modules()
        init_yara()
    except CuckooCriticalError as e:
        message = red("{0}: {1}".format(e.__class__.__name__, e))
        if len(log.handlers):
            log.critical(message)
        else:
            sys.stderr.write("{0}\n".format(message))
        sys.exit(1)

    try:
        # Regenerate one or more reports.
        if report:
            process_task_range(report)
        elif not instance:
            print ctx.get_help(), "\n"
            sys.exit("In automated mode an instance name is required!")
        else:
            log.info(
                "Initialized instance=%s, ready to process some tasks",
                instance
            )
            process_tasks(instance, maxcount)
    except KeyboardInterrupt:
        print(red("Aborting (re-)processing of your analyses.."))

    if instance:
        Pidfile(instance).remove()
Beispiel #9
0
def cuckoo_main(max_analysis_count=0):
    """Cuckoo main loop.
    @param max_analysis_count: kill cuckoo after this number of analyses
    """
    rs, sched = None, None

    def stop():
        if sched:
            sched.running = False
        if rs:
            rs.instance.stop()

        Pidfile("cuckoo").remove()
        if sched:
            sched.stop()

    def handle_sigterm(sig, f):
        stop()

    # Handle a SIGTERM, to reduce the chance of Cuckoo exiting without
    # cleaning
    signal.signal(signal.SIGTERM, handle_sigterm)

    try:
        rs = ResultServer()
        sched = Scheduler(max_analysis_count)
        sched.start()
    except KeyboardInterrupt:
        log.info("CTRL+C detected! Stopping.. This can take a few seconds")
    finally:
        if Pidfile("cuckoo").exists():
            stop()
Beispiel #10
0
def test_active_pids():
    set_cwd(tempfile.mkdtemp())
    cuckoo_create()

    Pidfile("test6").create()
    assert Pidfile.get_active_pids() == {
        "test6": os.getpid(),
    }
Beispiel #11
0
    def stop():
        if sched:
            sched.running = False
        if rs:
            rs.instance.stop()

        Pidfile("cuckoo").remove()
        if sched:
            sched.stop()
Beispiel #12
0
def cuckoo_main(max_analysis_count=0):
    """Cuckoo main loop.
    @param max_analysis_count: kill cuckoo after this number of analyses
    """
    try:
        ResultServer()
        sched = Scheduler(max_analysis_count)
        sched.start()
    except KeyboardInterrupt:
        sched.stop()

    Pidfile("cuckoo").remove()
Beispiel #13
0
def process(ctx, instance, report, maxcount):
    """Process raw task data into reports."""
    init_console_logging(level=ctx.parent.level)

    if instance:
        pidfile = Pidfile(instance)
        if pidfile.exists():
            log.error(red(
                "Cuckoo process instance '%s' already exists. PID: %s\n"
            ), instance, pidfile.pid)
            sys.exit(1)

        pidfile.create()

        init_logfile("process-%s.json" % instance)

    Database().connect()

    # Load additional Signatures.
    load_signatures()

    try:
        # Initialize all modules & Yara rules.
        init_modules()
        init_yara()
    except CuckooCriticalError as e:
        message = red("{0}: {1}".format(e.__class__.__name__, e))
        if len(log.handlers):
            log.critical(message)
        else:
            sys.stderr.write("{0}\n".format(message))
        sys.exit(1)

    try:
        # Regenerate one or more reports.
        if report:
            process_task_range(report)
        elif not instance:
            print ctx.get_help(), "\n"
            sys.exit("In automated mode an instance name is required!")
        else:
            log.info(
                "Initialized instance=%s, ready to process some tasks",
                instance
            )
            process_tasks(instance, maxcount)
    except KeyboardInterrupt:
        print(red("Aborting (re-)processing of your analyses.."))

    if instance:
        Pidfile(instance).remove()
Beispiel #14
0
def cuckoo_status():
    # In order to keep track of the diskspace statistics of the temporary
    # directory we create a temporary file so we can statvfs() on that.
    temp_file = Files.temp_put("")

    paths = dict(
        binaries=cwd("storage", "binaries"),
        analyses=cwd("storage", "analyses"),
        temporary=temp_file,
    )

    diskspace = {}
    for key, path in paths.items():
        if hasattr(os, "statvfs") and os.path.isdir(path):
            stats = os.statvfs(path)
            diskspace[key] = dict(
                free=stats.f_bavail * stats.f_frsize,
                total=stats.f_blocks * stats.f_frsize,
                used=(stats.f_blocks - stats.f_bavail) * stats.f_frsize,
            )

    # Now we remove the temporary file and its parent directory.
    os.unlink(temp_file)

    # Get the CPU load.
    if hasattr(os, "getloadavg"):
        cpuload = os.getloadavg()
    else:
        cpuload = []

    if os.path.isfile("/proc/meminfo"):
        values = {}
        for line in open("/proc/meminfo"):
            key, value = line.split(":", 1)
            values[key.strip()] = value.replace("kB", "").strip()

        if "MemAvailable" in values and "MemTotal" in values:
            memavail = int(values["MemAvailable"])
            memtotal = int(values["MemTotal"])
            memory = 100 - 100.0 * memavail / memtotal
        else:
            memory = memavail = memtotal = None
    else:
        memory = memavail = memtotal = None

    try:
        cpu_core_count = multiprocessing.cpu_count()
    except NotImplementedError:
        cpu_core_count = None

    response = dict(version=version,
                    hostname=socket.gethostname(),
                    machines=dict(total=len(db.list_machines()),
                                  available=db.count_machines_available()),
                    tasks=dict(total=db.count_tasks(),
                               pending=db.count_tasks("pending"),
                               running=db.count_tasks("running"),
                               completed=db.count_tasks("completed"),
                               reported=db.count_tasks("reported")),
                    diskspace=diskspace,
                    cpuload=cpuload,
                    cpu_count=cpu_core_count,
                    memory=memory,
                    memavail=memavail,
                    memtotal=memtotal,
                    processes=Pidfile.get_active_pids())

    return jsonify(response)
Beispiel #15
0
def cuckoo_status():
    # In order to keep track of the diskspace statistics of the temporary
    # directory we create a temporary file so we can statvfs() on that.
    temp_file = Files.temp_put("")

    paths = dict(
        binaries=cwd("storage", "binaries"),
        analyses=cwd("storage", "analyses"),
        temporary=temp_file,
    )

    diskspace = {}
    for key, path in paths.items():
        if hasattr(os, "statvfs") and os.path.isdir(path):
            stats = os.statvfs(path)
            diskspace[key] = dict(
                free=stats.f_bavail * stats.f_frsize,
                total=stats.f_blocks * stats.f_frsize,
                used=(stats.f_blocks - stats.f_bavail) * stats.f_frsize,
            )

    # Now we remove the temporary file and its parent directory.
    os.unlink(temp_file)

    # Get the CPU load.
    if hasattr(os, "getloadavg"):
        cpuload = os.getloadavg()
    else:
        cpuload = []

    if os.path.isfile("/proc/meminfo"):
        values = {}
        for line in open("/proc/meminfo"):
            key, value = line.split(":", 1)
            values[key.strip()] = value.replace("kB", "").strip()

        if "MemAvailable" in values and "MemTotal" in values:
            memavail = int(values["MemAvailable"])
            memtotal = int(values["MemTotal"])
            memory = 100 - 100.0 * memavail / memtotal
        else:
            memory = memavail = memtotal = None
    else:
        memory = memavail = memtotal = None

    try:
        cpu_core_count = multiprocessing.cpu_count()
    except NotImplementedError:
        cpu_core_count = None

    response = dict(
        version=version,
        hostname=socket.gethostname(),
        machines=dict(
            total=len(db.list_machines()),
            available=db.count_machines_available()
        ),
        tasks=dict(
            total=db.count_tasks(),
            pending=db.count_tasks("pending"),
            running=db.count_tasks("running"),
            completed=db.count_tasks("completed"),
            reported=db.count_tasks("reported")
        ),
        diskspace=diskspace,
        cpuload=cpuload,
        cpu_count=cpu_core_count,
        memory=memory,
        memavail=memavail,
        memtotal=memtotal,
        processes=Pidfile.get_active_pids()
    )

    return jsonify(response)
Beispiel #16
0
def cuckoo_init(level, ctx, cfg=None):
    """Initialize Cuckoo configuration.
    @param quiet: enable quiet mode.
    """
    logo()

    # It would appear this is the first time Cuckoo is being run (on this
    # Cuckoo Working Directory anyway).
    if not os.path.isdir(cwd()) or not os.listdir(cwd()):
        cuckoo_create(ctx.user, cfg)
        sys.exit(0)

    # Determine if this is a proper CWD.
    if not os.path.exists(cwd(".cwd")):
        sys.exit(
            "No proper Cuckoo Working Directory was identified, did you pass "
            "along the correct directory? For new installations please use a "
            "non-existant directory to build up the CWD! You can craft a CWD "
            "manually, but keep in mind that the CWD layout may change along "
            "with Cuckoo releases (and don't forget to fill out '$CWD/.cwd')!"
        )

    init_console_logging(level)

    # Only one Cuckoo process should exist per CWD. Run this check before any
    # files are possibly modified. Note that we mkdir $CWD/pidfiles/ here as
    # its CWD migration rules only kick in after the pidfile check.
    mkdir(cwd("pidfiles"))
    pidfile = Pidfile("cuckoo")
    if pidfile.exists():
        log.error(red("Cuckoo is already running. PID: %s"), pidfile.pid)
        sys.exit(1)

    pidfile.create()

    check_configs()
    check_version()

    ctx.log and init_logging(level)

    # Determine if any CWD updates are required and if so, do them.
    current = open(cwd(".cwd"), "rb").read().strip()
    latest = open(cwd(".cwd", private=True), "rb").read().strip()
    if current != latest:
        migrate_cwd()
        open(cwd(".cwd"), "wb").write(latest)

    Database().connect()

    # Load additional Signatures.
    load_signatures()

    init_modules()
    init_tasks()
    init_yara()
    init_binaries()
    init_rooter()
    init_routing()

    signatures = 0
    for sig in cuckoo.signatures:
        if not sig.enabled:
            continue
        signatures += 1

    if not signatures:
        log.warning(
            "It appears that you haven't loaded any Cuckoo Signatures. "
            "Signatures are highly recommended and improve & enrich the "
            "information extracted during an analysis. They also make up "
            "for the analysis score that you see in the Web Interface - so, "
            "pretty important!"
        )
        log.warning(
            "You'll be able to fetch all the latest Cuckoo Signaturs, Yara "
            "rules, and more goodies by running the following command:"
        )
        raw = cwd(raw=True)
        if raw == "." or raw == "~/.cuckoo":
            command = "cuckoo community"
        elif " " in raw or "'" in raw:
            command = 'cuckoo --cwd "%s" community' % raw
        else:
            command = "cuckoo --cwd %s community" % raw

        log.info("$ %s", green(command))
Beispiel #17
0
def cuckoo_init(level, ctx, cfg=None):
    """Initialize Cuckoo configuration.
    @param quiet: enable quiet mode.
    """
    logo()

    # It would appear this is the first time Cuckoo is being run (on this
    # Cuckoo Working Directory anyway).
    if not os.path.isdir(cwd()) or not os.listdir(cwd()):
        cuckoo_create(ctx.user, cfg)
        sys.exit(0)

    # Determine if this is a proper CWD.
    if not os.path.exists(cwd(".cwd")):
        sys.exit(
            "No proper Cuckoo Working Directory was identified, did you pass "
            "along the correct directory? For new installations please use a "
            "non-existant directory to build up the CWD! You can craft a CWD "
            "manually, but keep in mind that the CWD layout may change along "
            "with Cuckoo releases (and don't forget to fill out '$CWD/.cwd')!")

    init_console_logging(level)

    # Only one Cuckoo process should exist per CWD. Run this check before any
    # files are possibly modified. Note that we mkdir $CWD/pidfiles/ here as
    # its CWD migration rules only kick in after the pidfile check.
    mkdir(cwd("pidfiles"))
    pidfile = Pidfile("cuckoo")
    if pidfile.exists():
        log.error(red("Cuckoo is already running. PID: %s"), pidfile.pid)
        sys.exit(1)

    pidfile.create()

    check_configs()
    check_version()

    ctx.log and init_logging(level)

    # Determine if any CWD updates are required and if so, do them.
    current = open(cwd(".cwd"), "rb").read().strip()
    latest = open(cwd(".cwd", private=True), "rb").read().strip()
    if current != latest:
        migrate_cwd()
        open(cwd(".cwd"), "wb").write(latest)

    # Ensure the user is able to create and read temporary files.
    if not ensure_tmpdir():
        sys.exit(1)

    Database().connect()

    # Load additional Signatures.
    load_signatures()

    init_modules()
    init_tasks()
    init_yara()
    init_binaries()
    init_rooter()
    init_routing()

    signatures = 0
    for sig in cuckoo.signatures:
        if not sig.enabled:
            continue
        signatures += 1

    if not signatures:
        log.warning(
            "It appears that you haven't loaded any Cuckoo Signatures. "
            "Signatures are highly recommended and improve & enrich the "
            "information extracted during an analysis. They also make up "
            "for the analysis score that you see in the Web Interface - so, "
            "pretty important!")
        log.warning(
            "You'll be able to fetch all the latest Cuckoo Signaturs, Yara "
            "rules, and more goodies by running the following command:")
        log.info("$ %s", green(format_command("community")))
def test_create_pidfile():
    set_cwd(tempfile.mkdtemp())
    cuckoo_create()

    Pidfile("test1").create()
    assert int(open(cwd("pidfiles", "test1.pid"), "rb").read()) == os.getpid()
def test_pidfile_exists_false():
    set_cwd(tempfile.mkdtemp())
    cuckoo_create()
    assert not Pidfile("test3").exists()
def test_pid_exists_unsupported_platform(p):
    p.platform = "DogeOS"
    assert Pidfile("hello").proc_exists(os.getpid()) is None