Пример #1
0
def test_popen():
    """Ensures that Popen is working properly."""
    with mock.patch("subprocess.Popen") as p:
        p.return_value = None
        Popen(["foo", "bar"])

    p.assert_called_once_with(["foo", "bar"])

    with mock.patch("subprocess.Popen") as p:
        p.return_value = None
        Popen(
            ["foo", "bar"], close_fds=True,
            stdout=subprocess.PIPE, stderr=subprocess.PIPE
        )

    if is_windows():
        p.assert_called_once_with(
            ["foo", "bar"],
            stdout=subprocess.PIPE, stderr=subprocess.PIPE
        )
    else:
        p.assert_called_once_with(
            ["foo", "bar"], close_fds=True,
            stdout=subprocess.PIPE, stderr=subprocess.PIPE
        )

    # Test that the method actually works.
    p = Popen("echo 123", stdout=subprocess.PIPE, shell=True)
    out, err = p.communicate()
    assert out.strip() == "123" and not err

    # The following would normally throw an exception on Windows.
    p = Popen("echo 1234", close_fds=True, stdout=subprocess.PIPE, shell=True)
    out, err = p.communicate()
    assert out.strip() == "1234" and not err
Пример #2
0
def import_(ctx, mode, path):
    """Imports an older Cuckoo setup into a new CWD. The old setup should be
    identified by PATH and the new CWD may be specified with the --cwd
    parameter, e.g., "cuckoo --cwd /tmp/cwd import old-cuckoo"."""
    if mode == "symlink" and is_windows():
        sys.exit(red(
            "You can only use the 'symlink' mode on non-Windows platforms."
        ))

    print yellow("You are importing an existing Cuckoo setup. Please")
    print yellow("understand that, depending on the mode taken, if ")
    print yellow("you remove the old Cuckoo setup after this import ")
    print yellow("you may still"), red("loose ALL of your data!")
    print
    print yellow("Additionally, database migrations will be performed ")
    print yellow("in-place. You won't be able to use your old Cuckoo ")
    print yellow("setup anymore afterwards! However, we'll provide ")
    print yellow("you with the option to create a SQL backup beforehand.")
    print
    print red("TL;DR Cleaning the old setup after the import may")
    print red("corrupt your new setup: its SQL, MongoDB, and ")
    print red("ElasticSearch database may be dropped and, in 'symlink'")
    print red("mode, the analyses removed.")
    print

    value = click.confirm(
        "... I've read the above and understand the consequences", False
    )
    if not value:
        sys.exit(red("Aborting operation.. please try again!"))

    try:
        import_cuckoo(ctx.parent.user, mode, path)
    except KeyboardInterrupt:
        print(red("Aborting import of Cuckoo instance.."))
Пример #3
0
def import_legacy_analyses(mode, dirpath):
    """Imports the raw results of a legacy analysis. Using either the 'copy',
    'move', or 'symlink' mode."""
    if mode == "copy":
        import_analysis = import_analysis_copy
    elif mode == "move":
        import_analysis = shutil.move
    elif mode == "symlink":
        if is_windows():
            raise RuntimeError("Can't use 'symlink' mode under Windows!")
        import_analysis = os.symlink

    analyses = os.path.join(dirpath, "storage", "analyses")
    if not os.path.isdir(analyses):
        log.warning("Didn't find any analyses, so not much to import!")
        return

    tasks = []
    for task_id in os.listdir(analyses):
        if task_id == "latest":
            continue

        import_analysis(
            os.path.join(analyses, task_id), cwd(analysis=task_id)
        )
        tasks.append(int(task_id))
    return tasks
Пример #4
0
def test_popen():
    """Ensures that Popen is working properly."""
    with mock.patch("subprocess.Popen") as p:
        p.return_value = None
        Popen(["foo", "bar"])

    p.assert_called_once_with(["foo", "bar"])

    with mock.patch("subprocess.Popen") as p:
        p.return_value = None
        Popen(
            ["foo", "bar"], close_fds=True,
            stdout=subprocess.PIPE, stderr=subprocess.PIPE
        )

    if is_windows():
        p.assert_called_once_with(
            ["foo", "bar"],
            stdout=subprocess.PIPE, stderr=subprocess.PIPE
        )
    else:
        p.assert_called_once_with(
            ["foo", "bar"], close_fds=True,
            stdout=subprocess.PIPE, stderr=subprocess.PIPE
        )

    # Test that the method actually works.
    p = Popen("echo 123", stdout=subprocess.PIPE, shell=True)
    out, err = p.communicate()
    assert out.strip() == "123" and not err

    # The following would normally throw an exception on Windows.
    p = Popen("echo 1234", close_fds=True, stdout=subprocess.PIPE, shell=True)
    out, err = p.communicate()
    assert out.strip() == "1234" and not err
