Esempio n. 1
0
def investigate(file_path):
    # Clone our Clean snapshot
    my_call("VBoxManage startvm User1")
    time.sleep(52)
    subprocess.call(CREATE_SNAPSHOT, shell=True)
    time.sleep(2)

    task_id = -1
    my_call("cuckoo")
    # web = my_call("cuckoo api")
    # TODO implement
    # Send the file to cuckoo
    time.sleep(2)
    db = Database()
    db.connect()
    task_id = db.add_path(file_path)
    # a = subprocess.check_output(CALL_CUCKOO + file_path, shell= True)
    #a = subprocess.call(CALL_CUCKOO + file_path, shell=True)
    print "The id is " + str(task_id)
    # wait until it finishes running    subprocess.check_output(CREATE_SNAPSHOT)
    status = None
    while status != 'reported':
        lst = db.list_tasks()
        status = lst[0].status
        time.sleep(1)
    print "Reported"

    # THIS IS NOT THE CUCKOO PID!!!!
    # os.kill(newpid, signal.SIGTERM)
    # according to the ID, get the reports from this system.
    subprocess.call(REMOVE_SNAPSHOT, shell=True)
    # subprocess.call(KILL_CUCKOO, shell=True)
    kp = subprocess.Popen(["ps", "-ef"], stdout=subprocess.PIPE)
    grep = subprocess.Popen(["grep", "cuckoo"],
                            stdin=kp.stdout,
                            stdout=subprocess.PIPE)
    awk = subprocess.Popen(["awk", "{print $2}"],
                           stdin=grep.stdout,
                           stdout=subprocess.PIPE)
    kill = subprocess.Popen(["xargs", "kill"],
                            stdin=awk.stdout,
                            stdout=subprocess.PIPE)
    kp.stdout.close()
    grep.stdout.close()
    awk.stdout.close()
    return task_id


#
# for i in "abcdefghijklmnopqrstuvwxyz":
#     try:
#         investigate("/home/user/Desktop/sandboxing/ransomwares/" + i)
#     except:
#         print "Skipping..."

# Stages:    Save file.
#            Investigate
#            Grade
#            Signatures
#            return all to server.
Esempio n. 2
0
def init_tasks():
    """Check tasks and reschedule uncompleted ones."""
    db = Database()

    log.debug("Checking for locked tasks..")
    for task in db.list_tasks(status=TASK_RUNNING):
        if config("cuckoo:cuckoo:reschedule"):
            task_id = db.reschedule(task.id)
            log.info("Rescheduled task with ID %s and target %s: task #%s",
                     task.id, task.target, task_id)
        else:
            db.set_status(task.id, TASK_FAILED_ANALYSIS)
            log.info("Updated running task ID %s status to failed_analysis",
                     task.id)

    log.debug("Checking for pending service tasks..")
    for task in db.list_tasks(status=TASK_PENDING, category="service"):
        db.set_status(task.id, TASK_FAILED_ANALYSIS)
Esempio n. 3
0
def init_tasks():
    """Check tasks and reschedule uncompleted ones."""
    db = Database()

    log.debug("Checking for locked tasks..")
    for task in db.list_tasks(status=TASK_RUNNING):
        if config("cuckoo:cuckoo:reschedule"):
            task_id = db.reschedule(task.id)
            log.info(
                "Rescheduled task with ID %s and target %s: task #%s",
                task.id, task.target, task_id
            )
        else:
            db.set_status(task.id, TASK_FAILED_ANALYSIS)
            log.info(
                "Updated running task ID %s status to failed_analysis",
                task.id
            )

    log.debug("Checking for pending service tasks..")
    for task in db.list_tasks(status=TASK_PENDING, category="service"):
        db.set_status(task.id, TASK_FAILED_ANALYSIS)
