acquire 3.7.dev2__tar.gz → 3.7.dev4__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. {acquire-3.7.dev2/acquire.egg-info → acquire-3.7.dev4}/PKG-INFO +1 -1
  2. {acquire-3.7.dev2 → acquire-3.7.dev4}/acquire/acquire.py +1 -0
  3. {acquire-3.7.dev2 → acquire-3.7.dev4}/acquire/tools/decrypter.py +47 -10
  4. acquire-3.7.dev4/acquire/version.py +4 -0
  5. {acquire-3.7.dev2 → acquire-3.7.dev4/acquire.egg-info}/PKG-INFO +1 -1
  6. {acquire-3.7.dev2 → acquire-3.7.dev4}/acquire.egg-info/SOURCES.txt +1 -0
  7. acquire-3.7.dev4/tests/test_decryptor_funcs.py +28 -0
  8. acquire-3.7.dev2/acquire/version.py +0 -4
  9. {acquire-3.7.dev2 → acquire-3.7.dev4}/COPYRIGHT +0 -0
  10. {acquire-3.7.dev2 → acquire-3.7.dev4}/LICENSE +0 -0
  11. {acquire-3.7.dev2 → acquire-3.7.dev4}/MANIFEST.in +0 -0
  12. {acquire-3.7.dev2 → acquire-3.7.dev4}/README.md +0 -0
  13. {acquire-3.7.dev2 → acquire-3.7.dev4}/acquire/__init__.py +0 -0
  14. {acquire-3.7.dev2 → acquire-3.7.dev4}/acquire/collector.py +0 -0
  15. {acquire-3.7.dev2 → acquire-3.7.dev4}/acquire/crypt.py +0 -0
  16. {acquire-3.7.dev2 → acquire-3.7.dev4}/acquire/dynamic/__init__.py +0 -0
  17. {acquire-3.7.dev2 → acquire-3.7.dev4}/acquire/dynamic/windows/__init__.py +0 -0
  18. {acquire-3.7.dev2 → acquire-3.7.dev4}/acquire/dynamic/windows/collect.py +0 -0
  19. {acquire-3.7.dev2 → acquire-3.7.dev4}/acquire/dynamic/windows/exceptions.py +0 -0
  20. {acquire-3.7.dev2 → acquire-3.7.dev4}/acquire/dynamic/windows/handles.py +0 -0
  21. {acquire-3.7.dev2 → acquire-3.7.dev4}/acquire/dynamic/windows/named_objects.py +0 -0
  22. {acquire-3.7.dev2 → acquire-3.7.dev4}/acquire/dynamic/windows/ntdll.py +0 -0
  23. {acquire-3.7.dev2 → acquire-3.7.dev4}/acquire/dynamic/windows/types.py +0 -0
  24. {acquire-3.7.dev2 → acquire-3.7.dev4}/acquire/esxi.py +0 -0
  25. {acquire-3.7.dev2 → acquire-3.7.dev4}/acquire/hashes.py +0 -0
  26. {acquire-3.7.dev2 → acquire-3.7.dev4}/acquire/log.py +0 -0
  27. {acquire-3.7.dev2 → acquire-3.7.dev4}/acquire/outputs/__init__.py +0 -0
  28. {acquire-3.7.dev2 → acquire-3.7.dev4}/acquire/outputs/base.py +0 -0
  29. {acquire-3.7.dev2 → acquire-3.7.dev4}/acquire/outputs/dir.py +0 -0
  30. {acquire-3.7.dev2 → acquire-3.7.dev4}/acquire/outputs/tar.py +0 -0
  31. {acquire-3.7.dev2 → acquire-3.7.dev4}/acquire/tools/__init__.py +0 -0
  32. {acquire-3.7.dev2 → acquire-3.7.dev4}/acquire/uploaders/__init__.py +0 -0
  33. {acquire-3.7.dev2 → acquire-3.7.dev4}/acquire/uploaders/minio.py +0 -0
  34. {acquire-3.7.dev2 → acquire-3.7.dev4}/acquire/uploaders/plugin.py +0 -0
  35. {acquire-3.7.dev2 → acquire-3.7.dev4}/acquire/uploaders/plugin_registry.py +0 -0
  36. {acquire-3.7.dev2 → acquire-3.7.dev4}/acquire/utils.py +0 -0
  37. {acquire-3.7.dev2 → acquire-3.7.dev4}/acquire.egg-info/dependency_links.txt +0 -0
  38. {acquire-3.7.dev2 → acquire-3.7.dev4}/acquire.egg-info/entry_points.txt +0 -0
  39. {acquire-3.7.dev2 → acquire-3.7.dev4}/acquire.egg-info/requires.txt +0 -0
  40. {acquire-3.7.dev2 → acquire-3.7.dev4}/acquire.egg-info/top_level.txt +0 -0
  41. {acquire-3.7.dev2 → acquire-3.7.dev4}/pyproject.toml +0 -0
  42. {acquire-3.7.dev2 → acquire-3.7.dev4}/setup.cfg +0 -0
  43. {acquire-3.7.dev2 → acquire-3.7.dev4}/tests/__init__.py +0 -0
  44. {acquire-3.7.dev2 → acquire-3.7.dev4}/tests/conftest.py +0 -0
  45. {acquire-3.7.dev2 → acquire-3.7.dev4}/tests/docs/Makefile +0 -0
  46. {acquire-3.7.dev2 → acquire-3.7.dev4}/tests/docs/conf.py +0 -0
  47. {acquire-3.7.dev2 → acquire-3.7.dev4}/tests/docs/index.rst +0 -0
  48. {acquire-3.7.dev2 → acquire-3.7.dev4}/tests/test_acquire_command.py +0 -0
  49. {acquire-3.7.dev2 → acquire-3.7.dev4}/tests/test_collector.py +0 -0
  50. {acquire-3.7.dev2 → acquire-3.7.dev4}/tests/test_esxi_memory.py +0 -0
  51. {acquire-3.7.dev2 → acquire-3.7.dev4}/tests/test_file_sorting.py +0 -0
  52. {acquire-3.7.dev2 → acquire-3.7.dev4}/tests/test_minio_uploader.py +0 -0
  53. {acquire-3.7.dev2 → acquire-3.7.dev4}/tests/test_plugin.py +0 -0
  54. {acquire-3.7.dev2 → acquire-3.7.dev4}/tests/test_utils.py +0 -0
  55. {acquire-3.7.dev2 → acquire-3.7.dev4}/tox.ini +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: acquire