Пример #5
0
def import_legacy_analyses(mode, dirpath):
    """Imports the raw results of a legacy analysis. Using either the 'copy',
    'move', or 'symlink' mode."""
    if mode == "copy":
        import_analysis = shutil.copytree
    elif mode == "move":
        import_analysis = shutil.move
    elif mode == "symlink":
        if is_windows():
            raise RuntimeError("Can't use 'symlink' mode under Windows!")
        import_analysis = os.symlink

    analyses = os.path.join(dirpath, "storage", "analyses")
    if not os.path.isdir(analyses):
        log.warning("Didn't find any analyses, so not much to import!")
        return

    tasks = []
    for task_id in os.listdir(analyses):
        if task_id == "latest":
            continue

        import_analysis(os.path.join(analyses, task_id), cwd(analysis=task_id))
        tasks.append(int(task_id))
    return tasks
Пример #6
0
def init_legacy_analyses():
    dirpath = tempfile.mkdtemp()
    mkdir(dirpath, "storage")
    mkdir(dirpath, "storage", "analyses")

    mkdir(dirpath, "storage", "analyses", "1")
    mkdir(dirpath, "storage", "analyses", "1", "logs")
    Files.create(
        (dirpath, "storage", "analyses", "1", "logs"), "a.txt", "a"
    )
    mkdir(dirpath, "storage", "analyses", "1", "reports")
    Files.create(
        (dirpath, "storage", "analyses", "1", "reports"), "b.txt", "b"
    )

    mkdir(dirpath, "storage", "analyses", "2")
    Files.create((dirpath, "storage", "analyses", "2"), "cuckoo.log", "log")

    if not is_windows():
        os.symlink(
            "thisisnotanexistingfile",
            os.path.join(dirpath, "storage", "analyses", "2", "binary")
        )

    Files.create((dirpath, "storage", "analyses"), "latest", "last!!1")
    return dirpath
Пример #7
0
    def test_empty_symlink(self):
        oldfilepath = Files.temp_put("hello")
        try:
            movesql("sqlite:///%s" % oldfilepath, "symlink", temppath())

            # Following is non-windows.
            assert os.path.exists(oldfilepath)
            assert os.path.exists(cwd("cuckoo.db"))
            assert os.path.islink(cwd("cuckoo.db"))
            assert open(cwd("cuckoo.db"), "rb").read() == "hello"
        except RuntimeError as e:
            assert is_windows()
            assert "'symlink'" in e.message
Пример #8
0
    def test_empty_symlink(self):
        oldfilepath = Files.temp_put("hello")
        try:
            movesql("sqlite:///%s" % oldfilepath, "symlink", temppath())

            # Following is non-windows.
            assert os.path.exists(oldfilepath)
            assert os.path.exists(cwd("cuckoo.db"))
            assert os.path.islink(cwd("cuckoo.db"))
            assert open(cwd("cuckoo.db"), "rb").read() == "hello"
        except RuntimeError as e:
            assert is_windows()
            assert "'symlink'" in e.message
