UNPKG

chrome-cookie-extractor

Version:

Extract and decrypt Chrome cookies with curl integration - includes auth-curl command for authenticated requests

262 lines 11.5 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.ChromeCookieExtractor = void 0; const sqlite3 = __importStar(require("sqlite3")); const fs = __importStar(require("fs")); const path = __importStar(require("path")); const os = __importStar(require("os")); const profile_detector_1 = require("./profile-detector"); const decryptor_1 = require("./decryptor"); class ChromeCookieExtractor { constructor() { this.profiles = profile_detector_1.ProfileDetector.detectAllProfiles(); } getProfiles() { return this.profiles; } async extractCookies(options = {}) { if (this.profiles.length === 0) { throw new Error('No Chrome/Brave profiles found'); } const allCookies = []; const { domain, profiles: requestedProfiles } = options; const profilesToProcess = requestedProfiles ? this.profiles.filter(p => requestedProfiles.includes(p.name)) : this.profiles; for (const profile of profilesToProcess) { try { const cookies = await this.extractFromDatabase(profile.cookiesPath, domain); allCookies.push(...cookies); } catch (error) { console.error(`Warning: Failed to extract cookies from ${profile.name}:`, error); } } return allCookies; } async extractFromDatabase(cookiesPath, domain) { return new Promise((resolve, reject) => { // Try direct access first without copying const db = new sqlite3.Database(cookiesPath, sqlite3.OPEN_READONLY, (err) => { if (err) { // If direct access fails, try the copy method this.extractFromDatabaseWithCopy(cookiesPath, domain) .then(resolve) .catch(reject); return; } // Set busy timeout to handle locks db.run('PRAGMA busy_timeout = 30000', (err) => { if (err) { console.warn('Could not set busy timeout:', err); } }); // Check table structure db.all('PRAGMA table_info(cookies)', (err, rows) => { if (err) { db.close(); reject(err); return; } const columns = rows.map(row => row.name); const hasEncryptedValue = columns.includes('encrypted_value'); let query; let params = []; if (hasEncryptedValue) { query = ` SELECT name, value, encrypted_value, host_key, path, expires_utc, is_secure, is_httponly, creation_utc FROM cookies `; } else { query = ` SELECT name, value, host_key, path, expires_utc, is_secure, is_httponly, creation_utc FROM cookies `; } if (domain) { query += ' WHERE host_key LIKE ?'; params.push(`%${domain}%`); } db.all(query, params, (err, rows) => { if (err) { db.close(); reject(err); return; } const cookies = []; for (const row of rows) { let finalValue; if (hasEncryptedValue && row.encrypted_value) { // Try to decrypt the encrypted value const decryptedValue = decryptor_1.CookieDecryptor.decryptValue(row.encrypted_value); finalValue = decryptedValue !== '[ENCRYPTED]' ? decryptedValue : row.value || '[ENCRYPTED]'; } else { finalValue = row.value || ''; } cookies.push({ name: row.name, value: finalValue, domain: row.host_key, path: row.path, expires: row.expires_utc, secure: Boolean(row.is_secure), httponly: Boolean(row.is_httponly), creationTime: row.creation_utc }); } db.close(); resolve(cookies); }); }); }); }); } async extractFromDatabaseWithCopy(cookiesPath, domain) { // Create temporary copy to avoid database lock issues const tempDir = os.tmpdir(); const tempCookiesPath = path.join(tempDir, `cookies_${Date.now()}_${Math.random().toString(36).slice(2)}.db`); try { fs.copyFileSync(cookiesPath, tempCookiesPath); return new Promise((resolve, reject) => { const db = new sqlite3.Database(tempCookiesPath, sqlite3.OPEN_READONLY, (err) => { if (err) { reject(err); return; } // Check table structure db.all('PRAGMA table_info(cookies)', (err, rows) => { if (err) { db.close(); reject(err); return; } const columns = rows.map(row => row.name); const hasEncryptedValue = columns.includes('encrypted_value'); let query; let params = []; if (hasEncryptedValue) { query = ` SELECT name, value, encrypted_value, host_key, path, expires_utc, is_secure, is_httponly, creation_utc FROM cookies `; } else { query = ` SELECT name, value, host_key, path, expires_utc, is_secure, is_httponly, creation_utc FROM cookies `; } if (domain) { query += ' WHERE host_key LIKE ?'; params.push(`%${domain}%`); } db.all(query, params, (err, rows) => { if (err) { db.close(); reject(err); return; } const cookies = []; for (const row of rows) { let finalValue; if (hasEncryptedValue && row.encrypted_value) { // Try to decrypt the encrypted value const decryptedValue = decryptor_1.CookieDecryptor.decryptValue(row.encrypted_value); finalValue = decryptedValue !== '[ENCRYPTED]' ? decryptedValue : row.value || '[ENCRYPTED]'; } else { finalValue = row.value || ''; } cookies.push({ name: row.name, value: finalValue, domain: row.host_key, path: row.path, expires: row.expires_utc, secure: Boolean(row.is_secure), httponly: Boolean(row.is_httponly), creationTime: row.creation_utc }); } db.close(); resolve(cookies); }); }); }); }); } finally { // Clean up temporary file if (fs.existsSync(tempCookiesPath)) { fs.unlinkSync(tempCookiesPath); } } } formatAsNetscape(cookies) { const lines = ['# Netscape HTTP Cookie File']; for (const cookie of cookies) { // Skip encrypted cookies if (cookie.value === '[ENCRYPTED]') { continue; } // Convert Chrome's expires_utc (Windows FILETIME) to Unix timestamp const expires = cookie.expires > 0 ? Math.floor((cookie.expires - 11644473600000000) / 1000000) : 0; const domain = cookie.domain; const domainFlag = domain.startsWith('.') ? 'TRUE' : 'FALSE'; const path = cookie.path; const secure = cookie.secure ? 'TRUE' : 'FALSE'; const name = cookie.name; const value = cookie.value; lines.push(`${domain}\t${domainFlag}\t${path}\t${secure}\t${expires}\t${name}\t${value}`); } return lines.join('\n'); } formatAsCurl(cookies) { const validCookies = cookies.filter(c => c.value !== '[ENCRYPTED]'); if (validCookies.length === 0) { return ''; } const cookiePairs = validCookies.map(c => `${c.name}=${c.value}`); return `-H "Cookie: ${cookiePairs.join('; ')}"`; } formatAsJson(cookies) { return JSON.stringify(cookies, null, 2); } async saveCookiesFile(cookies, outputPath) { const netscapeFormat = this.formatAsNetscape(cookies); fs.writeFileSync(outputPath, netscapeFormat, 'utf8'); } } exports.ChromeCookieExtractor = ChromeCookieExtractor; //# sourceMappingURL=extractor.js.map