dissect.target 3.16.dev39__py3-none-any.whl → 3.16.dev43__py3-none-any.whl
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.
- dissect/target/helpers/fsutil.py +9 -9
- dissect/target/loaders/dir.py +10 -4
- dissect/target/loaders/velociraptor.py +8 -0
- dissect/target/tools/reg.py +41 -18
- {dissect.target-3.16.dev39.dist-info → dissect.target-3.16.dev43.dist-info}/METADATA +2 -2
- {dissect.target-3.16.dev39.dist-info → dissect.target-3.16.dev43.dist-info}/RECORD +11 -11
- {dissect.target-3.16.dev39.dist-info → dissect.target-3.16.dev43.dist-info}/COPYRIGHT +0 -0
- {dissect.target-3.16.dev39.dist-info → dissect.target-3.16.dev43.dist-info}/LICENSE +0 -0
- {dissect.target-3.16.dev39.dist-info → dissect.target-3.16.dev43.dist-info}/WHEEL +0 -0
- {dissect.target-3.16.dev39.dist-info → dissect.target-3.16.dev43.dist-info}/entry_points.txt +0 -0
- {dissect.target-3.16.dev39.dist-info → dissect.target-3.16.dev43.dist-info}/top_level.txt +0 -0
dissect/target/helpers/fsutil.py
CHANGED
@@ -16,23 +16,23 @@ from typing import Any, BinaryIO, Iterator, Optional, Sequence, TextIO, Union
|
|
16
16
|
try:
|
17
17
|
import lzma
|
18
18
|
|
19
|
-
|
19
|
+
HAS_XZ = True
|
20
20
|
except ImportError:
|
21
|
-
|
21
|
+
HAS_XZ = False
|
22
22
|
|
23
23
|
try:
|
24
24
|
import bz2
|
25
25
|
|
26
|
-
|
26
|
+
HAS_BZ2 = True
|
27
27
|
except ImportError:
|
28
|
-
|
28
|
+
HAS_BZ2 = False
|
29
29
|
|
30
30
|
try:
|
31
31
|
import zstandard
|
32
32
|
|
33
|
-
|
33
|
+
HAS_ZSTD = True
|
34
34
|
except ImportError:
|
35
|
-
|
35
|
+
HAS_ZSTD = False
|
36
36
|
|
37
37
|
import dissect.target.filesystem as filesystem
|
38
38
|
from dissect.target.exceptions import FileNotFoundError, SymlinkRecursionError
|
@@ -511,14 +511,14 @@ def open_decompress(
|
|
511
511
|
if magic[:2] == b"\x1f\x8b":
|
512
512
|
return gzip.open(file, mode, encoding=encoding, errors=errors, newline=newline)
|
513
513
|
|
514
|
-
if
|
514
|
+
if HAS_XZ and magic[:5] == b"\xfd7zXZ":
|
515
515
|
return lzma.open(file, mode, encoding=encoding, errors=errors, newline=newline)
|
516
516
|
|
517
|
-
if
|
517
|
+
if HAS_BZ2 and magic[:3] == b"BZh" and 0x31 <= magic[3] <= 0x39:
|
518
518
|
# In a valid bz2 header the 4th byte is in the range b'1' ... b'9'.
|
519
519
|
return bz2.open(file, mode, encoding=encoding, errors=errors, newline=newline)
|
520
520
|
|
521
|
-
if
|
521
|
+
if HAS_ZSTD and magic[:4] in [b"\xfd\x2f\xb5\x28", b"\x28\xb5\x2f\xfd"]:
|
522
522
|
# stream_reader is not seekable, so we have to resort to the less
|
523
523
|
# efficient decompressor which returns bytes.
|
524
524
|
return io.BytesIO(zstandard.decompress(file.read()))
|
dissect/target/loaders/dir.py
CHANGED
@@ -34,12 +34,12 @@ def find_entry_path(path: Path) -> str | None:
|
|
34
34
|
return prefix
|
35
35
|
|
36
36
|
|
37
|
-
def map_dirs(target: Target, dirs: list[Path], os_type: str, **kwargs) -> None:
|
37
|
+
def map_dirs(target: Target, dirs: list[Path | tuple[str, Path]], os_type: str, **kwargs) -> None:
|
38
38
|
"""Map directories as filesystems into the given target.
|
39
39
|
|
40
40
|
Args:
|
41
41
|
target: The target to map into.
|
42
|
-
dirs: The directories to map as filesystems.
|
42
|
+
dirs: The directories to map as filesystems. If a list member is a tuple, the first element is the drive letter.
|
43
43
|
os_type: The operating system type, used to determine how the filesystem should be mounted.
|
44
44
|
"""
|
45
45
|
alt_separator = ""
|
@@ -49,6 +49,12 @@ def map_dirs(target: Target, dirs: list[Path], os_type: str, **kwargs) -> None:
|
|
49
49
|
case_sensitive = False
|
50
50
|
|
51
51
|
for path in dirs:
|
52
|
+
drive_letter = None
|
53
|
+
if isinstance(path, tuple):
|
54
|
+
drive_letter, path = path
|
55
|
+
elif is_drive_letter_path(path):
|
56
|
+
drive_letter = path.name[0]
|
57
|
+
|
52
58
|
if isinstance(path, zipfile.Path):
|
53
59
|
dfs = ZipFilesystem(path.root.fp, path.at, alt_separator=alt_separator, case_sensitive=case_sensitive)
|
54
60
|
else:
|
@@ -58,8 +64,8 @@ def map_dirs(target: Target, dirs: list[Path], os_type: str, **kwargs) -> None:
|
|
58
64
|
if os_type == OperatingSystem.WINDOWS:
|
59
65
|
loaderutil.add_virtual_ntfs_filesystem(target, dfs, **kwargs)
|
60
66
|
|
61
|
-
if
|
62
|
-
target.fs.mount(
|
67
|
+
if drive_letter is not None:
|
68
|
+
target.fs.mount(drive_letter.lower() + ":", dfs)
|
63
69
|
|
64
70
|
|
65
71
|
def find_and_map_dirs(target: Target, path: Path, **kwargs) -> None:
|
@@ -43,6 +43,8 @@ def find_fs_directories(path: Path) -> tuple[Optional[OperatingSystem], Optional
|
|
43
43
|
# https://github.com/Velocidex/velociraptor/blob/87368e7cc678144592a1614bb3bbd0a0f900ded9/accessors/ntfs/vss.go#L82
|
44
44
|
if "HarddiskVolumeShadowCopy" in volume.name:
|
45
45
|
vss_volumes.add(volume)
|
46
|
+
elif (drive_letter := extract_drive_letter(volume.name)) is not None:
|
47
|
+
volumes.add((drive_letter, volume))
|
46
48
|
else:
|
47
49
|
volumes.add(volume)
|
48
50
|
|
@@ -54,6 +56,12 @@ def find_fs_directories(path: Path) -> tuple[Optional[OperatingSystem], Optional
|
|
54
56
|
return None, None
|
55
57
|
|
56
58
|
|
59
|
+
def extract_drive_letter(name: str) -> Optional[str]:
|
60
|
+
# \\.\X: in URL encoding
|
61
|
+
if len(name) == 14 and name.startswith("%5C%5C.%5C") and name.endswith("%3A"):
|
62
|
+
return name[10].lower()
|
63
|
+
|
64
|
+
|
57
65
|
class VelociraptorLoader(DirLoader):
|
58
66
|
"""Load Rapid7 Velociraptor forensic image files.
|
59
67
|
|
dissect/target/tools/reg.py
CHANGED
@@ -3,10 +3,16 @@
|
|
3
3
|
from __future__ import print_function
|
4
4
|
|
5
5
|
import argparse
|
6
|
+
import itertools
|
6
7
|
import logging
|
7
8
|
|
8
9
|
from dissect.target import Target
|
9
|
-
from dissect.target.exceptions import
|
10
|
+
from dissect.target.exceptions import (
|
11
|
+
RegistryError,
|
12
|
+
RegistryKeyNotFoundError,
|
13
|
+
TargetError,
|
14
|
+
)
|
15
|
+
from dissect.target.helpers.regutil import RegistryKey
|
10
16
|
from dissect.target.tools.utils import (
|
11
17
|
catch_sigpipe,
|
12
18
|
configure_generic_arguments,
|
@@ -29,7 +35,8 @@ def main():
|
|
29
35
|
parser.add_argument("targets", metavar="TARGETS", nargs="+", help="Targets to load")
|
30
36
|
parser.add_argument("-k", "--key", required=True, help="key to query")
|
31
37
|
parser.add_argument("-kv", "--value", help="value to query")
|
32
|
-
parser.add_argument("-d", "--depth", type=int, const=0, nargs="?", default=1)
|
38
|
+
parser.add_argument("-d", "--depth", type=int, const=0, nargs="?", default=1, help="max depth of subkeys to print")
|
39
|
+
parser.add_argument("-l", "--length", type=int, default=100, help="max length of key value to print")
|
33
40
|
|
34
41
|
configure_generic_arguments(parser)
|
35
42
|
args = parser.parse_args()
|
@@ -38,34 +45,50 @@ def main():
|
|
38
45
|
|
39
46
|
try:
|
40
47
|
for target in Target.open_all(args.targets):
|
48
|
+
if not target.has_function("registry"):
|
49
|
+
target.log.error("Target has no Windows Registry")
|
50
|
+
continue
|
51
|
+
|
41
52
|
try:
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
else:
|
53
|
+
keys = target.registry.keys(args.key)
|
54
|
+
first_key = next(keys)
|
55
|
+
|
56
|
+
print(target)
|
57
|
+
|
58
|
+
for key in itertools.chain([first_key], keys):
|
49
59
|
try:
|
50
|
-
|
51
|
-
|
52
|
-
|
60
|
+
if args.value:
|
61
|
+
print(key.value(args.value))
|
62
|
+
else:
|
63
|
+
recursor(key, args.depth, 0, args.length)
|
53
64
|
except RegistryError:
|
54
65
|
log.exception("Failed to find registry value")
|
55
|
-
|
56
|
-
|
66
|
+
|
67
|
+
except (RegistryKeyNotFoundError, StopIteration):
|
68
|
+
target.log.error("Key %r does not exist", args.key)
|
69
|
+
|
70
|
+
except Exception as e:
|
71
|
+
target.log.error("Failed to iterate key: %s", e)
|
72
|
+
target.log.debug("", exc_info=e)
|
57
73
|
except TargetError as e:
|
58
74
|
log.error(e)
|
59
75
|
log.debug("", exc_info=e)
|
60
76
|
parser.exit(1)
|
61
77
|
|
62
78
|
|
63
|
-
def recursor(key, depth, indent):
|
64
|
-
|
79
|
+
def recursor(key: RegistryKey, depth: int, indent: int, max_length: int = 100) -> None:
|
80
|
+
class_name = ""
|
81
|
+
if key.class_name:
|
82
|
+
class_name = f" ({key.class_name})"
|
83
|
+
|
84
|
+
print(" " * indent + f"+ {key.name!r} ({key.ts})" + class_name)
|
65
85
|
|
66
86
|
for r in key.values():
|
67
87
|
try:
|
68
|
-
|
88
|
+
value = repr(r.value)
|
89
|
+
if len(value) > max_length:
|
90
|
+
value = value[:max_length] + "..."
|
91
|
+
print(" " * indent + f" - {r.name!r} {value}")
|
69
92
|
except NotImplementedError:
|
70
93
|
continue
|
71
94
|
|
@@ -73,7 +96,7 @@ def recursor(key, depth, indent):
|
|
73
96
|
return
|
74
97
|
|
75
98
|
for subkey in key.subkeys():
|
76
|
-
recursor(subkey, depth - 1, indent + 2)
|
99
|
+
recursor(subkey, depth - 1, indent + 2, max_length)
|
77
100
|
|
78
101
|
|
79
102
|
if __name__ == "__main__":
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: dissect.target
|
3
|
-
Version: 3.16.
|
3
|
+
Version: 3.16.dev43
|
4
4
|
Summary: This module ties all other Dissect modules together, it provides a programming API and command line tools which allow easy access to various data sources inside disk images or file collections (a.k.a. targets)
|
5
5
|
Author-email: Dissect Team <dissect@fox-it.com>
|
6
6
|
License: Affero General Public License v3
|
@@ -35,7 +35,7 @@ Requires-Dist: flow.record ~=3.14.0
|
|
35
35
|
Requires-Dist: structlog
|
36
36
|
Provides-Extra: cb
|
37
37
|
Requires-Dist: dissect.target[full] ; extra == 'cb'
|
38
|
-
Requires-Dist: carbon-black-cloud-sdk
|
38
|
+
Requires-Dist: carbon-black-cloud-sdk ~=1.4.3 ; extra == 'cb'
|
39
39
|
Provides-Extra: full
|
40
40
|
Requires-Dist: asn1crypto ; extra == 'full'
|
41
41
|
Requires-Dist: dissect.btrfs <2.0.dev,>=1.0.dev ; extra == 'full'
|
@@ -48,7 +48,7 @@ dissect/target/helpers/configutil.py,sha256=t_UNvcWuMMT5C1tut_PgTwCnVUodf6RjhfXP
|
|
48
48
|
dissect/target/helpers/cyber.py,sha256=Ki5oSU0GgQxjgC_yWoeieGP7GOY5blQCzNX7vy7Pgas,16782
|
49
49
|
dissect/target/helpers/descriptor_extensions.py,sha256=uT8GwznfDAiIgMM7JKKOY0PXKMv2c0GCqJTCkWFgops,2605
|
50
50
|
dissect/target/helpers/docs.py,sha256=J5U65Y3yOTqxDEZRCdrEmO63XQCeDzOJea1PwPM6Cyc,5146
|
51
|
-
dissect/target/helpers/fsutil.py,sha256=
|
51
|
+
dissect/target/helpers/fsutil.py,sha256=tPyH4RBDqM9QXjamIQaDRLUy3b4dKmfrT6k3ZP01U6Y,19772
|
52
52
|
dissect/target/helpers/hashutil.py,sha256=SD24rcV_y0sBEl7M9T-isjm-VzJvCiTN2BoWMqAOAVI,2160
|
53
53
|
dissect/target/helpers/keychain.py,sha256=wYH0sf7eaxP0bZTo80RF_BQMWulCWmIQ8Tzt9K5TSNQ,3611
|
54
54
|
dissect/target/helpers/lazy.py,sha256=823VtmdWsbJyVZvNWopDhQdqq2i1xtj6b8IKfveboKw,1771
|
@@ -78,7 +78,7 @@ dissect/target/loaders/ad1.py,sha256=1_VmPZckDzXVvNF-HNtoUZqabnhCKBLUD3vVaitHQ00
|
|
78
78
|
dissect/target/loaders/asdf.py,sha256=dvPPDBrnz2JPXpCbqsu-NgQWIdVGMOit2KAdhIO1iiQ,972
|
79
79
|
dissect/target/loaders/cb.py,sha256=EGhdytBKBdofTd89juavDZZbmupEZmMBadeUXvVIK20,6612
|
80
80
|
dissect/target/loaders/cyber.py,sha256=Ip2hI7L98ZP7gUZuHQr0GxBdmbTzD-PntXmLJ5KpBuQ,1533
|
81
|
-
dissect/target/loaders/dir.py,sha256=
|
81
|
+
dissect/target/loaders/dir.py,sha256=Q5oVS48SuI0vA_QKgzWBiAFsQ4aQaW3tr-701vLk3AQ,5245
|
82
82
|
dissect/target/loaders/hyperv.py,sha256=_IOUJEO0BXaCBZ6sjIX0DZTkG9UNW5Vs9VcNHYv073w,5928
|
83
83
|
dissect/target/loaders/itunes.py,sha256=69aMTQiiGYpmD_EYSmf9mO1re8C3jAZIEStmwlMxdAk,13146
|
84
84
|
dissect/target/loaders/kape.py,sha256=t5TfrGLqPeIpUUpXzIl6aHsqXMEGDqJ5YwDCs07DiBA,1237
|
@@ -102,7 +102,7 @@ dissect/target/loaders/targetd.py,sha256=sfbn2_j3il2G-rPywAoNT5YPtD5KmKkmBv1zrPD
|
|
102
102
|
dissect/target/loaders/utm.py,sha256=e5x5ZI3HeL0STh4S-CaQb68Rnug4SVZR9zlmHaGFj0M,978
|
103
103
|
dissect/target/loaders/vb.py,sha256=CnQcn7bAkMzIB1y-lWLtPPXdIVsyeDaT6hTZEurjkV4,2072
|
104
104
|
dissect/target/loaders/vbox.py,sha256=8JD7D8iAY9JRvTHsrosp5ZMsZezuLhZ10Zt8sEL7KBI,732
|
105
|
-
dissect/target/loaders/velociraptor.py,sha256=
|
105
|
+
dissect/target/loaders/velociraptor.py,sha256=FNxZgs_ehmgGO_Giw5oNl7cVOWNqI2nEiPWT4GjF2e0,4955
|
106
106
|
dissect/target/loaders/vma.py,sha256=AAY5-s-nz6wgvmcFkptJD7nNXhpkdf6SqEKVOrJaIKs,644
|
107
107
|
dissect/target/loaders/vmwarevm.py,sha256=1MlKoIuWSwpYmpuLxDuVacvaYHUhAGO1KgZxzrc4fyg,428
|
108
108
|
dissect/target/loaders/vmx.py,sha256=o1rYYKu6ReleqqHf2aeRcNrmoRcngWZNhz1h7GlmggQ,962
|
@@ -317,7 +317,7 @@ dissect/target/tools/info.py,sha256=3smHr8I71yj3kCjsQ5nXkOHI9T_N8UwvkVa1CNOxB-s,
|
|
317
317
|
dissect/target/tools/logging.py,sha256=5ZnumtMWLyslxfrUGZ4ntRyf3obOOhmn8SBjKfdLcEg,4174
|
318
318
|
dissect/target/tools/mount.py,sha256=L_0tSmiBdW4aSaF0vXjB0bAkTC0kmT2N1hrbW6s5Jow,3254
|
319
319
|
dissect/target/tools/query.py,sha256=1LbvUKSmXOCMb4xqP3t86JkOgFzKlc7mLCqcczfLht8,16018
|
320
|
-
dissect/target/tools/reg.py,sha256=
|
320
|
+
dissect/target/tools/reg.py,sha256=FDsiBBDxjWVUBTRj8xn82vZe-J_d9piM-TKS3PHZCcM,3193
|
321
321
|
dissect/target/tools/shell.py,sha256=EBRNKiIV3ljaXKAXraA6DmrIw8Cy5h9irAuwlblP3zo,43251
|
322
322
|
dissect/target/tools/utils.py,sha256=bhVZ3-8YynpHkBl4m1T4IpSpCArAXnEjjYwAFGW5JPg,10595
|
323
323
|
dissect/target/tools/dump/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -332,10 +332,10 @@ dissect/target/volumes/luks.py,sha256=OmCMsw6rCUXG1_plnLVLTpsvE1n_6WtoRUGQbpmu1z
|
|
332
332
|
dissect/target/volumes/lvm.py,sha256=wwQVR9I3G9YzmY6UxFsH2Y4MXGBcKL9aayWGCDTiWMU,2269
|
333
333
|
dissect/target/volumes/md.py,sha256=j1K1iKmspl0C_OJFc7-Q1BMWN2OCC5EVANIgVlJ_fIE,1673
|
334
334
|
dissect/target/volumes/vmfs.py,sha256=-LoUbn9WNwTtLi_4K34uV_-wDw2W5hgaqxZNj4UmqAQ,1730
|
335
|
-
dissect.target-3.16.
|
336
|
-
dissect.target-3.16.
|
337
|
-
dissect.target-3.16.
|
338
|
-
dissect.target-3.16.
|
339
|
-
dissect.target-3.16.
|
340
|
-
dissect.target-3.16.
|
341
|
-
dissect.target-3.16.
|
335
|
+
dissect.target-3.16.dev43.dist-info/COPYRIGHT,sha256=m-9ih2RVhMiXHI2bf_oNSSgHgkeIvaYRVfKTwFbnJPA,301
|
336
|
+
dissect.target-3.16.dev43.dist-info/LICENSE,sha256=DZak_2itbUtvHzD3E7GNUYSRK6jdOJ-GqncQ2weavLA,34523
|
337
|
+
dissect.target-3.16.dev43.dist-info/METADATA,sha256=k_mmSMwlIKc86B11l-UAys9JHWtSfbicJtUob1FmEfE,11100
|
338
|
+
dissect.target-3.16.dev43.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
|
339
|
+
dissect.target-3.16.dev43.dist-info/entry_points.txt,sha256=tvFPa-Ap-gakjaPwRc6Fl6mxHzxEZ_arAVU-IUYeo_s,447
|
340
|
+
dissect.target-3.16.dev43.dist-info/top_level.txt,sha256=Mn-CQzEYsAbkxrUI0TnplHuXnGVKzxpDw_po_sXpvv4,8
|
341
|
+
dissect.target-3.16.dev43.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
{dissect.target-3.16.dev39.dist-info → dissect.target-3.16.dev43.dist-info}/entry_points.txt
RENAMED
File without changes
|
File without changes
|