Пример #9
0
def import_(ctx, mode, path):
    """Imports an older Cuckoo setup into a new CWD. The old setup should be
    identified by PATH and the new CWD may be specified with the --cwd
    parameter, e.g., "cuckoo --cwd /tmp/cwd import old-cuckoo"."""
    if os.path.exists(os.path.join(path, ".cwd")):
        print(yellow(
            "The 'cuckoo import' feature is meant to import a legacy Cuckoo, "
            "i.e., Cuckoo 1.2, 2.0-dev, 2.0-rc1, or 2.0-rc2 into a new Cuckoo "
            "CWD."
        ))
        print(red(
            "You're attempting to import an existing Cuckoo CWD. To upgrade "
            "Cuckoo / your CWD, simply run 'pip install -U cuckoo' and re-run "
            "the cuckoo commands!"
        ))
        sys.exit(1)

    if mode == "symlink" and is_windows():
        sys.exit(red(
            "You can only use the 'symlink' mode on non-Windows platforms."
        ))

    print yellow("You are importing an existing Cuckoo setup. Please")
    print yellow("understand that, depending on the mode taken, if ")
    print yellow("you remove the old Cuckoo setup after this import ")
    print yellow("you may still"), red("lose ALL of your data!")
    print
    print yellow("Additionally, database migrations will be performed ")
    print yellow("in-place*. You won't be able to use your old Cuckoo ")
    print yellow("setup anymore afterwards! However, we'll provide ")
    print yellow("you with the option to create a SQL backup beforehand.")
    print
    print red("TL;DR Cleaning the old setup after the import may")
    print red("corrupt your new setup: its SQL, MongoDB, and ")
    print red("ElasticSearch database may be dropped and, in 'symlink'")
    print red("mode, the analyses removed.")
    print
    print yellow("*: Except for sqlite3 databases in combination with")
    print yellow("   the import 'copy' approach.")
    print

    value = click.confirm(
        "... I've read the above and understand the consequences", False
    )
    if not value:
        sys.exit(red("Aborting operation.. please try again!"))

    try:
        import_cuckoo(ctx.parent.user, mode, path)
    except KeyboardInterrupt:
        print(red("Aborting import of Cuckoo instance.."))
Пример #10
0
def import_(ctx, mode, path):
    """Import an older Cuckoo setup into a new CWD. The old setup should be
    identified by PATH and the new CWD may be specified with the --cwd
    parameter, e.g., "cuckoo --cwd /tmp/cwd import old-cuckoo"."""
    if os.path.exists(os.path.join(path, ".cwd")):
        print(yellow(
            "The 'cuckoo import' feature is meant to import a legacy Cuckoo, "
            "i.e., Cuckoo 1.2, 2.0-dev, 2.0-rc1, or 2.0-rc2 into a new Cuckoo "
            "CWD."
        ))
        print(red(
            "You're attempting to import an existing Cuckoo CWD. To upgrade "
            "Cuckoo / your CWD, simply run 'pip install -U cuckoo' and re-run "
            "the cuckoo commands!"
        ))
        sys.exit(1)

    if mode == "symlink" and is_windows():
        sys.exit(red(
            "You can only use the 'symlink' mode on non-Windows platforms."
        ))

    print yellow("You are importing an existing Cuckoo setup. Please")
    print yellow("understand that, depending on the mode taken, if ")
    print yellow("you remove the old Cuckoo setup after this import ")
    print yellow("you may still"), red("lose ALL of your data!")
    print
    print yellow("Additionally, database migrations will be performed ")
    print yellow("in-place*. You won't be able to use your old Cuckoo ")
    print yellow("setup anymore afterwards! However, we'll provide ")
    print yellow("you with the option to create a SQL backup beforehand.")
    print
    print red("TL;DR Cleaning the old setup after the import may")
    print red("corrupt your new setup: its SQL, MongoDB, and ")
    print red("ElasticSearch database may be dropped and, in 'symlink'")
    print red("mode, the analyses removed.")
    print
    print yellow("*: Except for sqlite3 databases in combination with")
    print yellow("   the import 'copy' approach.")
    print

    value = click.confirm(
        "... I've read the above and understand the consequences", False
    )
    if not value:
        sys.exit(red("Aborting operation.. please try again!"))

    try:
        import_cuckoo(ctx.parent.user, mode, path)
    except KeyboardInterrupt:
        print(red("Aborting import of Cuckoo instance.."))
Пример #11
0
def movesql(dburi, mode, dirpath):
    engine = _dburi_engine(dburi)
    if engine.name != "sqlite":
        return

    if mode == "copy":
        import_file = shutil.copy
    elif mode == "move":
        import_file = shutil.move
    elif mode == "symlink":
        if is_windows():
            raise RuntimeError("Can't use 'symlink' mode under Windows!")
        import_file = os.symlink

    # For more information on the os.path.join() usage see also dumpcmd().
    import_file(os.path.abspath(os.path.join(dirpath, engine.url.database)),
                cwd("cuckoo.db"))