Esempio n. 4
0
class DatabaseEngine(object):
    """Tests database stuff."""
    URI = None

    def setup_class(self):
        set_cwd(tempfile.mkdtemp())

    def setup(self):
        self.d = Database()
        self.d.connect(dsn=self.URI)

    def teardown(self):
        # Clear all tables without dropping them
        # This is done after each test to ensure a test doesn't fail because
        # of data of a previous test
        meta = MetaData()
        meta.reflect(self.d.engine)
        ses = self.d.Session()
        try:
            for t in reversed(meta.sorted_tables):
                ses.execute(t.delete())
            ses.commit()
        finally:
            ses.close()

    def test_add_target(self):
        count = self.d.Session().query(Target).count()
        add_target("http://example.com", category="url")
        assert self.d.Session().query(Target).count() == count + 1

    def test_add_task(self):
        fd, sample_path = tempfile.mkstemp()
        os.write(fd, "hehe")
        os.close(fd)

        # Add task.
        count = self.d.Session().query(Task).count()
        add_task(sample_path, category="file")
        assert self.d.Session().query(Task).count() == count + 1

    def test_processing_get_task(self):
        # First reset all existing rows so that earlier exceptions don't affect
        # this unit test run.
        null, session = None, self.d.Session()

        session.query(Task).filter(Task.status == "completed",
                                   Task.processing == null).update({
                                       "processing":
                                       "something",
                                   })
        session.commit()

        t1 = add_task("http://google.com/1",
                      priority=1,
                      status="completed",
                      category="url")
        t2 = add_task("http://google.com/2",
                      priority=2,
                      status="completed",
                      category="url")
        t3 = add_task("http://google.com/3",
                      priority=1,
                      status="completed",
                      category="url")
        t4 = add_task("http://google.com/4",
                      priority=1,
                      status="completed",
                      category="url")
        t5 = add_task("http://google.com/5",
                      priority=3,
                      status="completed",
                      category="url")
        t6 = add_task("http://google.com/6",
                      priority=1,
                      status="completed",
                      category="url")
        t7 = add_task("http://google.com/7",
                      priority=1,
                      status="completed",
                      category="url")

        assert self.d.processing_get_task("foo") == t5
        assert self.d.processing_get_task("foo") == t2
        assert self.d.processing_get_task("foo") == t1
        assert self.d.processing_get_task("foo") == t3
        assert self.d.processing_get_task("foo") == t4
        assert self.d.processing_get_task("foo") == t6
        assert self.d.processing_get_task("foo") == t7
        assert self.d.processing_get_task("foo") is None

    def test_error_exists(self):
        task_id = add_task("http://google.com/7", category="url")
        self.d.add_error("A" * 1024, task_id)
        assert len(self.d.view_errors(task_id)) == 1
        self.d.add_error("A" * 1024, task_id)
        assert len(self.d.view_errors(task_id)) == 2

    def test_long_error(self):
        add_task("http://google.com/", category="url")
        self.d.add_error("A" * 1024, 1)
        err = self.d.view_errors(1)
        assert err and len(err[0].message) == 1024

    def test_submit(self):
        dirpath = tempfile.mkdtemp()
        submit_id = self.d.add_submit(dirpath, "files", {
            "foo": "bar",
        })
        submit = self.d.view_submit(submit_id)
        assert submit.id == submit_id
        assert submit.tmp_path == dirpath
        assert submit.submit_type == "files"
        assert submit.data == {
            "foo": "bar",
        }

    def test_connect_no_create(self):
        AlembicVersion.__table__.drop(self.d.engine)
        self.d.connect(dsn=self.URI, create=False)
        assert "alembic_version" not in self.d.engine.table_names()
        self.d.connect(dsn=self.URI)
        assert "alembic_version" in self.d.engine.table_names()

    def test_view_submit_tasks(self):
        submit_id = self.d.add_submit(None, None, None)
        target_id = add_target(__file__, category="file")
        t1 = add_task(custom="1", submit_id=submit_id)
        t2 = add_task(custom="2", submit_id=submit_id)

        submit = self.d.view_submit(submit_id)
        assert submit.id == submit_id
        with pytest.raises(DetachedInstanceError):
            print submit.tasks

        submit = self.d.view_submit(submit_id, tasks=True)
        assert len(submit.tasks) == 2
        tasks = sorted((task.id, task) for task in submit.tasks)
        assert tasks[0][1].id == t1
        assert tasks[0][1].custom == "1"
        assert tasks[1][1].id == t2
        assert tasks[1][1].custom == "2"

    def test_task_set_options(self):
        t0 = add_task(__file__, options={"foo": "bar"})
        t1 = add_task(__file__, options="foo=bar")

        assert self.d.view_task(t0).options == {"foo": "bar"}
        assert self.d.view_task(t1).options == {"foo": "bar"}

    def test_error_action(self):
        task_id = add_task(__file__)
        self.d.add_error("message1", task_id)
        self.d.add_error("message2", task_id, "actionhere")
        e1, e2 = self.d.view_errors(task_id)
        assert e1.message == "message1"
        assert e1.action is None
        assert e2.message == "message2"
        assert e2.action == "actionhere"

    def test_view_tasks(self):
        t1 = add_task(__file__)
        t2 = add_task("http://example.com", category="url")
        tasks = self.d.view_tasks([t1, t2])
        assert tasks[0].to_dict() == self.d.view_task(t1).to_dict()
        assert tasks[1].to_dict() == self.d.view_task(t2).to_dict()

    def test_add_machine(self):
        self.d.add_machine("name1", "label", "1.2.3.4", "windows", None,
                           "tag1 tag2", "int0", "snap0", "5.6.7.8", 2043,
                           "virtualbox")
        self.d.add_machine("name2", "label", "1.2.3.4", "windows", "",
                           "tag1 tag2", "int0", "snap0", "5.6.7.8", 2043,
                           "virtualbox")
        self.d.add_machine("name3", "label", "1.2.3.4", "windows", "opt1 opt2",
                           "tag1 tag2", "int0", "snap0", "5.6.7.8", 2043,
                           "virtualbox")
        self.d.add_machine("name4",
                           "label",
                           "1.2.3.4",
                           "windows", ["opt3", "opt4"],
                           "tag1 tag2",
                           "int0",
                           "snap0",
                           "5.6.7.8",
                           2043,
                           "virtualbox",
                           reserved_by=1600)
        m1 = self.d.view_machine("name1")
        m2 = self.d.view_machine("name2")
        m3 = self.d.view_machine("name3")
        m4 = self.d.view_machine("name4")
        assert m1.options == []
        assert m2.options == []
        assert m3.options == ["opt1", "opt2"]
        assert m4.options == ["opt3", "opt4"]
        assert m1.manager == "virtualbox"
        assert m4.reserved_by == 1600

    def test_adding_task(self):
        now = datetime.datetime.now()
        id = add_task(__file__, "file", 0, "py", "free=yes", 3, "custom",
                      "owner", "machine1", "DogeOS", ["tag1"], False, False,
                      now, "regular", None, now)

        task = self.d.view_task(id)
        assert id is not None
        assert task.timeout == 0
        assert task.package == "py"
        assert task.options == {"free": "yes"}
        assert task.priority == 3
        assert task.custom == "custom"
        assert task.owner == "owner"
        assert task.machine == "machine1"
        assert task.platform == "DogeOS"
        assert len(task.tags) == 1
        assert task.tags[0].name == "tag1"
        assert task.memory == False
        assert task.enforce_timeout == False
        assert task.clock == now
        assert task.submit_id is None
        assert task.start_on == now
        assert len(task.targets) == 1
        assert task.targets[0].category == "file"
        assert task.targets[0].target == __file__

    def test_set_machine_rcparams(self):
        self.d.add_machine("name5", "label5", "1.2.3.4", "windows", None,
                           "tag1 tag2", "int0", "snap0", "5.6.7.8", 2043,
                           "virtualbox")

        self.d.set_machine_rcparams("label5", {
            "protocol": "rdp",
            "host": "127.0.0.1",
            "port": 3389,
        })

        m = self.d.view_machine("name5")
        assert m.rcparams == {
            "protocol": "rdp",
            "host": "127.0.0.1",
            "port": "3389",
        }

    def test_add_target_file(self):
        fd, sample_path = tempfile.mkstemp()
        os.write(fd, os.urandom(64))
        os.close(fd)
        target = File(sample_path)

        id = add_target(sample_path, "file")
        db_target = self.d.find_target(id=id)

        assert id is not None
        assert db_target.file_size == 64
        assert db_target.file_type == target.get_type()
        assert db_target.md5 == target.get_md5()
        assert db_target.crc32 == target.get_crc32()
        assert db_target.sha1 == target.get_sha1()
        assert db_target.sha256 == target.get_sha256()
        assert db_target.sha512 == target.get_sha512()
        assert db_target.ssdeep == target.get_ssdeep()
        assert db_target.category == "file"

    def test_add_target_url(self):
        target = URL("http://example.com/")

        id = add_target(target.url, "url")
        db_target = self.d.find_target(id=id)

        assert id is not None
        assert db_target.md5 == target.get_md5()
        assert db_target.crc32 == target.get_crc32()
        assert db_target.sha1 == target.get_sha1()
        assert db_target.sha256 == target.get_sha256()
        assert db_target.sha512 == target.get_sha512()
        assert db_target.ssdeep == target.get_ssdeep()
        assert db_target.category == "url"

    def test_find_target(self):
        fd, sample_path = tempfile.mkstemp()
        os.write(fd, os.urandom(64))
        os.close(fd)
        target = File(sample_path)
        id = add_target(sample_path, category="file")

        assert self.d.find_target(id=id).id == id
        assert self.d.find_target(crc32=target.get_crc32()).id == id
        assert self.d.find_target(md5=target.get_md5()).id == id
        assert self.d.find_target(sha1=target.get_sha1()).id == id
        assert self.d.find_target(sha256=target.get_sha256()).id == id
        assert self.d.find_target(sha512=target.get_sha512()).id == id

    def test_find_target_multifilter(self):
        ids = []
        paths = []
        target = None
        for x in range(2):
            fd, sample_path = tempfile.mkstemp()
            randbytes = os.urandom(64)
            paths.append(sample_path)
            os.write(fd, randbytes)
            os.close(fd)
            target = File(sample_path)
            ids.append(add_target(sample_path, category="file"))

        db_target = self.d.find_target(sha256=target.get_sha256(),
                                       target=paths[1])
        assert self.d.find_target(id=ids[0], md5=target.get_md5()) is None
        assert db_target.id == ids[1]

    def test_fetch_with_machine(self):
        future = datetime.datetime(2200, 5, 12, 12, 12)
        add_task(__file__, category="file", tags=["service"])
        t2 = add_task(__file__, category="file", machine="machine1")
        add_task(__file__, category="file", start_on=future)
        add_task(__file__, category="file")

        t = self.d.fetch(machine="machine1", service=False)

        assert t.id == t2
        assert t.status == "pending"

    def test_fetch_service_false(self):
        add_task(__file__, category="file", tags=["service"])
        t2 = add_task(__file__, category="file")

        t = self.d.fetch(service=False)
        assert t.id == t2
        assert t.status == "pending"

    def test_fetch_service_true(self):
        t1 = add_task(__file__, category="file", tags=["service"])
        add_task(__file__, category="file", machine="machine1")
        add_task(__file__)
        add_task(__file__)

        task = self.d.fetch()
        assert task.id == t1
        assert task.status == "pending"

    def test_fetch_use_start_on_true(self):
        future = datetime.datetime(2200, 5, 12, 12, 12)
        add_task(__file__, category="file", start_on=future, priority=999)
        t2 = add_task(__file__, category="file")
        t = self.d.fetch(service=False)

        assert t.id == t2
        assert t.status == "pending"

    def test_fetch_use_start_on_false(self):
        future = datetime.datetime(2200, 5, 12, 12, 12)
        t1 = add_task(__file__, category="file", start_on=future, priority=999)
        add_task(__file__, category="file")

        t = self.d.fetch(use_start_on=False, service=False)
        assert t.id == t1
        assert t.status == "pending"

    def test_fetch_use_exclude(self):

        t1 = add_task(__file__, category="file", priority=999)
        t2 = add_task(__file__, category="file", priority=999)
        t3 = add_task(__file__, category="file", priority=999)
        t4 = add_task(__file__, category="file", priority=999)

        t = self.d.fetch(service=False, exclude=[t1, t2, t3])
        assert t.id == t4
        assert t.status == "pending"

    def test_fetch_specific_task(self):
        t1 = add_task(__file__, category="file", priority=999)
        t2 = add_task(__file__, category="file", priority=999)
        t = self.d.fetch(task_id=t1)
        assert t.id == t1
        assert t.status == "pending"

    def test_lock_machine(self):
        t1 = add_task(__file__, category="file", tags=["app1", "office7"])
        t2 = add_task(__file__, category="file", tags=["app1", "office15"])

        self.d.add_machine("name1", "name1", "1.2.3.4", "windows", "",
                           "app1,office7", "int0", "snap0", "5.6.7.8", 2043,
                           "virtualbox")
        self.d.add_machine("name2", "name2", "1.2.3.4", "DogeOS", "opt1 opt2",
                           "office13", "int0", "snap0", "5.6.7.8", 2043,
                           "virtualbox")
        self.d.add_machine("name3", "name3", "1.2.3.4", "CoffeeOS",
                           ["opt3", "opt4"], "cofOS,office7", "int0", "snap0",
                           "5.6.7.8", 2043, "virtualbox")

        task1 = self.d.view_task(t1)
        task2 = self.d.view_task(t2)

        m1 = self.d.lock_machine(tags=task1.tags)
        assert m1.locked
        assert m1.name == "name1"
        with pytest.raises(CuckooOperationalError):
            self.d.lock_machine(platform="DogeOS", tags=task2.tags)
        m2 = self.d.lock_machine(platform="DogeOS")
        assert m2.name == "name2"
        m3 = self.d.lock_machine(label="name3")
        assert m3.locked
        assert m3.name == "name3"

    def test_list_tasks(self):
        t1 = add_task(__file__,
                      category="file",
                      owner="doge",
                      options={"route": "vpn511"})
        t2 = add_task(__file__, category="file")
        add_task(__file__, category="file")
        self.d.set_status(t2, "reported")
        self.d.set_status(t1, "reported")

        tasks = self.d.list_tasks(owner="doge", status="reported")
        tasks2 = self.d.list_tasks()
        tasks3 = self.d.list_tasks(status="reported")

        assert tasks[0].id == t1
        assert len(tasks2) == 3
        assert len(tasks3) == 2

    def test_list_tasks_between(self):
        for x in range(5):
            add_task(__file__, category="file")

        tasks = self.d.list_tasks(filter_by="id",
                                  operators="between",
                                  values=(1, 3))
        assert len(tasks) == 3

    def test_list_tasks_multiple_filter(self):
        ids = []
        future = None
        for x in range(10):
            id = add_task(__file__, category="file")
            ids.append(id)
            future = datetime.datetime.now() + datetime.timedelta(days=id)
            ses = self.d.Session()
            task = ses.query(Task).get(id)
            task.completed_on = future
            ses.commit()
            ses.close()

        tasks = self.d.list_tasks(filter_by=["id", "completed_on"],
                                  operators=[">", "<"],
                                  values=[4, future],
                                  order_by="id",
                                  limit=1)
        assert len(tasks) == 1
        assert tasks[0].id == 5

    def test_list_tasks_offset_limit(self):
        for x in range(10):
            add_task(__file__, category="file")

        tasks = self.d.list_tasks(offset=5, limit=10, order_by="id")
        assert len(tasks) == 5
        assert tasks[4].id == 10

    def test_list_tasks_notvalue(self):
        for x in range(10):
            id = add_task(__file__, category="file")
            if id % 2 == 0:
                self.d.set_status(id, "running")

        tasks = self.d.list_tasks(filter_by="status",
                                  operators="!=",
                                  values="running",
                                  order_by="id")
        assert len(tasks) == 5
        assert tasks[4].id == 9

    def test_list_tasks_noresults(self):
        for x in range(5):
            add_task(__file__, category="file")
        tasks = self.d.list_tasks(status="reported")
        assert tasks == []

    def test_get_available_machines(self):
        self.d.add_machine("name1", "name1", "1.2.3.4", "windows", "",
                           "app1,office7", "int0", "snap0", "5.6.7.8", 2043,
                           "virtualbox")
        self.d.add_machine("name2", "name2", "1.2.3.4", "DogeOS", "opt1 opt2",
                           "office13", "int0", "snap0", "5.6.7.8", 2043,
                           "virtualbox")
        self.d.add_machine("name3", "name3", "1.2.3.4", "CoffeeOS",
                           ["opt3", "opt4"], "cofOS,office7", "int0", "snap0",
                           "5.6.7.8", 2043, "virtualbox")
        self.d.machine_reserve(label="name2", task_id=1337)
        self.d.lock_machine(label="name3")
        available = self.d.get_available_machines()
        names = [m["name"] for m in [db_m.to_dict() for db_m in available]]

        assert len(available) == 2
        assert "name2" in names
        assert "name1" in names

    def test_unlock_machine(self):
        self.d.add_machine("name1", "name1", "1.2.3.4", "windows", "",
                           "app1,office7", "int0", "snap0", "5.6.7.8", 2043,
                           "virtualbox")
        self.d.lock_machine(label="name1")

        assert self.d.view_machine(name="name1").locked
        self.d.unlock_machine(label="name1")
        assert not self.d.view_machine(name="name1").locked

    def test_list_machines(self):
        self.d.add_machine("name1", "name1", "1.2.3.4", "windows", "",
                           "app1,office7", "int0", "snap0", "5.6.7.8", 2043,
                           "virtualbox")
        self.d.add_machine("name2", "name2", "1.2.3.4", "DogeOS", "opt1 opt2",
                           "office13", "int0", "snap0", "5.6.7.8", 2043,
                           "virtualbox")
        allmachines = self.d.list_machines()
        names = [m["name"] for m in [db_m.to_dict() for db_m in allmachines]]

        assert len(allmachines) == 2
        assert "name2" in names
        assert "name1" in names

    def test_machine_reserve(self):
        self.d.add_machine("name1", "name1", "1.2.3.4", "windows", "",
                           "app1,office7", "int0", "snap0", "5.6.7.8", 2043,
                           "virtualbox")
        assert self.d.view_machine(name="name1").reserved_by is None
        self.d.machine_reserve(label="name1", task_id=42)
        assert self.d.view_machine(name="name1").reserved_by == 42

    def test_clear_reservation(self):
        self.d.add_machine("name1", "name1", "1.2.3.4", "windows", "",
                           "app1,office7", "int0", "snap0", "5.6.7.8", 2043,
                           "virtualbox")
        self.d.machine_reserve(label="name1", task_id=42)
        assert self.d.view_machine(name="name1").reserved_by == 42
        self.d.clear_reservation(label="name1")
        assert self.d.view_machine(name="name1").reserved_by is None

    def test_clean_machines(self):
        for x in range(6):
            name = "name%s" % x
            self.d.add_machine(name, name, "1.2.3.4", "windows", "",
                               "app1,office7", "int0", "snap0", "5.6.7.8",
                               2043, "virtualbox")

        assert len(self.d.list_machines()) == 6
        self.d.clean_machines()
        assert len(self.d.list_machines()) == 0

    def test_target_to_dict(self):
        fd, sample_path = tempfile.mkstemp()
        os.write(fd, os.urandom(64))
        os.close(fd)
        target = File(sample_path)
        id = add_target(sample_path, category="file")
        db_target = self.d.find_target(id=id)
        db_target = db_target.to_dict()

        assert db_target["id"] == id
        assert db_target["file_size"] == 64
        assert db_target["file_type"] == target.get_type()
        assert db_target["md5"] == target.get_md5()
        assert db_target["crc32"] == target.get_crc32()
        assert db_target["sha1"] == target.get_sha1()
        assert db_target["sha256"] == target.get_sha256()
        assert db_target["sha512"] == target.get_sha512()
        assert db_target["ssdeep"] == target.get_ssdeep()
        assert db_target["category"] == "file"
        assert db_target["target"] == sample_path

    def test_task_multiple_targets(self):
        db_targets = []
        task_id = add_task()
        for x in range(10):
            fd, sample_path = tempfile.mkstemp()
            os.write(fd, os.urandom(64))
            os.close(fd)
            add_target(sample_path, category="file", task_id=task_id)

        task = self.d.view_task(task_id)
        assert task.id == task_id
        assert len(task.targets) == 10
