/** * 虚拟身份池 * 用于生成随机持卡人姓名 */ const FIRST_NAMES = ["John", "Michael", "David", "James", "Robert", "William", "Richard", "Joseph", "Charles", "Thomas", "Christopher", "Daniel", "Matthew", "Anthony", "Mark", "Donald", "Steven", "Paul", "Andrew", "Joshua", "Kenneth", "Kevin", "Brian", "Mary", "Patricia", "Jennifer", "Linda", "Barbara", "Elizabeth", "Susan", "Jessica", "Sarah", "Karen", "Nancy", "Lisa", "Betty", "Margaret", "Sandra"]; const LAST_NAMES = ["Smith", "Johnson", "Williams", "Brown", "Jones", "Garcia", "Miller", "Davis", "Rodriguez", "Martinez", "Hernandez", "Lopez", "Gonzalez", "Wilson", "Anderson", "Thomas", "Taylor", "Moore", "Jackson", "Martin", "Lee", "Thompson", "White", "Harris", "Sanchez", "Clark", "Ramirez", "Lewis", "Robinson", "Walker", "Young"]; /** * 默认地址配置 */ const DEFAULT_ADDRESSES = [{ name: "John Smith", firstName: "John", lastName: "Smith", address1: "69 Adams Street", address2: "", city: "Brooklyn", state: "New York", stateCode: "NY", postal: "11201", countryText: "United States", countryValue: "US" }, { name: "Michael Johnson", firstName: "Michael", lastName: "Johnson", address1: "3511 Carlisle Avenue", address2: "", city: "Covington", state: "Kentucky", stateCode: "KY", postal: "41015", countryText: "United States", countryValue: "US" }]; // ========================================== // 算法工具函数 (Luhn Algorithm) // ========================================== function randomChoice(array) { return array[Math.floor(Math.random() * array.length)]; } /** * 根据卡号前缀识别卡组织类型 */ function getCardType(cardNumber) { const patterns = { Visa: /^4/, Mastercard: /^5[1-5]/, "American Express": /^3[47]/, Discover: /^6(?:011|5)/, JCB: /^35/, "Diners Club": /^3(?:0[0-5]|[68])/, Maestro: /^(?:5[0678]\d\d|6304|6390|67\d\d)/, UnionPay: /^62/ }; for (const [type, regex] of Object.entries(patterns)) { if (regex.test(cardNumber)) { return type; } } return "Unknown"; } /** * 计算 Luhn 校验位 (模10算法) * 用于确保生成的卡号在数学上是有效的 */ function calculateLuhnCheckDigit(digits) { let sum = 0; let shouldDouble = true; for (let i = digits.length - 1; i >= 0; i--) { let digit = parseInt(digits[i]); if (shouldDouble) { digit *= 2; if (digit > 9) { digit -= 9; } } sum += digit; shouldDouble = !shouldDouble; } return (10 - sum % 10) % 10; } /** * 验证卡号是否符合 Luhn 算法 */ function validateLuhn(number) { const digits = number.replace(/\D/g, ""); let sum = 0; let shouldDouble = false; for (let i = digits.length - 1; i >= 0; i--) { let digit = parseInt(digits[i]); if (shouldDouble) { digit *= 2; if (digit > 9) { digit -= 9; } } sum += digit; shouldDouble = !shouldDouble; } return sum % 10 === 0; } /** * 生成符合校验规则的卡号 * @param {string} binPattern - BIN 格式 (如 "552461xxxxxxxxxx") */ function generateValidCardNumber(binPattern) { let rawNumber = ""; // 1. 填充随机数 for (let i = 0; i < binPattern.length - 1; i++) { if (binPattern[i] === "x" || binPattern[i] === "X") { rawNumber += Math.floor(Math.random() * 10); } else { rawNumber += binPattern[i]; } } // 2. 计算最后一位校验码 const checkDigit = calculateLuhnCheckDigit(rawNumber); rawNumber += checkDigit; return rawNumber; } function generateExpiryDate() { const now = new Date(); const currentYear = now.getFullYear(); const currentMonth = now.getMonth() + 1; // 随机生成 1 到 60 个月后的日期 const randomMonths = Math.floor(Math.random() * 60) + 1; let targetMonth = currentMonth + randomMonths; let targetYear = currentYear; while (targetMonth > 12) { targetMonth -= 12; targetYear += 1; } return { month: targetMonth.toString().padStart(2, "0"), year: targetYear.toString() }; } function generateCVV(length = 3) { let cvv = ""; for (let i = 0; i < length; i++) { cvv += Math.floor(Math.random() * 10); } return cvv; } // ========================================== // 核心生成逻辑 // ========================================== /** * 本地生成模式:使用内置算法生成卡号 */ function generateCardsLocally(bin, amount = 10) { const cards = []; const uniqueSet = new Set(); console.log(`🎲 Generating ${amount} valid cards from BIN: ${bin}`); let attempts = 0; const maxAttempts = amount * 10; while (cards.length < amount && attempts < maxAttempts) { attempts++; const number = generateValidCardNumber(bin); if (uniqueSet.has(number)) continue; if (!validateLuhn(number)) { console.warn("⚠️ Generated invalid card (should not happen):", number); continue; } uniqueSet.add(number); const expiry = generateExpiryDate(); const cvv = generateCVV(3); const type = getCardType(number); cards.push({ serial_number: cards.length + 1, card_number: number, expiry_month: expiry.month, expiry_year: expiry.year, cvv: cvv, card_type: type, full_format: `${number}|${expiry.month}|${expiry.year}|${cvv}`, luhn_valid: true }); } console.log(`[cardbingenerator] Successfully generated ${cards.length} valid cards`); // 最后的完整性检查 const invalid = cards.filter(c => !validateLuhn(c.card_number)); if (invalid.length > 0) { console.error(`❌ Found ${invalid.length} invalid cards!`); } else { console.log("[cardbingenerator] All cards passed Luhn validation"); } // 统计卡种分布 const stats = {}; cards.forEach(c => { stats[c.card_type] = (stats[c.card_type] || 0) + 1; }); console.log("📊 Card types:", stats); return cards; } /** * 简单生成模式:仅生成随机数,不进行 Luhn 校验 (用于某些不需要校验的测试场景) */ function generateCardsSimple(bin, amount = 10) { const cards = []; const uniqueSet = new Set(); console.log(`🎲 Generating ${amount} cards (no validation) from BIN: ${bin}`); for (let i = 0; i < amount; i++) { let number = ""; for (let j = 0; j < bin.length; j++) { if (bin[j] === "x" || bin[j] === "X") { number += Math.floor(Math.random() * 10); } else { number += bin[j]; } } if (uniqueSet.has(number)) { i--; continue; } uniqueSet.add(number); const expiry = generateExpiryDate(); const cvv = generateCVV(3); const type = getCardType(number); cards.push({ serial_number: i + 1, card_number: number, expiry_month: expiry.month, expiry_year: expiry.year, cvv: cvv, card_type: type, full_format: `${number}|${expiry.month}|${expiry.year}|${cvv}`, luhn_valid: false }); } console.log(`[cardbingenerator] Generated ${cards.length} cards (simple mode)`); return cards; } // ========================================== // 远程生成逻辑 (AKR-Gen) // ========================================== /** * 远程生成模式:操控第三方网站 (akr-gen.bigfk.com) 生成卡号 * 当本地算法不满足需求时使用 */ async function generateCardsFromAKR(bin, onComplete) { let tab = null; try { console.log("[cardbingenerator] Opening AKR-gen tab..."); // 创建一个不激活的标签页(后台静默打开) tab = await chrome.tabs.create({ url: "https://akr-gen.bigfk.com/", active: false }); console.log("[cardbingenerator] Waiting for page load..."); await new Promise(resolve => setTimeout(resolve, 4000)); console.log("[cardbingenerator] Filling BIN and generating cards..."); // 注入脚本:自动填入BIN并点击生成 const fillResult = await chrome.scripting.executeScript({ target: { tabId: tab.id }, func: remotePage_fillAndClick, args: [bin] }); console.log("Fill result:", fillResult[0]?.result); console.log("⏳ Waiting a moment before checking results..."); await new Promise(resolve => setTimeout(resolve, 2000)); console.log("📥 Getting generated cards (will wait up to 10 seconds)..."); // 注入脚本:抓取结果 const scrapeResult = await chrome.scripting.executeScript({ target: { tabId: tab.id }, func: remotePage_scrapeResults }); console.log("[cardbingenerator] Closing AKR-gen tab..."); await chrome.tabs.remove(tab.id); tab = null; if (scrapeResult && scrapeResult[0] && scrapeResult[0].result) { const parsedCards = parseScrapedCards(scrapeResult[0].result); console.log(`[cardbingenerator] Generated ${parsedCards.length} cards`); if (parsedCards.length > 0) { const randomAddr = await getRandomAddress(); // 存入 storage 供 Content Script 使用 chrome.storage.local.set({ generatedCards: parsedCards, randomData: randomAddr }); onComplete({ success: true, cards: parsedCards }); } else { console.error("❌ No cards generated from AKR"); onComplete({ success: false, error: "No cards generated from AKR-gen" }); } } else { console.error("❌ Failed to retrieve cards from result"); onComplete({ success: false, error: "Failed to retrieve cards from page" }); } } catch (err) { console.error("❌ Error in generateCardsFromAKR:", err); if (tab) { try { await chrome.tabs.remove(tab.id); } catch (e) {} } onComplete({ success: false, error: err.message }); } } // -- 以下函数会被注入到目标页面执行,不能使用外部变量 -- function remotePage_fillAndClick(bin) { return new Promise(resolve => { function waitForElement(selector, retries = 10, delay = 300) { return new Promise(res => { let count = 0; const check = () => { const el = document.querySelector(selector) || document.getElementById(selector.replace("#", "")); if (el) { res(el); } else if (count < retries) { count++; setTimeout(check, delay); } else { res(null); } }; check(); }); } waitForElement("bin").then(input => { if (input) { console.log("[cardbingenerator] Found BIN input, filling with:", bin); input.value = bin; input.dispatchEvent(new Event("input", { bubbles: true })); input.dispatchEvent(new Event("change", { bubbles: true })); setTimeout(() => { waitForElement("button[type=\"submit\"]").then(btn => { if (btn) { console.log("[cardbingenerator] Found generate button, clicking..."); btn.click(); resolve(true); } else { console.error("❌ Generate button not found"); resolve(false); } }); }, 500); } else { console.error("❌ BIN input not found"); resolve(false); } }); }); } function remotePage_scrapeResults() { return new Promise(resolve => { function waitLoop(retries = 20, delay = 500) { let count = 0; const check = () => { const resultArea = document.getElementById("result"); if (resultArea && resultArea.value.trim()) { console.log("[cardbingenerator] Found generated cards:", resultArea.value.split("\n").length, "lines"); resolve(resultArea.value); } else if (count < retries) { count++; console.log(`[cardbingenerator] Waiting for cards... attempt ${count}/${retries}`); setTimeout(check, delay); } else { console.error("❌ Timeout waiting for cards"); resolve(""); } }; check(); } waitLoop(); }); } // ---------------------------------------------------- function parseScrapedCards(text) { if (!text) return []; const lines = text.trim().split("\n"); const cards = []; lines.forEach((line, index) => { if (line.trim()) { const parts = line.trim().split("|"); if (parts.length === 4) { cards.push({ serial_number: index + 1, card_number: parts[0], expiry_month: parts[1], expiry_year: parts[2], cvv: parts[3], full_format: line.trim() }); } } }); return cards; } /** * 辅助:获取随机地址 */ async function getRandomAddress() { return new Promise(resolve => { chrome.storage.local.get(["customAddresses"], data => { const custom = data.customAddresses || []; const pool = [...custom, ...DEFAULT_ADDRESSES]; if (pool.length === 0) { resolve(DEFAULT_ADDRESSES[0]); } else { const selected = randomChoice(pool); resolve(selected); } }); }); } // ========================================== // 数据清理逻辑 (Browsing Data API) // ========================================== async function clearStripeBrowsingData(sendResponse) { try { const domains = ["stripe.com", "checkout.stripe.com", "js.stripe.com", "hooks.stripe.com"]; // 1. 深度清理 Cookies (针对特定域) for (const domain of domains) { const cookies = await chrome.cookies.getAll({ domain: domain }); for (const cookie of cookies) { await chrome.cookies.remove({ url: "https://" + cookie.domain + cookie.path, name: cookie.name }); } } // 2. 清理浏览器缓存和存储 (针对特定 Origin) await chrome.browsingData.remove({ origins: domains.map(d => "https://" + d) }, { cache: true, cookies: true, localStorage: true, indexedDB: true, serviceWorkers: true, cacheStorage: true }); console.log("[cardbingenerator] Deep clear completed for Stripe domains"); if (sendResponse) sendResponse({ success: true }); } catch (err) { console.error("Error in deep clear:", err); if (sendResponse) sendResponse({ success: false, error: err.message }); } } // ========================================== // 消息监听与路由 // ========================================== // 安装时初始化默认 BIN chrome.runtime.onInstalled.addListener(() => { chrome.storage.local.get(["currentBin", "binHistory"], data => { if (!data.currentBin) { chrome.storage.local.set({ currentBin: "552461xxxxxxxxxx", binHistory: ["552461xxxxxxxxxx"] }); } }); }); // 主消息处理器 chrome.runtime.onMessage.addListener((request, sender, sendResponse) => { if (request.action === "generateCards") { // 路由到生成逻辑 generateCardsHandler(request.bin, request.useValidation, sendResponse); return true; // 保持消息通道打开以进行异步响应 } if (request.action === "clearBrowsingData") { // 路由到清理逻辑 clearStripeBrowsingData(sendResponse); return true; } }); async function generateCardsHandler(bin, useValidation = true, sendResponse) { try { console.log(`[cardbingenerator] Starting card generation... (Luhn: ${useValidation ? "ON" : "OFF"})`); // 根据配置决定是验证 Luhn 还是简单生成 const cards = useValidation ? generateCardsLocally(bin, 10) : generateCardsSimple(bin, 10); if (cards.length > 0) { const address = await getRandomAddress(); // 将结果存入 storage,这样 Content Script (第一部分代码) 就能读到了 chrome.storage.local.set({ generatedCards: cards, randomData: address }); console.log(`[cardbingenerator] Generated and saved ${cards.length} cards`); sendResponse({ success: true, cards: cards }); } else { console.error("❌ No cards generated"); sendResponse({ success: false, error: "Failed to generate cards" }); } } catch (err) { console.error("❌ Error in generateCardsHandler:", err); sendResponse({ success: false, error: err.message }); } }