Пример #12
0
def movesql(dburi, mode, dirpath):
    engine = _dburi_engine(dburi)
    if engine.name != "sqlite":
        return

    if mode == "copy":
        import_file = shutil.copy
    elif mode == "move":
        import_file = shutil.move
    elif mode == "symlink":
        if is_windows():
            raise RuntimeError("Can't use 'symlink' mode under Windows!")
        import_file = os.symlink

    # For more information on the os.path.join() usage see also dumpcmd().
    import_file(
        os.path.abspath(os.path.join(dirpath, engine.url.database)),
        cwd("cuckoo.db")
    )
Пример #13
0
def init_legacy_analyses():
    dirpath = tempfile.mkdtemp()
    mkdir(dirpath, "storage")
    mkdir(dirpath, "storage", "analyses")

    mkdir(dirpath, "storage", "analyses", "1")
    mkdir(dirpath, "storage", "analyses", "1", "logs")
    Files.create((dirpath, "storage", "analyses", "1", "logs"), "a.txt", "a")
    mkdir(dirpath, "storage", "analyses", "1", "reports")
    Files.create((dirpath, "storage", "analyses", "1", "reports"), "b.txt",
                 "b")

    mkdir(dirpath, "storage", "analyses", "2")
    Files.create((dirpath, "storage", "analyses", "2"), "cuckoo.log", "log")

    if not is_windows():
        os.symlink("thisisnotanexistingfile",
                   os.path.join(dirpath, "storage", "analyses", "2", "binary"))

    Files.create((dirpath, "storage", "analyses"), "latest", "last!!1")
    return dirpath
Пример #14
0
# Copyright (C) 2017 Cuckoo Foundation.
# This file is part of Cuckoo Sandbox - http://www.cuckoosandbox.org
# See the file 'docs/LICENSE' for copying permission.

import sys

from cuckoo.misc import is_windows, is_linux, is_macosx

# Note that collect_ignore is a parameter for pytest so that it knows which
# unit tests to skip etc. In other words, perform platform-specific unit tests
# (in terms of the Cuckoo Analyzer) depending on the current host machine.
collect_ignore = []

if is_windows():
    sys.path.insert(0, "cuckoo/data/analyzer/windows")
    collect_ignore.append("tests/linux")
    collect_ignore.append("tests/darwin")

if is_linux():
    sys.path.insert(0, "cuckoo/data/analyzer/linux")
    collect_ignore.append("tests/windows")
    collect_ignore.append("tests/darwin")

if is_macosx():
    sys.path.insert(0, "cuckoo/data/analyzer/darwin")
    collect_ignore.append("tests/windows")
    collect_ignore.append("tests/linux")
Пример #15
0
def test_is_macosx():
    assert is_windows() is False
    assert is_linux() is False
    assert is_macosx() is True