3
- Version: 3.7.dev2
3
+ Version: 3.7.dev4
4
4
  Summary: A tool to quickly gather forensic artifacts from disk images or a live system into a lightweight container
5
5
  Author-email: Dissect Team <dissect@fox-it.com>
6
6
  License: Affero General Public License v3
@@ -946,6 +946,7 @@ class QuarantinedFiles(Module):
946
946
  # Sophos
947
947
  ("glob", "sysvol/ProgramData/Sophos/Sophos/*/Quarantine"),
948
948
  ("glob", "sysvol/ProgramData/Sophos/Sophos */INFECTED"),
949
+ ("dir", "sysvol/ProgramData/Sophos/Safestore"),
949
950
  # HitmanPRO
950
951
  ("dir", "sysvol/ProgramData/HitmanPro/Quarantine"),
951
952
  ]
@@ -8,7 +8,8 @@ import multiprocessing
8
8
  import os
9
9
  import signal
10
10
  import sys
11
- from collections import deque
11
+ import textwrap
12
+ from collections import defaultdict, deque
12
13
  from concurrent.futures import ProcessPoolExecutor
13
14
  from datetime import datetime, timezone
14
15
  from pathlib import Path
@@ -343,19 +344,20 @@ def main():
343
344
  if not progress:
344
345
  log.info("`rich` is not installed, progress will not be shown")
345
346
 
346
- if args.output and len(args.files) > 1:
347
- parser.exit("--output is only allowed when decrypting a single file")
347
+ if args.output and args.output.is_file() and len(args.files) > 1:
348
+ parser.exit("--output should be a directory when decrypting multiple files.")
348
349
 
349
- if not args.output:
350
- for path in args.files:
351
- if path.suffix != ".enc":
352
- parser.exit(f"File doesn't have .enc extension: {path}")
350
+ files = find_enc_files(args.files)
353
351
 
354
352
  if args.output:
355
- outputs = [args.output.resolve()]
353
+ resolv_path = args.output.resolve()
354
+ outputs = [resolv_path / path.stem for path in files] if args.output.is_dir() else [resolv_path]
356
355
  else:
357
356
  # Strip .enc extension
358
- outputs = [path.with_suffix("") for path in args.files]
357
+ outputs = [path.with_suffix("") for path in files]
358
+
359
+ if len(set(outputs)) != len(outputs):
360
+ show_duplicates(args.output, files)
359
361
 
