diff options
author | Trygve Aaberge <trygveaa@gmail.com> | 2023-06-29 02:14:16 +0200 |
---|---|---|
committer | Trygve Aaberge <trygveaa@gmail.com> | 2023-06-29 22:15:55 +0200 |
commit | 4b6042a33bc276446b8ce937ef137947e292a048 (patch) | |
tree | 69646d0749d814593a3bada3c5db232454cfdbbb | |
parent | 3fa2bbc8985f8250a4cea1cd4f6d9ae7cf80ea83 (diff) | |
download | wee-slack-4b6042a33bc276446b8ce937ef137947e292a048.tar.gz |
Clearly separate code for Firefox and Chrome
This makes the code much easier to read in my opinion. It also fixes
some errors about potentially unbound variables.
-rwxr-xr-x | extract_token_from_browser.py | 112 |
1 files changed, 61 insertions, 51 deletions
diff --git a/extract_token_from_browser.py b/extract_token_from_browser.py index 375b290..3cc110a 100755 --- a/extract_token_from_browser.py +++ b/extract_token_from_browser.py @@ -3,27 +3,15 @@ from __future__ import annotations import argparse -from contextlib import contextmanager import json import os -from typing import TYPE_CHECKING -import secretstorage import shutil import sqlite3 import sys - +from contextlib import contextmanager from pathlib import Path -from secretstorage.exceptions import SecretStorageException from sqlite3 import OperationalError - -try: - import_err = None - from Crypto.Cipher import AES - from Crypto.Protocol.KDF import PBKDF2 - from plyvel import DB - from plyvel._plyvel import IOError as pIOErr -except ModuleNotFoundError as e: - import_err = e +from typing import TYPE_CHECKING, Literal, assert_never if TYPE_CHECKING: from _typeshed import StrPath @@ -50,6 +38,20 @@ def sqlite3_connect(path: StrPath): con.close() +def get_cookies(cookies_path: StrPath, cookie_d_query: str, cookie_ds_query: str): + cookie_d_value = None + try: + with sqlite3_connect(cookies_path) as con: + cookie_d_value = con.execute(cookie_d_query).fetchone()[0] + cookie_ds_value = con.execute(cookie_ds_query).fetchone()[0] + return cookie_d_value, cookie_ds_value + except TypeError: + if not cookie_d_value: + print("Couldn't find the 'd' cookie value", file=sys.stderr) + sys.exit(1) + return cookie_d_value, None + + parser = argparse.ArgumentParser( description="Extract Slack tokens from the browser files" ) @@ -61,15 +63,21 @@ parser.add_argument( ) args = parser.parse_args() +browser: Literal["firefox", "chrome"] + if sys.platform.startswith("linux"): chrome_key_iterations = 1 if args.browser == "firefox-snap": + browser = "firefox" browser_data = Path.home().joinpath("snap/firefox/common/.mozilla/firefox") elif args.browser == "firefox": + browser = "firefox" browser_data = Path.home().joinpath(".mozilla/firefox") elif args.browser == "chromium": + browser = "chrome" browser_data = Path.home().joinpath(".config/chromium") elif args.browser in ["chrome", "chrome-beta"]: + browser = "chrome" browser_data = Path.home().joinpath(".config/google-%s" % args.browser) else: print( @@ -79,12 +87,15 @@ if sys.platform.startswith("linux"): elif sys.platform.startswith("darwin"): chrome_key_iterations = 1003 if args.browser in ["firefox", "firefox-snap"]: + browser = "firefox" browser_data = Path.home().joinpath( "Library/Application Support/Firefox/Profiles" ) elif args.browser == "chromium": + browser = "chrome" browser_data = Path.home().joinpath("Library/Application Support/Chromium") elif args.browser in ["chrome", "chrome-beta"]: + browser = "chrome" browser_data = Path.home().joinpath("Library/Application Support/Google/Chrome") else: print( @@ -95,9 +106,9 @@ else: print("Currently only Linux and macOS is supported by this script", file=sys.stderr) sys.exit(1) -leveldb_path = None profile = args.profile -if args.browser in ["firefox", "firefox-snap"]: + +if browser == "firefox": cookie_d_query = ( "SELECT value FROM moz_cookies WHERE host = '.slack.com' " "AND name = 'd'" ) @@ -114,10 +125,28 @@ if args.browser in ["firefox", "firefox-snap"]: print("Couldn't find the default profile for Firefox", file=sys.stderr) sys.exit(1) cookies_path = default_profile_path.joinpath("cookies.sqlite") -else: - if import_err: - print("Missing required modules for Chrome browser support", file=sys.stderr) - raise import_err + + cookie_d_value, cookie_ds_value = get_cookies( + cookies_path, cookie_d_query, cookie_ds_query + ) + + local_storage_path = default_profile_path.joinpath("webappsstore.sqlite") + local_storage_query = "SELECT value FROM webappsstore2 WHERE key = 'localConfig_v2'" + local_config = None + try: + with sqlite3_connect(local_storage_path) as con: + local_config_str = con.execute(local_storage_query).fetchone()[0] + local_config = json.loads(local_config_str) + except (OperationalError, TypeError): + pass + +elif browser == "chrome": + import secretstorage + from Crypto.Cipher import AES + from Crypto.Protocol.KDF import PBKDF2 + from plyvel import DB + from plyvel._plyvel import IOError as pIOErr + from secretstorage.exceptions import SecretStorageException cookie_d_query = ( "SELECT encrypted_value FROM cookies WHERE " @@ -134,18 +163,10 @@ else: cookies_path = default_profile_path.joinpath("Cookies") leveldb_path = default_profile_path.joinpath("Local Storage/leveldb") -cookie_d_value = None -cookie_ds_value = None -try: - with sqlite3_connect(cookies_path) as con: - cookie_d_value = con.execute(cookie_d_query).fetchone()[0] - cookie_ds_value = con.execute(cookie_ds_query).fetchone()[0] -except TypeError: - if not cookie_d_value: - print("Couldn't find the 'd' cookie value", file=sys.stderr) - sys.exit(1) + cookie_d_value, cookie_ds_value = get_cookies( + cookies_path, cookie_d_query, cookie_ds_query + ) -if args.browser in ["chromium", "chrome", "chrome-beta"]: bus = secretstorage.dbus_init() try: collection = secretstorage.get_default_collection(bus) @@ -174,24 +195,6 @@ if args.browser in ["chromium", "chrome", "chrome-beta"]: if cookie_ds_value: cookie_ds_value = cipher.decrypt(cookie_ds_value[3:]).decode("utf8") -if cookie_ds_value: - cookie_value = f"d={cookie_d_value};d-s={cookie_ds_value}" -else: - cookie_value = cookie_d_value - -teams = [] - -if args.browser in ["firefox", "firefox-snap"]: - local_storage_path = default_profile_path.joinpath("webappsstore.sqlite") - local_storage_query = "SELECT value FROM webappsstore2 WHERE key = 'localConfig_v2'" - local_config = None - try: - with sqlite3_connect(local_storage_path) as con: - local_config_str = con.execute(local_storage_query).fetchone()[0] - local_config = json.loads(local_config_str) - except (OperationalError, TypeError): - pass -else: try: db = DB(str(leveldb_path)) except pIOErr: @@ -208,14 +211,21 @@ else: local_storage_value = db.get(b"_https://app.slack.com\x00\x01localConfig_v2") local_config = json.loads(local_storage_value[1:]) +else: + assert_never(browser) + +if cookie_ds_value: + cookie_value = f"d={cookie_d_value};d-s={cookie_ds_value}" +else: + cookie_value = cookie_d_value + if local_config: teams = [ team for team in local_config["teams"].values() if not team["id"].startswith("E") ] - -if not teams: +else: teams = [ { "token": "<token>", |