Пример #16
0
def test_sniffer():
    set_cwd(tempfile.mkdtemp())

    s = Sniffer()
    s.set_task(task)
    s.set_machine(machine)
    s.set_options({
        "tcpdump": __file__,
        "bpf": None,
    })

    with mock.patch("subprocess.Popen") as p:
        p.return_value = BasePopen()
        assert s.start() is True

    user = getuser()
    if user:
        user = "******" % user

    # Test regular setup.
    command = (
        "%s -U -q -s 0 -n -i interface %s-w %s "
        "host 1.2.3.4 and "
        "not ( dst host 1.2.3.4 and dst port 8000 ) and "
        "not ( src host 1.2.3.4 and src port 8000 ) and "
        "not ( dst host 1.1.1.1 and dst port 1234 ) and "
        "not ( src host 1.1.1.1 and src port 1234 )" % (
            __file__, user or "",
            cwd("storage", "analyses", "42", "dump.pcap")
        )
    )

    if is_windows():
        p.assert_called_once_with(
            command.split(), stdout=subprocess.PIPE, stderr=subprocess.PIPE
        )
    else:
        p.assert_called_once_with(
            command.split(), stdout=subprocess.PIPE, stderr=subprocess.PIPE,
            close_fds=True
        )

    assert s.stop() is None

    # Test a bpf rule.
    s.options["bpf"] = "not arp"
    with mock.patch("subprocess.Popen") as p:
        p.return_value = BasePopen()
        assert s.start() is True

    if is_windows():
        p.assert_called_once_with(
            command.split() + ["and", "(", "not arp", ")"],
            stdout=subprocess.PIPE, stderr=subprocess.PIPE
        )
    else:
        p.assert_called_once_with(
            command.split() + ["and", "(", "not arp", ")"],
            close_fds=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE
        )

    assert s.stop() is None

    # Test an invalid executable path.
    with mock.patch("os.path.exists") as p:
        p.return_value = False
        assert s.start() is False

    # Test stdout output from tcpdump.
    with mock.patch("subprocess.Popen") as p:
        p.return_value = PopenStdout()
        assert s.start() is True

    with pytest.raises(CuckooOperationalError) as e:
        assert s.stop()
    e.match("did not expect standard output")

    # Test unknown stderr output from tcpdump.
    with mock.patch("subprocess.Popen") as p:
        p.return_value = PopenStderr()
        assert s.start() is True

    with pytest.raises(CuckooOperationalError) as e:
        assert s.stop()
    e.match("following standard error output")

    # Test OSError and/or ValueError exceptions.
    with mock.patch("subprocess.Popen") as p:
        p.side_effect = OSError("this is awkward")
        assert s.start() is False

    with mock.patch("subprocess.Popen") as p:
        p.side_effect = ValueError("this is awkward")
        assert s.start() is False
Пример #17
0
def test_sniffer():
    set_cwd(tempfile.mkdtemp())

    s = Sniffer()
    s.set_task(task)
    s.set_machine(machine)
    s.set_options({
        "tcpdump": __file__,
        "bpf": None,
    })

    with mock.patch("subprocess.Popen") as p:
        p.return_value = BasePopen()
        assert s.start() is True

    user = getuser()
    if user:
        user = "******" % user

    # Test regular setup.
    command = (
        "%s -U -q -s 0 -n -i interface %s-w %s "
        "host 1.2.3.4 and "
        "not ( dst host 1.2.3.4 and dst port 8000 ) and "
        "not ( src host 1.2.3.4 and src port 8000 ) and "
        "not ( dst host 1.1.1.1 and dst port 1234 ) and "
        "not ( src host 1.1.1.1 and src port 1234 )" %
        (__file__, user or "", cwd("storage", "analyses", "42", "dump.pcap")))

    if is_windows():
        p.assert_called_once_with(command.split(),
                                  stdout=subprocess.PIPE,
                                  stderr=subprocess.PIPE)
    else:
        p.assert_called_once_with(command.split(),
                                  stdout=subprocess.PIPE,
                                  stderr=subprocess.PIPE,
                                  close_fds=True)

    assert s.stop() is None

    # Test a bpf rule.
    s.options["bpf"] = "not arp"
    with mock.patch("subprocess.Popen") as p:
        p.return_value = BasePopen()
        assert s.start() is True

    if is_windows():
        p.assert_called_once_with(command.split() +
                                  ["and", "(", "not arp", ")"],
                                  stdout=subprocess.PIPE,
                                  stderr=subprocess.PIPE)
    else:
        p.assert_called_once_with(command.split() +
                                  ["and", "(", "not arp", ")"],
                                  close_fds=True,
                                  stdout=subprocess.PIPE,
                                  stderr=subprocess.PIPE)

    assert s.stop() is None

    # Test an invalid executable path.
    with mock.patch("os.path.exists") as p:
        p.return_value = False
        assert s.start() is False

    # Test permission denied on tcpdump.
    with mock.patch("subprocess.Popen") as p:
        p.return_value = PopenPermissionDenied()
        assert s.start() is True

    with pytest.raises(CuckooOperationalError) as e:
        assert s.stop()
    e.match("the network traffic during the")
    e.match("denied-for-tcpdump")

    # Test stdout output from tcpdump.
    with mock.patch("subprocess.Popen") as p:
        p.return_value = PopenStdout()
        assert s.start() is True

    with pytest.raises(CuckooOperationalError) as e:
        assert s.stop()
    e.match("did not expect standard output")

    # Test unknown stderr output from tcpdump.
    with mock.patch("subprocess.Popen") as p:
        p.return_value = PopenStderr()
        assert s.start() is True

    with pytest.raises(CuckooOperationalError) as e:
        assert s.stop()
    e.match("following standard error output")

    # Test OSError and/or ValueError exceptions.
    with mock.patch("subprocess.Popen") as p:
        p.side_effect = OSError("this is awkward")
        assert s.start() is False

    with mock.patch("subprocess.Popen") as p:
        p.side_effect = ValueError("this is awkward")
        assert s.start() is False
