def test_tasks_delete(self): filepath1 = Files.temp_put("foobar") filepath2 = Files.temp_put("foobar") assert os.path.exists(filepath1) assert os.path.exists(filepath2) self.db.session.add(db.Task(filepath1, status=db.Task.FINISHED)) self.db.session.add(db.Task(filepath2, status=db.Task.FINISHED)) data = { "task_ids": "1 2", } assert self.client.delete("/api/tasks", data=data).json == { "success": True, } assert not os.path.exists(filepath1) assert not os.path.exists(filepath2) assert self.client.delete("/api/task/1").json == { "success": False, "message": "Task already deleted", } assert self.client.delete("/api/task/2").json == { "success": False, "message": "Task already deleted", } assert not os.path.exists(filepath1) assert not os.path.exists(filepath2)
def test_status(self): # Create any temporary file, as long as the temporary directory is # not empty. Tests bug fix where /cuckoo/status tries to remove the # entire temporary directory. Files.temp_put("") r = self.app.get("/cuckoo/status") assert r.status_code == 200
def test_fd_exhaustion(self): fd, filepath = tempfile.mkstemp() for x in xrange(0x100): Files.temp_put("foo") fd2, filepath = tempfile.mkstemp() # Let's leave a bit of working space. assert fd2 - fd < 64
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_wsf_language(): wsf = WindowsScriptFile(Files.temp_put( "<script language='JScript.Encode'></script>" )) wsf.decode = mock.MagicMock(return_value="codehere") assert wsf.run() == ["codehere"] wsf.decode.assert_called_once()
def test_empty_mempath(self, p): set_cwd(tempfile.mkdtemp()) m = Memory() m.memory_path = Files.temp_put("") assert m.run() is None p.error.assert_called_once() assert "dump empty" in p.error.call_args_list[0][0][0]
def test_star_new(self): filepath = Files.temp_put(""" virtualbox.virtualbox.machines = cuckoo2, cuckoo3 virtualbox.cuckoo2.ip = 192.168.56.102 virtualbox.cuckoo3.ip = 192.168.56.103 virtualbox.notexistingvm.ip = 1.2.3.4 """) assert read_kv_conf(filepath) == { "virtualbox": { "virtualbox": { "machines": [ "cuckoo2", "cuckoo3", ], }, "cuckoo2": { "ip": "192.168.56.102", }, "cuckoo3": { "ip": "192.168.56.103", }, "notexistingvm": { "ip": "1.2.3.4", }, }, }
def test_resubmit_file_missing(self, client): filepath = Files.temp_put("hello world") db.add_path(filepath, options={ "human": 0, "free": "yes", }) os.unlink(filepath) assert client.get("/submit/re/1/").status_code == 500
def test_empty_move(self): oldfilepath = Files.temp_put("hello") movesql("sqlite:///%s" % oldfilepath, "move", temppath()) assert not os.path.exists(oldfilepath) assert os.path.exists(cwd("cuckoo.db")) assert not os.path.islink(cwd("cuckoo.db")) assert open(cwd("cuckoo.db"), "rb").read() == "hello"
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_temp_conf(self): dirpath = tempfile.mkdtemp() set_cwd(dirpath) Folders.create(dirpath, "conf") with open(os.path.join(dirpath, "conf", "cuckoo.conf"), "wb") as f: f.write("[cuckoo]\ntmppath = %s" % dirpath) filepath = Files.temp_put("foo") assert filepath.startswith(os.path.join(dirpath, "cuckoo-tmp"))
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_star_existing(self): filepath = Files.temp_put(""" virtualbox.cuckoo1.resultserver_port = 1234 """) assert read_kv_conf(filepath) == { "virtualbox": { "cuckoo1": { "resultserver_port": 1234, }, }, }
def test_get_urls(): filepath = Files.temp_put(""" http://google.com google.com/foobar thisisnotadomain https://1.2.3.4:9001/hello """) assert sorted(File(filepath).get_urls()) == [ # TODO Why does this not work properly at my own machine? "http://google.com", "https://1.2.3.4:9001/hello", ]
def test_whitespace_before_line2(): set_cwd(tempfile.mkdtemp()) filepath = Files.temp_put(""" [virtualbox] machines = cuckoo1 [cuckoo1] label = cuckoo1 ip = 1.2.3.4 snapshot = asnapshot """) with pytest.raises(CuckooConfigurationError) as e: Config(file_name="virtualbox", cfg=filepath) e.match("Most likely there are leading whitespaces")
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
def test_private_key(self): buf = open("tests/files/pdf0.pdf", "rb").read() filepath = Files.temp_put(( buf + "-----BEGIN RSA PRIVATE KEY-----\n" "HELLOWORLD\n" "-----END RSA PRIVATE KEY-----" + buf )) assert File(filepath).get_keys() == [ "-----BEGIN RSA PRIVATE KEY-----\n" "HELLOWORLD\n" "-----END RSA PRIVATE KEY-----" ]
def test_task_delete(self): filepath = Files.temp_put("foobar") assert os.path.exists(filepath) self.db.session.add(db.Task(filepath, status=db.Task.FINISHED)) assert self.client.delete("/api/task/1").json == { "success": True, } assert not os.path.exists(filepath) assert self.client.delete("/api/task/1").json == { "success": False, "message": "Task already deleted", } assert not os.path.exists(filepath)
def test_cuckoo_init_kv_conf(self): filepath = Files.temp_put( "cuckoo.cuckoo.version_check = no" ) # Create a new CWD as Files.temp_put() indexes - or tries to - the # original cuckoo.conf (even though it doesn't exist yet). set_cwd(tempfile.mkdtemp()) with pytest.raises(SystemExit): main.main( ("--cwd", cwd(), "init", "--conf", filepath), standalone_mode=False ) assert config("cuckoo:cuckoo:version_check") is False
def test_success(self): filepath = Files.temp_put(""" cuckoo.cuckoo.version_check = off auxiliary.sniffer.enabled = no """) assert read_kv_conf(filepath) == { "cuckoo": { "cuckoo": { "version_check": False, }, }, "auxiliary": { "sniffer": { "enabled": False, }, }, }
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 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)
def test_hash_file(self): filepath = Files.temp_put("hehe") assert Files.md5_file(filepath) == "529ca8050a00180790cf88b63468826a" assert Files.sha1_file(filepath) == "42525bb6d3b0dc06bb78ae548733e8fbb55446b3" assert Files.sha256_file(filepath) == "0ebe2eca800cf7bd9d9d9f9f4aafbc0c77ae155f43bbbeca69cb256a24c7f9bb"
def test_stringio(self): filepath = Files.temp_put(cStringIO.StringIO("foo"), "/tmp") assert open(filepath, "rb").read() == "foo"
def test_temp_file(self): filepath1 = Files.temp_put("hello", "/tmp") filepath2 = Files.temp_put("hello", "/tmp") assert open(filepath1, "rb").read() == "hello" assert open(filepath2, "rb").read() == "hello" assert filepath1 != filepath2
def test_fail3(self): filepath = Files.temp_put("cuckoo.cuckoo.version_check = foo") with pytest.raises(CuckooConfigurationError) as e: read_kv_conf(filepath) e.match("Invalid flat configuration entry")
def test_fail2(self): filepath = Files.temp_put("a.b.c : d") with pytest.raises(CuckooConfigurationError) as e: read_kv_conf(filepath) e.match("missing .* character")
def test_fail1(self): filepath = Files.temp_put("a = b") with pytest.raises(CuckooConfigurationError) as e: read_kv_conf(filepath) e.match("Invalid configuration entry")
def test_hash_file(self): filepath = Files.temp_put("hehe", "/tmp") assert Files.md5_file(filepath) == "529ca8050a00180790cf88b63468826a" assert Files.sha1_file(filepath) == "42525bb6d3b0dc06bb78ae548733e8fbb55446b3" assert Files.sha256_file(filepath) == "0ebe2eca800cf7bd9d9d9f9f4aafbc0c77ae155f43bbbeca69cb256a24c7f9bb"
def test_add_sample(self, p): p.from_file.return_value = "" assert self.d.add_path(Files.temp_put(os.urandom(16))) is not None
def test_bytesio(self): filepath = Files.temp_put(io.BytesIO("foo"), "/tmp") assert open(filepath, "rb").read() == "foo"
def status(request): """ Returns a variety of information about both Cuckoo and the operating system. :return: Dictionary """ # 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=os.path.dirname(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: memory = 100.0 * int(values["MemFree"]) / int( values["MemTotal"]) else: memory = None else: memory = None data = 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, memory=memory, ) return JsonResponse({"status": True, "data": data})