Esempio n. 5
0
def migrate_cwd():
    db = Database()
    log.warning(
        "This is the first time you're running Cuckoo after updating your "
        "local version of Cuckoo. We're going to update files in your CWD "
        "that require updating. Note that we'll first ensure that no custom "
        "patches have been applied by you before applying any modifications "
        "of our own.")

    # Remove now-obsolete index_*.yar files.
    for filename in os.listdir(cwd("yara")):
        if filename.startswith("index_") and filename.endswith(".yar"):
            os.remove(cwd("yara", filename))

    # Create new directories if not present yet.
    mkdir(cwd("stuff"))
    mkdir(cwd("yara", "office"))

    # Create the new $CWD/whitelist/ directory.
    if not os.path.exists(cwd("whitelist")):
        shutil.copytree(cwd("..", "data", "whitelist", private=True),
                        cwd("whitelist"))

    # Create the new $CWD/yara/dumpmem/ directory.
    if not os.path.exists(cwd("yara", "dumpmem")):
        mkdir(cwd("yara", "dumpmem"))

    hashes = {}
    for line in open(cwd("cwd", "hashes.txt", private=True), "rb"):
        if not line.strip() or line.startswith("#"):
            continue
        hash_, filename = line.split()
        hashes[filename] = hashes.get(filename, []) + [hash_]

    # We remove $CWD/monitor/latest upfront if it's a symbolic link, because
    # our migration code doesn't properly handle symbolic links.
    if os.path.islink(cwd("monitor", "latest")):
        os.remove(cwd("monitor", "latest"))

    modified, outdated, deleted = [], [], []
    for filename, hashes in hashes.items():
        if not os.path.exists(cwd(filename)):
            if hashes[-1] != "0" * 40:
                outdated.append(filename)
            continue
        hash_ = hashlib.sha1(open(cwd(filename), "rb").read()).hexdigest()
        if hash_ not in hashes:
            modified.append(filename)
        elif hashes[-1] == "0" * 40:
            deleted.append(filename)
        elif hash_ != hashes[-1]:
            outdated.append(filename)

    if modified:
        log.error(
            "One or more files in the CWD have been modified outside of "
            "regular Cuckoo usage. Due to these changes Cuckoo isn't able to "
            "automatically upgrade your setup.")

        for filename in sorted(modified):
            log.warning("Modified file: %s (=> %s)", filename, cwd(filename))

        log.error("Moving forward you have two options:")
        log.warning(
            "1) You make a backup of the affected files, remove their "
            "presence in the CWD (yes, actually 'rm -f' the file), and "
            "re-run Cuckoo to automatically restore the new version of the "
            "file. Afterwards you'll be able to re-apply any changes as you "
            "like.")
        log.warning(
            "2) You revert back to the version of Cuckoo you were on "
            "previously and accept that manual changes that have not been "
            "merged upstream require additional maintenance that you'll "
            "pick up at a later point in time.")

        sys.exit(1)

    for filename in sorted(deleted):
        log.debug("Deleted %s", filename)
        os.unlink(cwd(filename))

    for filename in sorted(outdated):
        filepath = cwd("..", "data", filename, private=True)
        if not os.path.exists(filepath):
            log.debug(
                "Failed to upgrade file not shipped with this release: %s",
                filename)
            continue

        log.debug("Upgraded %s", filename)
        if not os.path.exists(os.path.dirname(cwd(filename))):
            os.makedirs(os.path.dirname(cwd(filename)))
        shutil.copy(filepath, cwd(filename))

    log.info("Checking if any task directories are missing")
    for db_task in db.list_tasks(status=TASK_PENDING, details=False):
        task = Task(db_task)
        if not task.dir_exists():
            task.create_empty()
            for target in task.targets:
                if target.is_file and not os.path.exists(target.copied_binary):
                    target.copy()
        else:
            # Always call this so that missing (newly added) directories
            # are created
            task.create_dirs()

    log.info("Automated migration of your CWD was successful! Continuing "
             "execution of Cuckoo as expected.")