Пример #18
0
# This file is part of Cuckoo Sandbox - http://www.cuckoosandbox.org
# See the file 'docs/LICENSE' for copying permission.

import os
import shutil
import sys
import tempfile

from cuckoo.misc import is_windows, is_linux, is_macosx, getuser, mkdir

# Note that collect_ignore is a parameter for pytest so that it knows which
# unit tests to skip etc. In other words, perform platform-specific unit tests
# (in terms of the Cuckoo Analyzer) depending on the current host machine.
collect_ignore = []

if is_windows():
    sys.path.insert(0, "cuckoo/data/analyzer/windows")
    collect_ignore.append("tests/linux")
    collect_ignore.append("tests/darwin")

    # Copy over the monitoring binaries as if we were in a real analysis.
    monitor = open("cuckoo/data/monitor/latest", "rb").read().strip()
    for filename in os.listdir("cuckoo/data/monitor/%s" % monitor):
        shutil.copy("cuckoo/data/monitor/%s/%s" % (monitor, filename),
                    "cuckoo/data/analyzer/windows/bin/%s" % filename)

if is_linux():
    sys.path.insert(0, "cuckoo/data/analyzer/linux")
    collect_ignore.append("tests/windows")
    collect_ignore.append("tests/darwin")
Пример #19
0
    assert os.path.isdir(cwd(analysis=1))
    assert os.path.isdir(cwd(analysis=2))

def test_import_legacy_analyses_move():
    dirpath = init_import_legacy("move")

    dirpath1 = os.path.join(dirpath, "storage", "analyses", "1")
    assert not os.path.isdir(dirpath1)

    dirpath2 = os.path.join(dirpath, "storage", "analyses", "2")
    assert not os.path.isdir(dirpath2)

    assert os.path.isdir(cwd(analysis=1))
    assert os.path.isdir(cwd(analysis=2))

if not is_windows():
    def test_import_legacy_analyses_symlink():
        dirpath = init_import_legacy("symlink")

        assert os.path.islink(cwd(analysis=1))
        assert os.path.islink(cwd(analysis=2))

        dirpath1 = os.path.join(dirpath, "storage", "analyses", "1")
        assert os.path.isdir(dirpath1)
        filepath = os.path.join(dirpath1, "logs", "a.txt")
        assert open(filepath, "rb").read() == "a"

        assert os.readlink(cwd(analysis=1)) == dirpath1

        dirpath2 = os.path.join(dirpath, "storage", "analyses", "2")
        assert os.path.isdir(dirpath2)
Пример #20
0
def test_is_macosx():
    assert is_windows() is False
    assert is_linux() is False
    assert is_macosx() is True
Пример #21
0

def test_import_legacy_analyses_move():
    dirpath = init_import_legacy("move")

    dirpath1 = os.path.join(dirpath, "storage", "analyses", "1")
    assert not os.path.isdir(dirpath1)

    dirpath2 = os.path.join(dirpath, "storage", "analyses", "2")
    assert not os.path.isdir(dirpath2)

    assert os.path.isdir(cwd(analysis=1))
    assert os.path.isdir(cwd(analysis=2))


if not is_windows():

    def test_import_legacy_analyses_symlink():
        dirpath = init_import_legacy("symlink")

        assert os.path.islink(cwd(analysis=1))
        assert os.path.islink(cwd(analysis=2))

        dirpath1 = os.path.join(dirpath, "storage", "analyses", "1")
        assert os.path.isdir(dirpath1)
        filepath = os.path.join(dirpath1, "logs", "a.txt")
        assert open(filepath, "rb").read() == "a"

        assert os.readlink(cwd(analysis=1)) == dirpath1

        dirpath2 = os.path.join(dirpath, "storage", "analyses", "2")