360
362
  if not args.key_file and not args.key_server:
361
363
  parser.exit("Need either --key-file or --key-server")
@@ -378,7 +380,7 @@ def main():
378
380
  status_queue = mp.Queue()
379
381
  tasks = []
380
382
 
381
- for in_path, out_path in zip(args.files, outputs):
383
+ for in_path, out_path in zip(files, outputs):
382
384
  task_id = (
383
385
  progress.add_task("decrypt", start=False, visible=False, filename=in_path.name)
384
386
  if progress
@@ -424,6 +426,41 @@ def main():
424
426
  break
425
427
 
426
428
 
429
+ def show_duplicates(output_directory: Path, files: list[Path]) -> None:
430
+ # Gather all files that could cause duplicates in `args.output`.
431
+ input_files = defaultdict(list)
432
+ for input_file in files:
433
+ input_files[input_file.name].append(input_file)
434
+
435
+ # Find all duplicates
436
+ duplicate_generator = (file_paths for file_paths in input_files.values() if len(file_paths) > 1)
437
+ duplicates = "\n\n".join(
438
+ textwrap.indent(
439
+ "\n".join(str(file) for file in file_paths),
440
+ prefix=" - ",
441
+ )
442
+ for file_paths in duplicate_generator
443
+ )
444
+ log.warning(
445
+ "Two or more encrypted files have the same name. "
446
+ f"This will skip decrypting the file if it already exists in '{output_directory}'\n"
447
+ f"The files with the same names are:\n"
448
+ f"{duplicates}"
449
+ )
450
+
451
+
452
+ def find_enc_files(files: list[Path]) -> list[Path]:
453
+ encrypted_files = []
454
+ for path in files:
455
+ if path.is_file() and path.suffix == ".enc":
456
+ encrypted_files.append(path)
457
+ elif path.is_dir():
458
+ encrypted_files.extend(path.rglob("*.enc"))
459
+ else:
460
+ log.info(f"File {path!r} does not have the .enc extension. skipping.")
461
+ return encrypted_files
462
+
463
+
427
464
  if __name__ == "__main__":
428
465
  try:
429
466
  sys.exit(main())
@@ -0,0 +1,4 @@
1
+ # file generated by setuptools_scm
2
+ # don't change, don't track in version control
3
+ __version__ = version = '3.7.dev4'
4
+ __version_tuple__ = version_tuple = (3, 7, 'dev4')
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: acquire
3
- Version: 3.7.dev2
3
+ Version: 3.7.dev4
4
4
  Summary: A tool to quickly gather forensic artifacts from disk images or a live system into a lightweight container
5
5
  Author-email: Dissect Team <dissect@fox-it.com>
6
6
  License: Affero General Public License v3
@@ -41,6 +41,7 @@ tests/__init__.py
41
41
  tests/conftest.py
42
42
  tests/test_acquire_command.py
43
43
  tests/test_collector.py
44
+ tests/test_decryptor_funcs.py
44
45
  tests/test_esxi_memory.py
45
46
  tests/test_file_sorting.py
46
47
  tests/test_minio_uploader.py
@@ -0,0 +1,28 @@
1
+ from pathlib import Path
2
+
3
+ from acquire.tools.decrypter import find_enc_files
4
+
5
+
6
+ def test_find_non_encrypted_files(tmp_path: Path):
7
+ input_files = [tmp_path / "test", tmp_path / "help"]
8
+
9
+ for file in input_files:
10
+ file.touch()
11
+
12
+ assert find_enc_files(input_files) == []
13
+
14
+
15
+ def test_find_inside_dir(tmp_path: Path):
16
+ output_path = tmp_path.joinpath("output/for/this/test")
17
+ output_path.mkdir(parents=True)
18
+
19
+ rel_path = output_path.relative_to(tmp_path)
20
+
21
+ expected_outputs = []
22
+
23
+ for directory in rel_path.parents:
24
+ searchable_file = tmp_path / directory / "test.enc"
25
+ searchable_file.touch()
26
+ expected_outputs.append(searchable_file)
27
+
28
+ assert sorted(find_enc_files([tmp_path])) == sorted(expected_outputs)
@@ -1,4 +0,0 @@
1
- # file generated by setuptools_scm
2
- # don't change, don't track in version control
3
- __version__ = version = '3.7.dev2'
4
- __version_tuple__ = version_tuple = (3, 7, 'dev2')
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes