def test_mongo_connect_notenabled(p): set_cwd(tempfile.mkdtemp()) cuckoo_create() m = Mongo() m.init() m.connect() p.MongoClient.assert_not_called()
def test_mongo_connect_store_file(): set_cwd(tempfile.mkdtemp()) cuckoo_create(cfg={ "reporting": { "mongodb": { "enabled": True, "db": "cuckootest", }, }, }) mongo.init() assert mongo.database == "cuckootest" fd, filepath = tempfile.mkstemp() os.write(fd, "hello world") os.close(fd) f = File(filepath) r = MongoDB() r.init_once() id1 = r.store_file(f, "foobar.txt") id2 = r.store_file(f, "foobar.txt") assert id1 == id2 assert mongo.db.fs.files.find_one({ "sha256": f.get_sha256(), })["_id"] == id1 assert mongo.grid.get(id1).read() == "hello world"
def test_initialize_global(self): set_cwd(tempfile.mkdtemp()) cuckoo_create(cfg={ "cuckoo": { "cuckoo": { "machinery": "virtualbox", }, # This unittest will actually start the ResultServer. "resultserver": { "ip": "127.0.0.1", "port": 3000, }, }, }) db.connect() self.m = VirtualBox() self.m.set_options(Config("virtualbox")) self.m._initialize("virtualbox") m, = db.list_machines() assert m.label == "cuckoo1" assert m.interface == "vboxnet0" assert m.ip == "192.168.56.101" assert m.options == [] assert m.platform == "windows" assert m.resultserver_ip == "127.0.0.1" assert m.resultserver_port == 3000 assert m.tags == []
def test_rooter_client(p, q, r): set_cwd(tempfile.mkdtemp()) cuckoo_create() s = p.socket.return_value s.recv.return_value = json.dumps({ "exception": None, "output": "thisisoutput", }) assert rooter( "command", "arg1", "arg2", arg3="foo", arg4="bar" ) == "thisisoutput" s.bind.assert_called_once() s.connect.assert_called_once_with("/tmp/cuckoo-rooter") s.send.assert_called_once_with(json.dumps({ "command": "command", "args": ( "arg1", "arg2", ), "kwargs": { "arg3": "foo", "arg4": "bar", } })) q.acquire.assert_called_once() q.release.assert_called_once()
def test_monitor_latest_symlink(self): set_cwd(tempfile.mktemp()) cuckoo_create() monitor = open(cwd("monitor", "latest"), "rb").read().strip() os.unlink(cwd("monitor", "latest")) os.symlink(cwd("monitor", monitor), cwd("monitor", "latest")) migrate_cwd()
def test_process_log_taskid(p, q): set_cwd(tempfile.mkdtemp()) cuckoo_create() init_console_logging(logging.DEBUG) init_logfile("process-p0.json") def log_something(target, copy_path, task): logger("test message", action="hello.world", status="success") q.side_effect = log_something process_task({ "id": 12345, "category": "url", "target": "http://google.com/", "package": "ie", "options": {}, "custom": None, }) for line in open(cwd("log", "process-p0.json"), "rb"): obj = json.loads(line) if obj["action"] == "hello.world": assert obj["task_id"] == 12345 break else: raise
def test_process_json_logging(): set_cwd(tempfile.mkdtemp()) cuckoo_create() init_yara() init_logfile("process-p0.json") def process_tasks(instance, maxcount): logger("foo bar", action="hello.world", status="success") with mock.patch("cuckoo.main.Database"): with mock.patch("cuckoo.main.process_tasks") as p1: with mock.patch("time.time") as p2: p1.side_effect = process_tasks p2.return_value = 1484232003 main.main( ("--cwd", cwd(), "process", "p0"), standalone_mode=False ) assert json.load(open(cwd("log", "process-p0.json"), "rb")) == { "asctime": mock.ANY, "action": "hello.world", "level": "info", "message": "foo bar", "status": "success", "task_id": None, "time": 1484232003, }
def test_init_routing_vpns(p): set_cwd(tempfile.mkdtemp()) cuckoo_create(cfg={ "routing": { "vpn": { "enabled": True, "vpns": [ "1", "2", ], }, "1": { "name": "1", "interface": "tun1", "rt_table": "main", }, "2": { "name": "2", "interface": "tun2", "rt_table": "main", }, }, }) init_routing() assert p.call_count == 12 p.assert_any_call("nic_available", "tun1") p.assert_any_call("rt_available", "main") p.assert_any_call("nic_available", "tun2") p.assert_any_call("disable_nat", "tun1") p.assert_any_call("disable_nat", "tun2") p.assert_any_call("enable_nat", "tun1") p.assert_any_call("enable_nat", "tun2") p.assert_any_call("flush_rttable", "main") p.assert_any_call("init_rttable", "main", "tun1") p.assert_any_call("init_rttable", "main", "tun2")
def test_init_rooter_exceptions(p): set_cwd(tempfile.mkdtemp()) cuckoo_create(cfg={ "routing": { "routing": { "internet": "eth0", }, }, }) p.error = Exception e = Exception() e.strerror = "No such file or directory" p.socket.return_value.connect.side_effect = e with pytest.raises(CuckooStartupError) as e: init_rooter() e.match("different Unix socket path") e = Exception() e.strerror = "Connection refused" p.socket.return_value.connect.side_effect = e with pytest.raises(CuckooStartupError) as e: init_rooter() e.match("rooter is not actually running") e = Exception() e.strerror = "Permission denied" p.socket.return_value.connect.side_effect = e with pytest.raises(CuckooStartupError) as e: init_rooter() e.match("due to incorrect permissions")
def test_init_routing_internet_exc(p): set_cwd(tempfile.mkdtemp()) cuckoo_create(cfg={ "routing": { "routing": { "internet": "eth0", }, }, }) def nic_notavail(cmd, arg): return False def rt_notavail(cmd, arg): if cmd == "rt_available": return False return True p.side_effect = nic_notavail with pytest.raises(CuckooStartupError) as e: init_routing() p.assert_called_once() e.match("configured as dirty line is not") p.side_effect = rt_notavail with pytest.raises(CuckooStartupError) as e: init_routing() e.match("routing table that has been")
def test_plugin_enabled(self, p): set_cwd(tempfile.mkdtemp()) cuckoo_create(cfg={ "memory": { "pslist": { "enabled": True, }, "psxview": { "enabled": False, }, }, }) p.return_value = 12345 m = VolatilityManager(None, "WinXPSP2x86") assert m.vol.addr_space == 12345 assert m.enabled("pslist", []) is True assert m.enabled("psxview", []) is False assert m.enabled("sockscan", ["winxp"]) is True assert m.enabled("netscan", ["vista", "win7"]) is False m = VolatilityManager(None, "Win7SP1x64") assert m.enabled("pslist", []) is True assert m.enabled("psxview", []) is False assert m.enabled("sockscan", ["winxp"]) is False assert m.enabled("netscan", ["vista", "win7"]) is True m = VolatilityManager(None, "Win10x64") assert m.enabled("pslist", []) is True assert m.enabled("psxview", []) is False assert m.enabled("sockscan", ["winxp"]) is False assert m.enabled("netscan", ["vista", "win7"]) is False
def test_bson_limit(self): set_cwd(tempfile.mkdtemp()) cuckoo_create() ba = BehaviorAnalysis() ba.set_path(cwd(analysis=1)) ba.set_task({ "id": 1, }) mkdir(cwd(analysis=1)) mkdir(cwd("logs", analysis=1)) # 256mb should be fine, right? with open(cwd("logs", "1.txt", analysis=1), "wb") as f: f.write("A"*256*1024*1024) with open(cwd("logs", "2.txt", analysis=1), "wb") as f: f.write("A"*1024*1024) assert ba.run() == {} assert sorted(list(ba._enum_logs())) == [ cwd("logs", "2.txt", analysis=1), ]
def test_path(self, p): set_cwd(tempfile.mkdtemp(prefix=".")) cuckoo_create() mkdir(cwd(analysis=1)) def create(): mkdir(cwd("suricata", "files", analysis=1)) f = open(cwd("suricata", "files", "file.1", analysis=1), "wb") f.write("a") f = open(cwd("suricata", "eve.json", analysis=1), "wb") f.write("") f = open(cwd("suricata", "files-json.log", analysis=1), "wb") f.write(json.dumps({ "id": 1, "size": 1, "filename": "a.txt", })) open(cwd("dump.pcap", analysis=1), "wb").write("pcap") s = Suricata() s.set_path(cwd(analysis=1)) s.set_options({}) s.process_pcap_binary = create s.run()
def test_default_cwd(self, p): set_cwd(tempfile.mkdtemp()) cuckoo_create() with chdir(cwd()): decide_cwd(".") cuckoo_init(logging.INFO, self.ctx) p.assert_called_once_with("cuckoo community")
def test_clean_keepdirs(p): set_cwd(tempfile.mkdtemp()) cuckoo_create() with open(cwd("log", "cuckoo.log"), "wb") as f: f.write("this is a log file") os.mkdir(cwd(analysis=1)) with open(cwd("analysis.log", analysis=1), "wb") as f: f.write("this is also a log file") with open(cwd("storage", "binaries", "a"*40), "wb") as f: f.write("this is a binary file") assert os.path.isdir(cwd("log")) assert os.path.exists(cwd("log", "cuckoo.log")) assert os.path.exists(cwd("storage", "analyses")) assert os.path.exists(cwd("storage", "analyses", "1")) assert os.path.exists(cwd("storage", "analyses", "1", "analysis.log")) assert os.path.exists(cwd("storage", "baseline")) assert os.path.exists(cwd("storage", "binaries")) assert os.path.exists(cwd("storage", "binaries", "a"*40)) cuckoo_clean() assert os.path.isdir(cwd("log")) assert not os.path.exists(cwd("log", "cuckoo.log")) assert os.path.exists(cwd("storage", "analyses")) assert not os.path.exists(cwd("storage", "analyses", "1")) assert not os.path.exists(cwd("storage", "analyses", "1", "analysis.log")) assert os.path.exists(cwd("storage", "baseline")) assert os.path.exists(cwd("storage", "binaries")) assert not os.path.exists(cwd("storage", "binaries", "a"*40))
def setup(self): set_cwd(tempfile.mkdtemp()) cuckoo_create() db.connect() api.app.config["TESTING"] = True self.app = api.app.test_client()
def test_yara_offsets(): set_cwd(tempfile.mkdtemp()) cuckoo_create() init_yara() buf = ( # The SSEXY payload as per vmdetect.yar "66 0F 70 ?? ?? 66 0F DB ?? ?? ?? ?? " "?? 66 0F DB ?? ?? ?? ?? ?? 66 0F EF " # A VirtualBox MAC address. "30 38 2d 30 30 2d 32 37" ) filepath = Files.temp_put( "A"*64 + buf.replace("??", "00").replace(" ", "").decode("hex") ) assert File(filepath).get_yara() == [{ "meta": { "description": "Possibly employs anti-virtualization techniques", "author": "nex" }, "name": "vmdetect", "offsets": { "ssexy": [ (64, 1), ], "virtualbox_mac_1a": [ (88, 0), ], }, "strings": [ "MDgtMDAtMjc=", "Zg9wAABmD9sAAAAAAGYP2wAAAAAAZg/v", ], }]
def test_log_error_action(): set_cwd(tempfile.mkdtemp()) cuckoo_create() db.connect() reset_logging() init_console_logging(logging.DEBUG) task_id = db.add_path(__file__) assert db.view_errors(task_id) == [] logging.getLogger(__name__).error("message1", extra={ "error_action": "erroraction", "task_id": task_id, }) logging.getLogger(__name__).error("message2", extra={ "task_id": task_id, }) errors = db.view_errors(task_id) assert len(errors) == 2 assert errors[0].message == "message1" assert errors[0].action == "erroraction" assert errors[1].message == "message2" assert errors[1].action is None
def test_basics(): set_cwd(tempfile.mkdtemp()) cuckoo_create() mkdir(cwd(analysis=1)) init_yara() em = ExtractManager(1) em.write_extracted("foo", "bar") filepath = cwd("extracted", "0.foo", analysis=1) assert open(filepath, "rb").read() == "bar" scr = Scripting() cmd = scr.parse_command( "powershell -e %s" % "foobar".encode("utf-16le").encode("base64") ) em.push_script({ "pid": 1, "first_seen": 2, }, cmd) filepath = cwd("extracted", "0.ps1", analysis=1) assert open(filepath, "rb").read() == "foobar" em.push_command_line( "powershell -e %s" % "world!".encode("utf-16le").encode("base64") ) filepath = cwd("extracted", "1.ps1", analysis=1) assert open(filepath, "rb").read() == "world!"
def test_yara_no_description(): set_cwd(tempfile.mkdtemp()) cuckoo_create() open(cwd("yara", "binaries", "empty.yara"), "wb").write(""" rule EmptyRule { condition: 1 } rule DescrRule { meta: description = "this is description" condition: 1 } """) init_yara() a, b = File(Files.temp_put("hello")).get_yara() assert a["name"] == "EmptyRule" assert a["meta"] == { "description": "(no description)", } assert b["name"] == "DescrRule" assert b["meta"] == { "description": "this is description", }
def test_no_superfluous_conf(p): """Tests that upon CWD creation no superfluous configuration values are writted out (which may happen after a configuration migration).""" set_cwd(tempfile.mkdtemp()) cuckoo_create() Config.from_confdir(cwd("conf")) p.error.assert_not_called()
def test_clean_dropdb(p): set_cwd(tempfile.mkdtemp()) cuckoo_create() cuckoo_clean() p.return_value.connect.assert_called_once() p.return_value.drop.assert_called_once_with()
def test_do_not_get_exception(self): set_cwd(tempfile.mkdtemp()) cuckoo_create() responses.add(responses.GET, "http://1.2.3.4:8000/", status=501) gm = GuestManager("cuckoo1", "1.2.3.4", "windows", 1, None) assert gm.get("/", do_raise=False).status_code == 501
def am_init(options={}, cfg={}): set_cwd(tempfile.mkdtemp()) cuckoo_create(cfg=cfg) class task(object): def __init__(self): self.id = 1234 self.category = "file" self.target = __file__ self.options = options def to_dict(self): return Dictionary(self.__dict__) def to_json(self): return json.dumps(self.to_dict()) class sample(object): sha256 = sha256_ class machine(object): ip = "1.2.3.4" interface = "vboxnet0" with mock.patch("cuckoo.core.scheduler.Database") as p: p.return_value.view_task.return_value = task() am = AnalysisManager(1234, None) am.machine = machine p.return_value.view_sample.return_value = sample() return am
def test_invalid_configuration(self): # Explicitly want a clean CWD here. set_cwd(tempfile.mkdtemp()) cuckoo_create() cf = CuckooFeedback() with pytest.raises(CuckooFeedbackError) as e: cf.send_feedback(CuckooFeedbackObject( name=None, email="*****@*****.**", company="foo" )) e.match("Could not validate") with pytest.raises(CuckooFeedbackError) as e: cf.send_feedback(CuckooFeedbackObject( name="foo", email=None, company="foo" )) e.match("Could not validate") with pytest.raises(CuckooFeedbackError) as e: cf.send_feedback(CuckooFeedbackObject( name="foo", email="a@b,com", company="foo" )) e.match("Could not validate") with pytest.raises(CuckooFeedbackError) as e: cf.send_feedback(CuckooFeedbackObject( name="foo", email="*****@*****.**", company=None )) e.match("Could not validate")
def test_api_fetch_once(self, p, client): set_cwd(tempfile.mkdtemp()) cuckoo_create() Database().connect() p.return_value = { "version": "2.0.5", "blogposts": [{ "title": "title", "important": False, "oneline": "this is oneliner", "url": "https://cuckoosandbox.org/blog/blogpost", "date": "today or tomorrow", }], } # Clear the 'updates' variable. from cuckoo.web.controllers.cuckoo.api import updates updates.clear() r = client.get("/cuckoo/api/status") assert r.status_code == 200 r = client.get("/cuckoo/api/status") assert r.status_code == 200 r = json.loads(r.content)["data"] assert r["latest_version"] == "2.0.5" assert r["blogposts"] == [mock.ANY] p.assert_called_once()
def test_load_signatures(): set_cwd(tempfile.mkdtemp()) cuckoo_create() shutil.rmtree(cwd("signatures")) shutil.copytree("tests/files/enumplugins", cwd("signatures")) sys.modules.pop("signatures", None) load_signatures() # Ensure that the Signatures are loaded in the global list. names = [] for sig in cuckoo.signatures: names.append(sig.__module__) assert "signatures.sig1" in names assert "signatures.sig2" in names assert "signatures.sig3" in names # Ensure that the Signatures are loaded in the RunSignatures object. RunSignatures.init_once() rs, names = RunSignatures({}), [] for sig in rs.signatures: names.append(sig.__class__.__name__) assert "Sig1" in names assert "Sig2" in names assert "Sig3" in names
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_init_star_multiple(self): cuckoo_create(cfg={ "virtualbox": { "virtualbox": { "machines": [ "cuckoo2", "cuckoo3", ], }, "cuckoo2": { "ip": "192.168.56.102", }, "cuckoo3": { "ip": "192.168.56.103", }, "notexistingvm": { "ip": "1.2.3.4", }, }, }) assert config("virtualbox:virtualbox:machines") == [ "cuckoo2", "cuckoo3" ] assert config("virtualbox:cuckoo2:ip") == "192.168.56.102" assert config("virtualbox:cuckoo3:ip") == "192.168.56.103" assert config("virtualbox:notexistingvm:ip") is None
def _test_api_status_cpucount(self, p, client): set_cwd(tempfile.mkdtemp()) cuckoo_create() Database().connect() p.return_value = 2 r = client.get("/cuckoo/api/status") assert r.status_code == 200 assert json.loads(r.content)["cpucount"] == 2
def test_process_dodelete(r, s, p): set_cwd(tempfile.mkdtemp()) cuckoo_create( cfg={ "cuckoo": { "cuckoo": { "delete_original": True, "delete_bin_copy": True, }, }, }) filepath1 = Files.temp_put("hello world") filepath2 = Files.create(cwd("storage", "binaries"), "A" * 40, "binary") process(filepath1, filepath2, 1) assert not os.path.exists(filepath1) assert not os.path.exists(filepath2)
def test_logger(): set_cwd(tempfile.mkdtemp()) cuckoo_create() init_logfile("cuckoo.json") with mock.patch("time.time") as p: p.return_value = 1484232001 logger("test %s", "message", action="a", status="b") assert json.load(open(cwd("log", "cuckoo.json"), "rb")) == { "asctime": mock.ANY, "action": "a", "level": "info", "message": "test message", "status": "b", "task_id": None, "time": 1484232001, }
def test_has_signatures(self, p): set_cwd(tempfile.mkdtemp()) sys.modules.pop("signatures", None) sys.modules.pop("signatures.android", None) sys.modules.pop("signatures.cross", None) sys.modules.pop("signatures.darwin", None) sys.modules.pop("signatures.extractor", None) sys.modules.pop("signatures.linux", None) sys.modules.pop("signatures.network", None) sys.modules.pop("signatures.windows", None) cuckoo_create() shutil.copy( "tests/files/enumplugins/sig1.py", cwd("signatures", "windows", "foobar.py") ) cuckoo.signatures = [] cuckoo_init(logging.INFO, self.ctx) p.assert_not_called()
def test_connect_pg(p, q): set_cwd(tempfile.mkdtemp()) cuckoo_create(cfg={ "cuckoo": { "database": { "connection": "postgresql://*****:*****@localhost/foobar", "timeout": 120, } } }) db = Database() db.connect(create=False) q.assert_called_once_with( "postgresql://*****:*****@localhost/foobar", connect_args={"sslmode": "disable"} ) assert db.engine.pool_timeout == 120
def test_clean_dropmongo(p, q): set_cwd(tempfile.mkdtemp()) cuckoo_create( cfg={ "reporting": { "mongodb": { "enabled": True, "host": "host", "port": 13337, }, }, }) cuckoo_clean() p.init.assert_called_once_with() p.connect.assert_called_once_with() p.drop.assert_called_once_with() p.close.assert_called_once_with()
def test_feedback_enabled(p, q): set_cwd(tempfile.mkdtemp()) cuckoo_create() faketask = {"id": 1} r = Feedback() r.set_path("tests/files/sample_analysis_storage") r.set_task(faketask) r.run({ "debug": { "errors": [ "a", "b", ], }, }) q.assert_called_once() p.return_value.send_feedback.assert_called_once()
def test_empty_pcap(self, p): set_cwd(tempfile.mkdtemp()) cuckoo_create(cfg={ "cuckoo": { "processing": { "sort_pcap": True, }, }, }) mkdir(cwd(analysis=1)) shutil.copy("tests/files/pcap/empty.pcap", cwd("dump.pcap", analysis=1)) na = NetworkAnalysis() na.set_path(cwd(analysis=1)) na.set_options({}) na.run() p.warning.assert_not_called()
def test_yara_externals(): set_cwd(tempfile.mkdtemp()) cuckoo_create() open(cwd("yara", "office", "external.yara"), "wb").write(""" rule ExternalRule { condition: filename matches /document.xml/ } """) init_yara() assert not File(Files.temp_put("")).get_yara("office") assert not File(Files.temp_put("hello")).get_yara("office", { "filename": "hello.jpg", }) a, = File(Files.temp_put("hello")).get_yara("office", { "filename": "document.xml", }) assert a["name"] == "ExternalRule"
def test_no_sorted_pcap(self): set_cwd(self.mkdtemp()) cuckoo_create(cfg={ "cuckoo": { "processing": { "sort_pcap": False, }, }, }) mkdir(cwd(analysis=1)) shutil.copy( "tests/files/sample_analysis_storage/dump.pcap", cwd("dump.pcap", analysis=1) ) na = NetworkAnalysis() na.set_options({}) na.set_path(cwd(analysis=1)) na.run() assert not os.path.exists(cwd("dump_sorted.pcap", analysis=1))
def test_mongodb_offline(p, q, r, s): set_cwd(tempfile.mkdtemp()) cuckoo_create(cfg={ "reporting": { "mongodb": { "enabled": True, }, }, }) r.side_effect = socket.error("error") db = p.return_value.__getitem__.return_value db.collection_names.side_effect = pymongo.errors.PyMongoError("error") with pytest.raises(CuckooCriticalError) as e: mongo.init() mongo.connect() e.match("Unable to connect to MongoDB") s.warning.assert_called_once()
def test_yes_sorted_pcap(self): set_cwd(tempfile.mkdtemp()) cuckoo_create({ "cuckoo": { "network": { "sort_pcap": True, }, }, }) mkdir(cwd(analysis=1)) shutil.copy( "tests/files/sample_analysis_storage/dump.pcap", cwd("dump.pcap", analysis=1) ) na = NetworkAnalysis() na.set_options({}) na.set_path(cwd(analysis=1)) na.run() assert os.path.exists(cwd("dump_sorted.pcap", analysis=1))
def test_new_directory(self): set_cwd(tempfile.mkdtemp()) cuckoo_create() shutil.rmtree(cwd("yara", "scripts")) shutil.rmtree(cwd("yara", "shellcode")) shutil.rmtree(cwd("stuff")) shutil.rmtree(cwd("whitelist")) open(cwd("yara", "index_binaries.yar"), "wb").write("hello") migrate_cwd() # TODO Move this to its own 2.0.2 -> 2.0.3 migration handler. assert os.path.exists(cwd("yara", "scripts", ".gitignore")) assert os.path.exists(cwd("yara", "shellcode", ".gitignore")) # TODO Move this to its own 2.0.3 -> 2.0.4 migration handler. assert os.path.exists(cwd("stuff")) assert os.path.exists(cwd("whitelist")) assert open( cwd("whitelist", "domain.txt"), "rb").read().strip() == ("# You can add whitelisted domains here.") assert not os.path.exists(cwd("yara", "index_binaries.yar"))
def test_scheduler_initialize(p): set_cwd(tempfile.mkdtemp()) cuckoo_create( cfg={ "cuckoo": { "cuckoo": { "machinery": "machin3", }, }, "routing": { "routing": { "internet": "intern0t", }, "vpn": { "enabled": True, "vpns": [ "a", ], }, "a": { "name": "a", "interface": "vpnint0", }, }, }) Database().connect() s = Scheduler() m = mock.MagicMock() m.return_value.machines.return_value = [ Dictionary(name="cuckoo1", interface="int1", ip="1.2.3.4"), Dictionary(name="cuckoo2", interface="int2", ip="5.6.7.8"), ] with mock.patch.dict(cuckoo.machinery.plugins, {"machin3": m}): s.initialize() m.return_value.initialize.assert_called_once_with("machin3") assert p.call_count == 4 p.assert_any_call("forward_disable", "int1", "vpnint0", "1.2.3.4") p.assert_any_call("forward_disable", "int2", "vpnint0", "5.6.7.8") p.assert_any_call("forward_disable", "int1", "intern0t", "1.2.3.4") p.assert_any_call("forward_disable", "int2", "intern0t", "5.6.7.8")
def test_static_extracted(): set_cwd(tempfile.mkdtemp()) cuckoo_create( cfg={ "processing": { "analysisinfo": { "enabled": False, }, "debug": { "enabled": False, } }, }) mkdir(cwd(analysis=1)) shutil.copy("tests/files/createproc1.docm", cwd("binary", analysis=1)) open(cwd("yara", "office", "ole.yar"), "wb").write(""" rule OleInside { strings: $s1 = "Win32_Process" condition: filename matches /word\/vbaProject.bin/ and $s1 } """) init_yara() class OleInsideExtractor(Extractor): def handle_yara(self, filepath, match): return (match.category == "office" and match.yara[0].name == "OleInside") ExtractManager._instances = {} ExtractManager.extractors = OleInsideExtractor, results = RunProcessing( Dictionary({ "id": 1, "category": "file", "target": "tests/files/createproc1.docm", })).run() assert len(results["extracted"]) == 1
def test_targetinfo(self): set_cwd(tempfile.mkdtemp()) cuckoo_create() init_yara() ti = TargetInfo() ti.file_path = __file__ ti.set_task({ "category": "file", "target": __file__, }) obj = ti.run() assert obj["category"] == "file" assert os.path.basename(obj["file"]["name"]) == "test_processing.py" ti = TargetInfo() ti.file_path = "tests/files/pdf0.zip" ti.set_task({ "category": "archive", "target": "tests/files/pdf0.zip", "options": { "filename": "files/pdf0.pdf", }, }) obj = ti.run() assert obj["category"] == "archive" assert os.path.basename(obj["archive"]["name"]) == "pdf0.zip" assert obj["filename"] == "files/pdf0.pdf" assert obj["human"] == "files/pdf0.pdf @ pdf0.zip" assert obj["file"]["name"] == "pdf0.pdf" assert obj["file"]["size"] == 680 ti = TargetInfo() ti.file_path = __file__ ti.set_task({ "category": "url", "target": "http://google.com", }) assert ti.run() == { "category": "url", "url": "http://google.com", }
def test_init_routing_internet_normal(p): set_cwd(tempfile.mkdtemp()) cuckoo_create(cfg={ "routing": { "routing": { "internet": "eth0", "rt_table": "table", }, }, }) p.side_effect = True, True, None, None, None, None init_routing() assert p.call_count == 6 p.assert_any_call("nic_available", "eth0") p.assert_any_call("rt_available", "table") p.assert_any_call("disable_nat", "eth0") p.assert_any_call("enable_nat", "eth0") p.assert_any_call("flush_rttable", "table") p.assert_any_call("init_rttable", "table", "eth0")
def test_init_modules(p, q, r): set_cwd(tempfile.mkdtemp()) cuckoo_create() load_signatures() logs = [] def log(fmt, *args): logs.append(fmt % args if args else fmt) p.debug.side_effect = log r.index_time_pattern = "yearly" init_modules() logs = "\n".join(logs) assert "KVM" in logs assert "Xen" in logs assert "CreatesExe" in logs assert "SystemMetrics" in logs
def test_outdated_file(self, p, q): set_cwd(tempfile.mkdtemp()) cuckoo_create() # We're going to pretend like web/local_settings.py is outdated by # replacing its sha1 by that of its initial version. our_buf = open(cwd("web", "local_settings.py"), "rb").read() def our_sha1(buf): class obj(object): def hexdigest(self): return "d90bb80df2ed51d393823438f1975c1075523ec8" return obj() if buf == our_buf else hashlib.sha1(buf) q.sha1.side_effect = our_sha1 migrate_cwd() p.assert_called_once_with( cwd("..", "data", "web/local_settings.py", private=True), cwd("web/local_settings.py"))
def init(reschedule): set_cwd(tempfile.mkdtemp()) cuckoo_create(cfg={ "cuckoo": { "cuckoo": { "reschedule": reschedule, }, }, }) Database().connect() statuses = ("pending", "running", "completed", "reported") tasks = [] for status in statuses: task_id = Database().add_path(__file__) Database().set_status(task_id, status) tasks.append(task_id) init_tasks()
def test_mongo_init_withuser(): set_cwd(tempfile.mkdtemp()) cuckoo_create( cfg={ "reporting": { "mongodb": { "enabled": True, "username": "******", "password": "******", }, }, }) m = Mongo() m.init() assert m.enabled is True assert m.hostname == "127.0.0.1" assert m.port == 27017 assert m.database == "cuckoo" assert m.username == "foo" assert m.password == "bar"
def test_basics(): set_cwd(tempfile.mkdtemp()) cuckoo_create() mkdir(cwd(analysis=1)) em = ExtractManager(1) em.write_extracted("foo", "bar") filepath = cwd("extracted", "0.foo", analysis=1) assert open(filepath, "rb").read() == "bar" scr = Scripting() cmd = scr.parse_command("powershell -e %s" % "foobar".encode("utf-16le").encode("base64")) em.push_script({ "pid": 1, "first_seen": 2, }, cmd) filepath = cwd("extracted", "0.ps1", analysis=1) assert open(filepath, "rb").read() == "foobar"
def test_mongo_connect_success_nouser(p, q): set_cwd(tempfile.mkdtemp()) cuckoo_create(cfg={ "reporting": { "mongodb": { "enabled": True, }, }, }) m = Mongo() m.init() m.connect() p.MongoClient.assert_called_once_with("127.0.0.1", 27017) client = p.MongoClient.return_value client.__getitem__.assert_called_once_with("cuckoo") db = client.__getitem__.return_value db.authenticate.assert_not_called() q.GridFS.assert_called_once_with(db) assert m.db == db assert m.grid == q.GridFS.return_value
def test_process_nodelete(self, mp, ms, mr): set_cwd(tempfile.mkdtemp()) cuckoo_create(cfg={ "cuckoo": { "cuckoo": { "delete_original": False, "delete_bin_copy": False, }, }, }) id, sample = self.add_task() task = Task() task.load_from_db(id) task.create_dirs() copied_binary = cwd("storage", "binaries", File(sample).get_sha256()) task.process() assert os.path.exists(copied_binary) assert os.path.exists(sample)
def test_config2_vpns(): set_cwd(tempfile.mkdtemp()) cuckoo_create( cfg={ "routing": { "vpn": { "vpns": [ "a", "b", ], }, "a": { "name": "name_a", "description": "desc_a", }, "b": { "name": "name_b", "description": "desc_b", }, }, }) assert config2("routing", "vpn") == { "enabled": False, "vpns": [ "a", "b", ], } assert config2("routing", "a") == { "__section__": None, "name": "name_a", "description": "desc_a", "interface": None, "rt_table": None, } with pytest.raises(CuckooConfigurationError) as e: config2("routing", "c") e.match("No such configuration section exists") assert config2("routing", "a").name == "name_a" assert config2("routing", "a").interface is None
def test_mongo_init_nouser(): set_cwd(tempfile.mkdtemp()) cuckoo_create( cfg={ "reporting": { "mongodb": { "enabled": True, "host": "1.2.3.4", "port": 4242, "db": "foobar", }, }, }) m = Mongo() m.init() assert m.enabled is True assert m.hostname == "1.2.3.4" assert m.port == 4242 assert m.database == "foobar" assert m.username is None assert m.password is None
def test_process_log_taskid(): set_cwd(tempfile.mkdtemp()) cuckoo_create() db.connect() init_console_logging(logging.DEBUG) init_logfile("process-p0.json") task = Task() id = submit_task.add_url("http://google.com/", package="ie") task.load_from_db(id) task.process = mock.MagicMock() process_task(task) for line in open(cwd("log", "process-p0.json"), "rb"): obj = json.loads(line) if obj["action"] == "task.report": assert obj["task_id"] == task.id break else: raise
def test_logging(): set_cwd(tempfile.mkdtemp()) cuckoo_create() init_logfile("cuckoo.json") with mock.patch("time.time") as p: p.return_value = 1484232002 log = logging.getLogger("test.module") log.warning("test %s", "message2", extra={ "action": "a", "status": "b", }) assert json.load(open(cwd("log", "cuckoo.json"), "rb")) == { "asctime": mock.ANY, "action": "a", "level": "warning", "message": "test message2", "status": "b", "task_id": None, "time": 1484232002, }
def test_process_dodelete(self, mp, ms, mr): set_cwd(tempfile.mkdtemp()) cuckoo_create(cfg={ "cuckoo": { "cuckoo": { "delete_original": True, "delete_bin_copy": True, }, }, }) id, sample = self.add_task() task = Task() task.load_from_db(id) task.create_dirs() assert os.path.exists(task.target) assert os.path.exists(task.targets[0].copied_binary) task.process() assert not os.path.exists(sample) assert not os.path.exists(task.targets[0].copied_binary)
def test_push_script_recursive(): set_cwd(tempfile.mkdtemp()) cuckoo_create() mkdir(cwd(analysis=1)) open(cwd("yara", "office", "ole.yar"), "wb").write(""" rule OleInside { strings: $s1 = "Win32_Process" condition: filename matches /word\/vbaProject.bin/ and $s1 } """) init_yara() s = Static() s.file_path = "tests/files/createproc1.docm" s.set_task({ "id": 1, "category": "file", "target": s.file_path, "package": "doc", }) s.run() assert ExtractManager.for_task(1).results()[0]["yara"] == [{ "name": "OleInside", "meta": { "description": "(no description)", }, "offsets": { "s1": [ (3933, 0), ], }, "strings": [ "Win32_Process".encode("base64").strip(), ], }]
def test_submit_defaults_novpn(self): set_cwd(tempfile.mkdtemp()) cuckoo_create( cfg={ "routing": { "vpn": { "enabled": False, "vpns": ["france", "italy"], }, "france": { "description": "VPN in France", }, "italy": { "description": "VPN in Italy", }, }, }) obj = defaults() assert obj["routing"]["route"] == "none" assert obj["routing"]["vpns"] == [] assert obj["routing"]["inetsim"] is False assert obj["routing"]["tor"] is False