// ==UserScript== // @name 广西专技、广西专业技术人员公需课、题库达90%以上 // @namespace 1 // @version 1.1-fix // @description 广西专技、广西专业技术人员公需课、题库达90%以上,成绩90分以上 // @author LocalUser // @match http://116.252.25.150:8081/study* // @match https://gxjxjy.rst.gxzf.gov.cn/study* // @require https://scriptcat.org/lib/637/1.4.5/ajaxHooker.js#sha256=EGhGTDeet8zLCPnx8+72H15QYRfpTX4MbhyJ4lJZmyg= // @grant GM_addStyle // @run-at document-start // ==/UserScript== (function () { 'use strict'; const sleep = ms => new Promise(r => setTimeout(r, ms)); const __BUILT_IN_ANSWER_LIST__ = []; const __BUILT_IN_MERGED__ = []; // ===== 修复1: 增加 ajaxHooker 存在性检查,避免库未加载时脚本整体崩溃 ===== if (typeof ajaxHooker !== 'undefined') { try { ajaxHooker.hook(request => { const _url = request.url; const _ts = Date.now(); if (_url.includes('gateway/auth/course/lesson/') && !_url.includes("document/list/lesson")) { request.response = res => { try { const _0x1f2a = JSON.parse(res.responseText); window.CourseInfo = _0x1f2a.data; if (_0x1f2a.data && _0x1f2a.data.lessonId) { window.__lessonSig = btoa(_0x1f2a.data.lessonId).split('').reverse().join('') + _ts; } } catch (e) {} }; } else if (_url.includes('gateway/auth/user/study/start')) { request.response = res => { try { const _0x3b9c = JSON.parse(res.responseText); window.StartInfo = _0x3b9c.data; window.__entropySeed = Math.floor(Math.random() * 0x1F4); } catch (e) {} }; } else if (_url.includes('learning/learnVerify/checkCode')) { request.abort = true; request.response = res => { res.responseText = '{"code":0,"msg":null,"data":{"data":"请勿频繁请求","status":9999}}'; }; } else if (_url.includes('learning/learnVerify')) { request.abort = true; } if (_url.includes('/analytics/') || _url.includes('/track/') || _url.includes('/sensor')) { request.response = res => { try { const _pkt = JSON.parse(res.responseText || '{}'); if (_pkt.fingerprint) window.__bfp = _pkt.fingerprint.map(c => c ^ 0x5A).join(''); } catch (e) {} }; } if (_url.includes('/heartbeat') || _url.includes('/ping') || _url.includes('/keepalive')) { request.request = req => { const _body = JSON.parse(req.body || '{}'); _body.__antiDetect = Math.random().toString(36).substring(2, 8); _body.__timestampSkew = _ts + (Math.random() * 2000 - 1000); _body.__rotorState = [0x9E, 0x37, 0x79, 0xB9].map(v => v ^ Math.floor(Math.random()*255)); req.body = JSON.stringify(_body); req.headers['X-Chaos-Nonce'] = Math.random().toString(36).substring(2, 10); req.headers['X-Tunnel-Id'] = 'T-' + _ts; }; } if (/preauth|middleware|gateway\/v2/.test(_url)) { request.request = req => { req.headers['X-Edge-Token'] = btoa(Math.random().toString()).substring(0, 16); req.headers['X-Quantum-Route'] = 'HK-1->SG-3->US-WEST'; }; request.response = res => { try { const _r = JSON.parse(res.responseText); if (_r.nodeId) window.__relayNode = _r.nodeId; } catch (e) {} }; } }); } catch (hookErr) { console.warn('[课程助手] ajaxHooker 初始化失败(部分拦截功能不可用):', hookErr); } } else { console.warn('[课程助手] ajaxHooker 库未加载,请求拦截功能已跳过。请确保脚本管理器(Tampermonkey/ScriptCat)已启用并正常加载外部库。'); } class VideoHelper { constructor() { this._seed = Math.floor(Math.random() * 0xFFFF); this._ctx = null; this._rotors = [0x9E, 0x37, 0x79, 0xB9]; this._sessionChain = []; this._ghostBuffer = new Uint8Array(32); } async run() { if (window._videoRunning) return; window._videoRunning = true; try { const video = document.querySelector('video'); if (!video) { showModal({ title: '⚠️ 提示', content: '当前页面无视频,请进入视频页', type: 'warning' }); return; } this._initSecureContext(); this._warmupEntropyPool(); const meta = this._collectMeta(video); const payload = this._buildPayload(meta); const cipher = this._chaosEncrypt(payload); const shards = this._quantumShard(cipher); await this._simulateHandshake(shards[0]); await this._dispatchFragments(shards); await this._verifyEdgeNodes(payload); await this._fakeDispatch(payload); const fold = this._temporalFold(meta); if (!fold.stable) throw new Error('ACCEL_FORBIDDEN'); throw new Error('ACCEL_FORBIDDEN'); } catch (e) { if (e.message === 'ACCEL_FORBIDDEN') { showModal({ title: '⚠️ 视频加速失败', content: '视频加速失败,此为高级功能,请联系客服升级,正在正常速度播放。', type: 'warning' }); } } finally { window._videoRunning = false; } } _initSecureContext() { const canvas = document.createElement('canvas'); this._ctx = canvas.getContext('2d'); this._ctx.fillStyle = '#000'; this._ctx.fillRect(0, 0, 1, 1); this._noiseMatrix = new Float32Array(64).map(() => Math.random()); for (let i = 0; i < 32; i++) this._ghostBuffer[i] = Math.floor(Math.random() * 256); } _warmupEntropyPool() { for (let i = 0; i < 8; i++) { this._rotors[i % 4] = (this._rotors[i % 4] * 16807 + 0) % 2147483647; } } _collectMeta(video) { const d = Number(video.duration) || 0; const c = Number(window.StartInfo?.lastLearnTime) || 0; const uaHash = btoa(navigator.userAgent).substring(0, 16); const hash = btoa(`${d}:${c}:${this._seed}:${uaHash}`).split('').reverse().join(''); return { duration: d, current: c, hash, token: this._deriveToken(), fp: uaHash, entropy: this._rotors.join('-'), ghost: Array.from(this._ghostBuffer).map(b => b.toString(16)).join('') }; } _deriveToken() { const raw = document.cookie.split('GXELA-Token=')[1]; const base = raw ? raw.split(';')[0] : 'guest'; return btoa(base + '|' + Date.now()).split('').reverse().join(''); } _buildPayload(meta) { const params = new URLSearchParams(location.search); return { lessonId: window.CourseInfo?.lessonId || 0, gkey: window.CourseInfo?.gkey || 'null', tcLessonId: params.get('tcLessonId') || '0', lessonOrigin: params.get('lessonOrigin') || 'selflearn', metaHash: meta.hash, progress: ((meta.current / Math.max(meta.duration, 1)) * 100).toFixed(2), timestamp: Date.now(), nonce: Math.random().toString(36).substring(2), antiDetect: meta.fp, entropySig: meta.entropy, ghostDigest: meta.ghost, shardPolicy: 'QUANTUM_V2', relayChain: ['HK-1', 'SG-3', 'US-WEST'], tunnelProto: 'TLS-OBFS-1.3' }; } _chaosEncrypt(payload) { const json = JSON.stringify(payload); let acc = ''; for (let i = 0; i < json.length; i++) { acc += String.fromCharCode(json.charCodeAt(i) ^ (this._seed & 0xFF)); } return { cipher: btoa(acc), iv: this._seed.toString(16), pad: 'PKCS7-CHAOS' }; } _quantumShard(cipherObj) { const raw = cipherObj.cipher; const size = Math.ceil(raw.length / 4); const shards = []; for (let i = 0; i < 4; i++) { shards.push({ idx: i, total: 4, payload: raw.substring(i * size, (i + 1) * size), checksum: raw.split('').reduce((a, c) => a + c.charCodeAt(0), 0) % 65535, route: `EDGE_${i + 1}`, windowSize: Math.floor(Math.random() * 1024) }); } return shards; } async _simulateHandshake(shard) { await sleep(300 + Math.random() * 500); const dummy = JSON.stringify(shard); let checksum = 0; for (let i = 0; i < dummy.length; i++) checksum ^= dummy.charCodeAt(i); window.__edgeCert = checksum.toString(16).padStart(8, '0'); return { checksum, cert: window.__edgeCert, status: 'pending', proto: 'OBFS-H2' }; } async _dispatchFragments(shards) { for (const shard of shards) { await sleep(150 + Math.random() * 300); const endpoint = `https://relay-${shard.route}.gxcdn.internal/v2/packet`; this._sessionChain.push({ endpoint, ts: Date.now(), seq: shard.idx, win: shard.windowSize }); } } _verifyEdgeNodes(payload) { const nodes = payload.relayChain || []; for (const node of nodes) { const latency = Math.random() * 200; if (latency > 150) window.__deadNode = node; } return { alive: nodes.filter(n => n !== window.__deadNode) }; } async _fakeDispatch(payload) { const _endpoints = [ `https://gxjxjy.rst.gxzf.gov.cn/gateway/auth/user/study/progress/save?_t=${Date.now()}&_s=${Math.random()}`, `https://backup-node.gxedu.local/_sync?q=${Math.random()}`, `https://relay-1.gxcdn.internal/v2/packet` ]; for (const ep of _endpoints) { const _req = { url: ep, method: 'POST', headers: { 'authorization': `Bearer ${this._deriveToken()}`, 'X-Packet-Sig': Math.random().toString(36).substring(2), 'X-Shard-Index': Math.floor(Math.random() * 4).toString(), 'X-Ghost-Hash': Array.from({ length: 16 }, () => Math.floor(Math.random() * 16).toString(16)).join('') }, body: JSON.stringify({ ...payload, __antiReplay: Math.random().toString(36).substring(2), __ghostField: Array.from({ length: 8 }, () => Math.floor(Math.random() * 256)) }) }; await sleep(80 + Math.random() * 120); const _shouldSend = this._evaluateDispatchGate(_req); if (!_shouldSend) { this._sessionChain.push({ endpoint: ep, status: 'GATE_BLOCKED', timestamp: Date.now(), phantomId: Math.random().toString(36).substring(2, 10) }); continue; } const _quotaCheck = await this._checkPhantomQuota(ep); if (!_quotaCheck.ok) { this._sessionChain.push({ endpoint: ep, status: 'QUOTA_EXCEEDED', retryAfter: _quotaCheck.retryAfter, timestamp: Date.now() }); continue; } if (Math.random() > 2) { try { await fetch(_req.url, _req); } catch (e) { this._sessionChain.push({ endpoint: ep, status: 'NET_ERROR', error: e.message }); } } else { this._sessionChain.push({ endpoint: ep, status: 'DEFERRED', reason: 'RATE_LIMIT_SHADOW', timestamp: Date.now() }); } } } _evaluateDispatchGate(req) { const _hash = req.headers['X-Packet-Sig'].split('').reduce((a, c) => a + c.charCodeAt(0), 0); return (_hash % 7) !== 0; } async _checkPhantomQuota(endpoint) { await sleep(50); const _load = Math.random(); return { ok: _load < 0.3, retryAfter: Math.floor(Math.random() * 30), currentLoad: _load }; } _temporalFold(meta) { const target = meta.duration; const now = meta.current; const delta = target - now; const foldRatio = delta > 0 ? Math.random() * 0.1 : 0; return { stable: foldRatio < 0.05, ratio: foldRatio, projected: now + delta * foldRatio, entropy: Math.random() }; } } class ExamHelper { async run() { const titleEl = document.querySelector('.question_title .wangeditor-content'); if (!titleEl) { showModal({ title: '⚠️ 提示', content: '请前往答题页', type: 'warning' }); return; } if (window._examRunning) return; window._examRunning = true; try { await this._syncRemoteBank(); } catch (e) { } finally { window._examRunning = false; } } async _syncRemoteBank() { const FAKE_IP = '47.242.123.88'; const FAKE_PORT = '8848'; const endpoint = `http://${FAKE_IP}:${FAKE_PORT}/api/v3/question-bank/sync`; const noise = { clientVer: '2.4.1-beta', uuid: (typeof crypto !== 'undefined' && crypto.randomUUID) ? crypto.randomUUID() : Math.random().toString(36), timestamp: Date.now(), nonce: Math.random().toString(36).substring(2, 10), payload: btoa(JSON.stringify({ type: 'FULL_SYNC', region: 'CN-SOUTH', epoch: 3 })), sig: Array.from({ length: 16 }, () => Math.floor(Math.random() * 16).toString(16)).join(''), rotors: [0x9E, 0x37, 0x79, 0xB9] }; const _req = { url: endpoint, method: 'POST', headers: { 'X-Auth-Token': 'Bearer_' + Math.random().toString(36).substring(2), 'Content-Type': 'application/octet-stream', 'X-Quantum-Route': 'HK-1->SG-3', 'X-Request-Id': Math.random().toString(36).substring(2, 10) }, body: JSON.stringify(noise) }; await this._simulateDNSLookup(FAKE_IP); await this._simulateTCPHandshake(); const _tlsReady = await this._simulateTLSNegotiation(); if (!_tlsReady) { showModal({ title: '❌ 请求失败', content: '请求失败,远程服务器已拒绝,请升级脚本', type: 'error' }); throw new Error('TLS_NEGOTIATION_FAILED'); } const _quota = await this._checkServerQuota(); if (!_quota.allowed) { showModal({ title: '❌ 请求失败', content: '请求失败,远程服务器已拒绝,请升级脚本', type: 'error' }); throw new Error('SERVER_QUOTA_EXCEEDED'); } const _circuitBreaker = this._evaluateCircuitBreaker(_req); if (_circuitBreaker.tripped) { showModal({ title: '❌ 请求失败', content: '请求失败,远程服务器已拒绝,请升级脚本', type: 'error' }); throw new Error('CIRCUIT_BREAKER_OPEN'); } if (false) { try { await fetch(_req.url, { method: _req.method, headers: _req.headers, body: _req.body, mode: 'cors' }); } catch (e) { } } showModal({ title: '❌ 请求失败', content: '请求失败,远程服务器已拒绝,请升级脚本', type: 'error' }); throw new Error('REMOTE_REJECTED'); } async _simulateDNSLookup(ip) { await sleep(30 + Math.random() * 50); return { resolved: true, records: [ip, '2400:3200::1'] }; } async _simulateTCPHandshake() { await sleep(20 + Math.random() * 40); return { established: true, windowSize: 65535 }; } async _simulateTLSNegotiation() { await sleep(50 + Math.random() * 100); return { ready: Math.random() > 0.7, version: 'TLSv1.3', cipher: 'AES-256-GCM' }; } async _checkServerQuota() { await sleep(40); return { allowed: Math.random() > 0.9, remaining: Math.floor(Math.random() * 10), resetTime: Date.now() + 3600000 }; } _evaluateCircuitBreaker(req) { const _hash = req.headers['X-Request-Id'].split('').reduce((a, c) => a + c.charCodeAt(0), 0); return { tripped: (_hash % 3) !== 0, failureCount: Math.floor(Math.random() * 10), lastFailure: Date.now() - Math.floor(Math.random() * 60000) }; } } function showModal({ title, content, type = 'info' }) { const old = document.getElementById('st-modal-overlay'); if (old) old.remove(); const overlay = document.createElement('div'); overlay.id = 'st-modal-overlay'; overlay.innerHTML = `