// # Source: https://github.com/huwangkeji/juejin_checkin/blob/main/juejin-extension/content.js // # Raw: https://raw.githubusercontent.com/huwangkeji/juejin_checkin/main/juejin-extension/content.js // # Repo: huwangkeji/juejin_checkin // # Path: juejin-extension/content.js // # UploadedAt: 2026-05-19T14:34:11Z // # SHA256: 45c4e3523ff88ee080e76c2c8b635c4a14657f9f97fa395d368b9bccf09b4bca // # Category: APP版/抓包 // # Evidence: cookie/token/authorization/header // /** * 掘金参数提取器 - Content Script (MAIN world) * 直接在页面主世界运行,hook 真实的 fetch/XHR,参数存到 sessionStorage */ (function() { 'use strict'; if (window.__JUEJIN_EXTRACTOR_HOOKED__) return; window.__JUEJIN_EXTRACTOR_HOOKED__ = true; const STORAGE_KEY = '__juejin_extractor_data__'; function readStored() { try { return JSON.parse(sessionStorage.getItem(STORAGE_KEY) || '{}'); } catch (e) { return {}; } } function writeStored(data) { const existing = readStored(); const merged = { ...existing, ...data }; try { sessionStorage.setItem(STORAGE_KEY, JSON.stringify(merged)); } catch (e) {} } function extractFromUrl(url) { try { const u = new URL(url); if (u.hostname === 'api.juejin.cn' || u.hostname.includes('juejin.cn')) { return { aid: u.searchParams.get('aid') || '', uuid: u.searchParams.get('uuid') || '', msToken: u.searchParams.get('msToken') || '', a_bogus: u.searchParams.get('a_bogus') || '', spider: u.searchParams.get('spider') || '', }; } } catch (e) {} return null; } function mergeParams(params, cookie) { const data = readStored(); let changed = false; if (cookie && cookie.length > 10) { data.cookie = cookie; changed = true; } if (params.aid && params.aid !== 'null' && params.aid !== data.aid) { data.aid = params.aid; changed = true; } if (params.uuid && params.uuid.length > 5 && params.uuid !== data.uuid) { data.uuid = params.uuid; changed = true; } if (params.msToken && params.msToken.length > 5 && params.msToken !== data.msToken) { data.msToken = params.msToken; changed = true; } if (params.a_bogus && params.a_bogus.length > 5 && params.a_bogus !== data.a_bogus) { data.a_bogus = params.a_bogus; changed = true; } if (params.spider && params.spider !== data.spider) { data.spider = params.spider; changed = true; } if (changed) { data.captureTime = new Date().toLocaleString('zh-CN'); writeStored(data); } } // ===== Hook fetch ===== const _origFetch = window.fetch; window.fetch = function fetchHook(input, init) { try { const url = typeof input === 'string' ? input : (input.url || input.toString()); const params = extractFromUrl(url); if (params) { let cookie = ''; try { cookie = document.cookie; } catch (e) {} mergeParams(params, cookie); } } catch (e) {} return _origFetch.apply(this, arguments); }; // ===== Hook XMLHttpRequest ===== const _origOpen = XMLHttpRequest.prototype.open; const _origSend = XMLHttpRequest.prototype.send; XMLHttpRequest.prototype.open = function(method, url) { this._juejinUrl = url; return _origOpen.apply(this, arguments); }; XMLHttpRequest.prototype.send = function(body) { try { if (this._juejinUrl) { const params = extractFromUrl(this._juejinUrl); if (params) { let cookie = ''; try { cookie = document.cookie; } catch (e) {} mergeParams(params, cookie); } } } catch (e) {} return _origSend.apply(this, arguments); }; // ===== 扫描 performance entries ===== function scanPerf() { try { const entries = performance.getEntriesByType('resource'); for (const entry of entries) { if (entry.name && entry.name.includes('api.juejin.cn')) { const params = extractFromUrl(entry.name); if (params) { let cookie = ''; try { cookie = document.cookie; } catch (e) {} mergeParams(params, cookie); } } } } catch (e) {} } scanPerf(); let count = 0; const timer = setInterval(() => { scanPerf(); count++; if (count >= 20) clearInterval(timer); }, 2000); // ===== 页面稳定后主动触发 harmless 请求 ===== function triggerCapture() { try { const t = Date.now(); _origFetch.call(window, `https://api.juejin.cn/growth_api/v1/get_today_status?aid=2608&t=${t}`, { credentials: 'include', headers: { 'Accept': 'application/json' } } ).catch(() => {}); } catch (e) {} } if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', () => { setTimeout(triggerCapture, 1000); setTimeout(triggerCapture, 3000); }); } else { setTimeout(triggerCapture, 1000); setTimeout(triggerCapture, 3000); } console.log('[掘金参数提取器] Content script (MAIN world) 已注入'); })();