def test_add_multi_write_file_element(self, out_dir, data): store = forensicstore.new(out_dir + "/amcache.forensicstore") file_date = datetime.datetime(2014, 9, 11, 21, 50, 18, 301000) origin = { "path": "C:\\Windows\\appcompat\\Programs\\Amcache.hve", "volume": "2" } file = store.add_file_element("WindowsAMCacheHveFile", "Amcache.hve", file_date, file_date, file_date, origin, []) with store.add_file_element_export(file) as export: for _ in range(123): export.write(b'A') elements = store.all() first = list(elements).pop() del first["id"] assert first == EXAMPLE_FORENSICSTORE[2] with store.fs.open("/WindowsAMCacheHveFile/Amcache.hve", 'rb') as io: assert io.read() == 123 * b'A' store.close() shutil.rmtree(out_dir) shutil.rmtree(data)
def test_import_image(tmp): return client = docker.from_env() # build image image_tag = "test_artifacts" image, _ = client.images.build(path="import-image/", tag=image_tag) store = forensicstore.new(os.path.join(tmp, "input.forensicstore")) store.close() # run image store_path = os.path.abspath(tmp) store_path_unix = to_unix_path(store_path) import_path = os.path.abspath(os.path.join(tmp, INPUT_IMAGE_SUBDIR)) import_path_unix = to_unix_path(import_path) volumes = { store_path_unix: { 'bind': '/input', 'mode': 'rw' }, import_path_unix: { 'bind': '/input/' + INPUT_IMAGE_SUBDIR, 'mode': 'ro' } } container = client.containers.run( image_tag, command=["--input-file", "win10_mock.vhd"], volumes=volumes, detach=True, ) result = container.wait() out = container.logs() container.remove() print(out.decode("utf-8")) assert result["StatusCode"] == 0 # test results store = forensicstore.open(os.path.join(store_path, "input.forensicstore")) items = list(store.all()) store.close() # shutil.copyfile(os.path.join(store_path, "input.forensicstore"), "./input.forensicstore") assert len(items) == 1832 # cleanup try: shutil.rmtree(tmp) except PermissionError: pass
def test_insert_quotes(self, out_dir, data): store = forensicstore.new(out_dir + "/quotes.forensicstore") element_id = store.insert({"type": "any_type"}) store.update( element_id, {"foo": '@"%ProgramFiles%\\Windows Journal\\Journal.exe",-3072'}) assert store.get(element_id)[ "foo"] == '@"%ProgramFiles%\\Windows Journal\\Journal.exe",-3072' store.close() shutil.rmtree(out_dir) shutil.rmtree(data)
def test_add_directory_element(self, out_dir, data): store = forensicstore.new(out_dir + "/program_files.forensicstore") dir_date = datetime.datetime(2014, 9, 11, 21, 50, 18, 301000) store.add_directory_element("WindowsEnvironmentVariableProgramFiles", "C:\\Program Files", dir_date, dir_date, dir_date, []) elements = store.all() first = list(elements).pop() del first["id"] assert first == EXAMPLE_FORENSICSTORE[3] store.close() shutil.rmtree(out_dir) shutil.rmtree(data)
def test_import_store(self, out_dir, data): import_store = forensicstore.new(out_dir + "/tmp.forensicstore") with import_store.store_file("testfile.txt") as (path, io): io.write(123 * b'A') import_store.insert({"type": "foo", "export_path": path}) import_store.close() store = forensicstore.new(out_dir + "/amcache.forensicstore") with store.store_file("testfile.txt") as (path, io): io.write(123 * b'B') store.insert({"type": "foo", "export_path": path}) store.import_forensicstore(out_dir + "/tmp.forensicstore") elements = store.all() assert len(list(elements)) == 2 with store.fs.open("/testfile.txt", 'rb') as io: assert io.read() == 123 * b'B' with store.fs.open("/testfile_0.txt", 'rb') as io: assert io.read() == 123 * b'A' store.close() shutil.rmtree(out_dir) shutil.rmtree(data)
def test_add_duplicate_file_element(self, out_dir, data): store = forensicstore.new(out_dir + "/amcache.forensicstore") file_date = datetime.datetime(2014, 9, 11, 21, 50, 18, 301000) origin = { "path": "C:\\Windows\\appcompat\\Programs\\Amcache.hve", "volume": "2" } file1 = store.add_file_element("WindowsAMCacheHveFile", "Amcache.hve", file_date, file_date, file_date, origin, []) with store.add_file_element_export(file1) as export: export.write(123 * b'A') file2 = store.add_file_element("WindowsAMCacheHveFile", "Amcache.hve", file_date, file_date, file_date, origin, []) with store.add_file_element_export(file2) as export: export.write(123 * b'B') file3 = store.add_file_element("WindowsAMCacheHveFile", "Amcache.hve", file_date, file_date, file_date, origin, []) with store.add_file_element_export(file3, "Amcache_b.hve") as export: export.write(123 * b'C') file4 = store.add_file_element("WindowsAMCacheHveFile", "Amcache.hve", file_date, file_date, file_date, origin, []) with store.add_file_element_export(file4, "Amcache_b.hve") as export: export.write(123 * b'D') first = store.get(file1) del first["id"] assert first == EXAMPLE_FORENSICSTORE[2] with store.fs.open("/WindowsAMCacheHveFile/Amcache.hve", 'rb') as io: assert io.read() == 123 * b'A' with store.fs.open("/WindowsAMCacheHveFile/Amcache_0.hve", 'rb') as io: assert io.read() == 123 * b'B' with store.fs.open("/WindowsAMCacheHveFile/Amcache_b.hve", 'rb') as io: assert io.read() == 123 * b'C' with store.fs.open("/WindowsAMCacheHveFile/Amcache_b_0.hve", 'rb') as io: assert io.read() == 123 * b'D' store.close() shutil.rmtree(out_dir) shutil.rmtree(data)
def test_docker(tmp): client = docker.from_env() # build image image_tag = "test_artifacts" image, _ = client.images.build(path="import-image/", tag=image_tag) store = forensicstore.new(os.path.join(tmp, "input.forensicstore")) store.close() # run image store_path = os.path.abspath(tmp) store_path_unix = to_unix_path(store_path) import_path = os.path.abspath(os.path.join(tmp, "in")) import_path_unix = to_unix_path(import_path) volumes = { store_path_unix: { 'bind': '/store', 'mode': 'rw' }, import_path_unix: { 'bind': '/data', 'mode': 'ro' } } out = client.containers.run(image_tag, command=["input.forensicstore"], volumes=volumes, stderr=True).decode("ascii") # print(out) # test results store = forensicstore.open(os.path.join(store_path, "input.forensicstore")) items = list(store.all()) store.close() shutil.copyfile(os.path.join(store_path, "input.forensicstore"), "./input.forensicstore") # assert len(items) == 8 # cleanup try: shutil.rmtree(tmp) except PermissionError: pass
def test_add_registry_key_element(self, out_dir, data): store = forensicstore.new(out_dir + "/codepage.forensicstore") key_date = datetime.datetime(2009, 7, 14, 4, 34, 14, 225000) key = store.add_registry_key_element( "WindowsCodePage", key_date, "HKEY_LOCAL_MACHINE\\System\\CurrentControlSet\\Control\\Nls\\CodePage", []) store.add_registry_value_element(key, "REG_SZ", "1252".encode("utf-16"), "ACP") elements = store.all() first = list(elements).pop() del first["id"] assert first == EXAMPLE_FORENSICSTORE[5] store.close() shutil.rmtree(out_dir) shutil.rmtree(data)
def test_add_process_element(self, out_dir, data): store = forensicstore.new(out_dir + "/iptables.forensicstore") cmd_date = datetime.datetime(2016, 1, 20, 14, 11, 25, 550000) cmd = store.add_process_element("IPTablesRules", "iptables", cmd_date, "/root/", "/sbin/iptables -L -n -v", 0, []) with store.add_process_element_stdout( cmd) as stdout, store.add_process_element_stderr( cmd) as stderr: stdout.write(b"foo") stderr.write(b"bar") elements = store.all() first = list(elements).pop() del first["id"] assert first == EXAMPLE_FORENSICSTORE[0] with store.fs.open("/IPTablesRules/stdout", 'rb') as io: assert io.read() == b"foo" with store.fs.open("/IPTablesRules/stderr", 'rb') as io: assert io.read() == b"bar" store.close() shutil.rmtree(out_dir) shutil.rmtree(data)
def main(): parser = argparse.ArgumentParser( prog="discoruns", description= "Extract persistence mechanisms from disc images or forensicstores.") parser.add_argument( '--format', help="Output format of the collected persistence mechanisms.", choices=['console', 'json'], dest='format', default="console") parser.add_argument("-v", "--verbose", help="Show logging messages.", dest='verbose', action="store_true", default=False) subparsers = parser.add_subparsers(title="subcommands", dest="subcommand", required=True) parser_image = subparsers.add_parser('image') parser_image.add_argument( "image", metavar="IMAGE", help="Location of a disk image or a forensicstore.") parser_forensicstore = subparsers.add_parser('forensicstore') parser_forensicstore.add_argument("forensicstore", metavar="FORENSICSTORE", help="Location of a forensicstore.") args = parser.parse_args() if args.verbose: logger.setLevel(logging.DEBUG) else: logger.setLevel(logging.INFO) start_time = time.time() if args.subcommand == "image": if not os.path.exists(args.image): logger.error("Image does not exist!") sys.exit(1) fstore_full_path = f"{Path(args.image).stem}.forensicstore" # Create new store try: store = forensicstore.new(fstore_full_path) store.close() except forensicstore.forensicstore.StoreExitsError: logger.error("Forensicstore does allready exist!") sys.exit(1) # Start extraction logger.info("Collecting artifacts. This might take a while...") ArtifactCollectorWrapper( args.image, fstore_full_path, f"{os.path.join(os.path.dirname(os.path.abspath(__file__)), 'artifacts')}", "WindowsPersistence").collect_artifacts() elif args.subcommand == "forensicstore": if not os.path.exists(args.forensicstore): logger.error("Forensicstore does not exist!") sys.exit(1) logger.info("Using an existing forensicstore.") fstore_full_path = args.forensicstore collected_mechanisms = collect(fstore_full_path) if args.format == "json": print(json.dumps(collected_mechanisms, indent=4)) else: print(tabulate.tabulate(collected_mechanisms)) print() print("Total found entries: " + str(len(collected_mechanisms))) print("Execution time: %.4s seconds" % (time.time() - start_time))
def main(): root_parser = argparse.ArgumentParser(description='Handle forensicstores') root_subparsers = root_parser.add_subparsers(dest='root_command') root_subparsers.required = True create_parser = root_subparsers.add_parser("create") create_parser.add_argument('store') import_parser = root_subparsers.add_parser("import") import_parser.add_argument('url') import_parser.add_argument('store') validate_parser = root_subparsers.add_parser("validate") validate_parser.add_argument('store') validate_parser.add_argument('--no-fail', action='store_true', dest="nofail") element_parser = root_subparsers.add_parser("element") element_subparsers = element_parser.add_subparsers(dest='command') element_subparsers.required = True get_parser = element_subparsers.add_parser("get") get_parser.add_argument('id') get_parser.add_argument('store') select_parser = element_subparsers.add_parser("select") select_parser.add_argument('type') select_parser.add_argument('store') all_parser = element_subparsers.add_parser("all") all_parser.add_argument('store') insert_parser = element_subparsers.add_parser("insert") insert_parser.add_argument('json') insert_parser.add_argument('store') update_parser = element_subparsers.add_parser("update") update_parser.add_argument('id') update_parser.add_argument('json') update_parser.add_argument('store') args = root_parser.parse_args() if args.root_command == "create": store = forensicstore.new(args.store) store.close() elif args.root_command == "validate": store = forensicstore.open(args.store) errors = store.validate() if errors: print(json.dumps(errors)) if args.nofail: sys.exit(0) sys.exit(len(errors)) elif args.root_command == "element": if args.command == "get": store = forensicstore.open(args.store) element = store.get(args.id) print(json.dumps(element)) store.close() elif args.command == "select": store = forensicstore.open(args.store) elements = list(store.select([{"type": args.type}])) print(json.dumps(elements)) store.close() elif args.command == "all": store = forensicstore.open(args.store) elements = list(store.all()) print(json.dumps(elements)) store.close() elif args.command == "insert": store = forensicstore.open(args.store) element = store.insert(json.loads(args.json)) print(json.dumps(element)) store.close() elif args.command == "update": store = forensicstore.open(args.store) print(args.json) element = store.update(args.id, json.loads(args.json)) print(json.dumps(element)) store.close() else: NotImplementedError("Sub command %s does not exist" % args.command) else: NotImplementedError("Command %s does not exist" % args.root_command)
def test_init_create(self, out_dir, data): store = forensicstore.new(out_dir + "/init_create.forensicstore") store.close() assert os.path.exists(out_dir + "/init_create.forensicstore") shutil.rmtree(out_dir) shutil.rmtree(data)