完成扩展

This commit is contained in:
dela
2026-01-10 16:53:02 +08:00
parent 9eba656dbd
commit 97b162939e
31 changed files with 8436 additions and 0 deletions

View File

@@ -0,0 +1,456 @@
/**
* ============================================================================
* HCaptcha Bypass Module (Modularized Version)
* ============================================================================
* 功能:
* 1. 攔截 hCaptcha 的網絡請求 (Fetch & XHR)
* 2. 向 hCaptcha HTML 注入自動點擊腳本
* 3. 模擬用戶行為繞過檢測
* 4. 支援配置熱更新
*
* 使用方式:
* const bypass = new HCaptchaBypassModule(config);
* bypass.init();
* ============================================================================
*/
class HCaptchaBypassModule {
constructor(config = {}) {
// 默認配置
this.config = {
enabled: true, // 是否啟用繞過
autoClick: true, // 是否自動點擊
clickDelay: 400, // 點擊檢測間隔 (ms)
maxAttempts: 200, // 最大嘗試次數
debug: false, // 調試模式
settingsKey: '__HCAPTCHA_BYPASS_SETTINGS__', // 全局配置鍵名
...config
};
// 運行時狀態
this.isInterceptorLoaded = false;
this.isInjectorActive = false;
this.activeIntervals = [];
// 綁定方法上下文
this.checkSettings = this.checkSettings.bind(this);
}
/**
* 初始化模塊
*/
init() {
this.log('Initializing HCaptcha Bypass Module...');
// 1. 將配置暴露到全局 (供 iframe 內部讀取)
this.exposeSettings();
// 2. 啟動攔截器 (劫持網絡請求)
this.setupInterceptors();
// 3. 啟動配置熱更新
this.startSettingsWatcher();
// 4. 監聽跨域消息
this.setupMessageListener();
this.log('Module initialized successfully');
}
/**
* 銷毀模塊
*/
destroy() {
this.activeIntervals.forEach(id => clearInterval(id));
this.activeIntervals = [];
this.log('Module destroyed');
}
/**
* 暴露配置到全局
*/
exposeSettings() {
window[this.config.settingsKey] = {
autoCaptcha: this.config.autoClick,
enabled: this.config.enabled,
captchaService: 'hCaptcha'
};
// 同時嘗試暴露到父窗口
try {
if (window.parent && window.parent !== window) {
window.parent[this.config.settingsKey] = window[this.config.settingsKey];
}
} catch (e) {
// 跨域錯誤忽略
}
}
/**
* 配置熱更新監聽
*/
startSettingsWatcher() {
const intervalId = setInterval(this.checkSettings, 1000);
this.activeIntervals.push(intervalId);
}
checkSettings() {
try {
const settings = window[this.config.settingsKey];
if (settings) {
this.config.enabled = settings.enabled ?? this.config.enabled;
this.config.autoClick = settings.autoCaptcha ?? this.config.autoClick;
}
} catch (e) {
// Ignore
}
}
/**
* 跨域消息監聽
*/
setupMessageListener() {
window.addEventListener('message', (event) => {
if (event.data?.type === 'HCAPTCHA_BYPASS_UPDATE_SETTINGS') {
Object.assign(this.config, event.data.settings);
this.exposeSettings();
this.log('Settings updated via postMessage:', event.data.settings);
}
if (event.data?.msg === 'hCaptcha Injector Loaded') {
this.log('Injector script successfully loaded in iframe');
}
});
}
/**
* ========================================================================
* 攔截器部分:劫持網絡請求並注入腳本
* ========================================================================
*/
setupInterceptors() {
if (this.isInterceptorLoaded) {
this.log('Interceptor already loaded, skipping...');
return;
}
this.isInterceptorLoaded = true;
// 目標 URL 匹配
this.targetUrlPattern = /newassets\.hcaptcha\.com\/captcha\/v1\/[^/]+\/static\/hcaptcha\.html/;
// 需要替換的代碼模式
this.replacementPatterns = [
/this\.\$radio\.setAttribute\("aria-checked",\s*!1\)/g,
/this\.\$radio\.setAttribute\("aria-checked",\s*false\)/g,
/this\.\$radio\.setAttribute\("aria-checked",\s*0\)/g,
/setAttribute\("aria-checked",!1\)/g
];
// 注入的 Payload (自動點擊腳本)
this.injectedPayload = this.generateInjectorScript();
// Hook Fetch & XHR
this.hookFetch();
this.hookXHR();
this.log('Network interceptors installed');
}
/**
* 生成注入腳本
*/
generateInjectorScript() {
const config = this.config;
// 這裡用模板字符串生成完整的注入代碼
// 將之前的 injector 邏輯封裝成字符串
return `
(function() {
'use strict';
// ===== 配置讀取 =====
let isAutoClickEnabled = false;
let settingsKey = '${config.settingsKey}';
function initSettings() {
try {
if (window.parent && window.parent[settingsKey]) {
isAutoClickEnabled = window.parent[settingsKey].autoCaptcha || false;
} else if (window.top && window.top[settingsKey]) {
isAutoClickEnabled = window.top[settingsKey].autoCaptcha || false;
}
window.addEventListener('message', (event) => {
if (event.data?.type === 'HCAPTCHA_BYPASS_UPDATE_SETTINGS') {
isAutoClickEnabled = event.data.settings?.autoClick || false;
}
});
} catch (err) {
isAutoClickEnabled = true; // 跨域限制時默認啟用
}
}
initSettings();
// ===== 核心點擊邏輯 =====
const CHECKBOX_SELECTOR = '#checkbox';
let attemptCount = 0;
let isSolved = false;
let clickInterval = null;
function attemptClick() {
if (attemptCount >= ${config.maxAttempts} || isSolved) {
if (clickInterval) clearInterval(clickInterval);
return;
}
const checkbox = document.querySelector(CHECKBOX_SELECTOR);
if (!checkbox) {
attemptCount++;
return;
}
const isChecked = checkbox.getAttribute('aria-checked');
const isVisible = checkbox.offsetParent !== null;
if (isVisible && isChecked === 'false' && isAutoClickEnabled) {
try {
checkbox.click();
console.log('[HCaptcha Bypass] Checkbox clicked');
setTimeout(() => {
const newState = checkbox.getAttribute('aria-checked');
if (newState === 'true') {
isSolved = true;
if (clickInterval) clearInterval(clickInterval);
// 通知父窗口
window.parent.postMessage({
type: 'HCAPTCHA_BYPASS_SOLVED',
msg: 'hCaptcha solved successfully'
}, '*');
}
}, 1000);
} catch (e) {
console.error('[HCaptcha Bypass] Click failed:', e);
}
}
attemptCount++;
}
// 啟動點擊循環
clickInterval = setInterval(attemptClick, ${config.clickDelay});
// 冗餘觸發
setTimeout(attemptClick, 500);
setTimeout(attemptClick, 1500);
setTimeout(attemptClick, 3000);
// 通知父窗口注入成功
setTimeout(() => {
window.parent.postMessage({
type: 'HCAPTCHA_BYPASS_INJECTOR_LOADED',
msg: 'hCaptcha Injector Loaded'
}, '*');
}, 2000);
})();
`;
}
/**
* Hook Fetch API
*/
hookFetch() {
const originalFetch = window.fetch;
const self = this;
window.fetch = function(...args) {
const url = typeof args[0] === 'string' ? args[0] : args[0]?.url;
// 檢查是否為目標 URL
const isTarget = url && self.targetUrlPattern.test(url);
if (!isTarget || !self.config.enabled) {
return originalFetch.apply(this, args);
}
self.log('Fetch intercepted:', url);
// 攔截並修改響應
return originalFetch.apply(this, args).then(response => {
return response.text().then(html => {
const modifiedHtml = self.injectScript(html);
return new Response(modifiedHtml, {
status: response.status,
statusText: response.statusText,
headers: response.headers
});
});
});
};
}
/**
* Hook XMLHttpRequest
*/
hookXHR() {
const originalOpen = XMLHttpRequest.prototype.open;
const originalSend = XMLHttpRequest.prototype.send;
const self = this;
XMLHttpRequest.prototype.open = function(method, url, ...rest) {
this._interceptedUrl = url;
return originalOpen.apply(this, [method, url, ...rest]);
};
XMLHttpRequest.prototype.send = function(...args) {
const url = this._interceptedUrl;
const isTarget = url && self.targetUrlPattern.test(url);
if (!isTarget || !self.config.enabled) {
return originalSend.apply(this, args);
}
self.log('XHR intercepted:', url);
const originalOnReadyStateChange = this.onreadystatechange;
this.onreadystatechange = function() {
if (this.readyState === 4 && this.status === 200) {
let html = this.responseText;
if (html) {
html = self.injectScript(html);
Object.defineProperty(this, 'responseText', {
get: () => html,
configurable: true
});
Object.defineProperty(this, 'response', {
get: () => html,
configurable: true
});
}
}
if (originalOnReadyStateChange) {
originalOnReadyStateChange.apply(this, arguments);
}
};
return originalSend.apply(this, args);
};
}
/**
* 注入腳本到 HTML
*/
injectScript(html) {
let modified = html;
// 1. 替換檢測邏輯 (將 false 改為 true)
this.replacementPatterns.forEach(pattern => {
modified = modified.replace(pattern, match => {
return match.replace(/!1|false|0/g, '!0'); // !0 === true
});
});
// 2. 注入自動點擊腳本
const scriptTag = `<script>${this.injectedPayload}</script>`;
if (modified.includes('</body>')) {
modified = modified.replace('</body>', scriptTag + '</body>');
} else if (modified.includes('</html>')) {
modified = modified.replace('</html>', scriptTag + '</html>');
} else {
modified += scriptTag;
}
this.log('Script injected into hCaptcha HTML');
return modified;
}
/**
* 日誌輸出
*/
log(...args) {
if (this.config.debug) {
console.log('[HCaptcha Bypass Module]', ...args);
}
}
/**
* 更新配置
*/
updateConfig(newConfig) {
Object.assign(this.config, newConfig);
this.exposeSettings();
this.log('Config updated:', this.config);
}
/**
* 手動觸發點擊 (從外部調用)
*/
triggerClick() {
const iframes = document.querySelectorAll('iframe[src*="hcaptcha.com"]');
iframes.forEach(iframe => {
try {
iframe.contentWindow.postMessage({
type: 'HCAPTCHA_BYPASS_TRIGGER_CLICK'
}, '*');
} catch (e) {
this.log('Cannot access iframe:', e);
}
});
}
}
/**
* ============================================================================
* 全局 API 暴露
* ============================================================================
*/
window.HCaptchaBypassModule = HCaptchaBypassModule;
// 自動初始化選項
if (typeof HCAPTCHA_BYPASS_AUTO_INIT !== 'undefined' && HCAPTCHA_BYPASS_AUTO_INIT) {
const instance = new HCaptchaBypassModule({
enabled: true,
autoClick: true,
debug: true
});
instance.init();
window.__hcaptchaBypass = instance;
}
// ============================================================================
// Extension Compatibility Wrapper
// ============================================================================
window.addEventListener('message', (event) => {
if (event.source !== window) return;
const message = event.data;
if (message && message.type === 'INIT_MODULE' && message.moduleName === 'hcaptchaBypass') {
if (window.__hcaptchaBypassInstance) return;
try {
const instance = new HCaptchaBypassModule(message.config);
instance.init();
window.__hcaptchaBypassInstance = instance;
console.log('[Extension] HCaptcha Bypass initialized');
} catch (error) {
console.error('[Extension] HCaptcha Bypass init failed:', error);
}
}
if (message && message.type === 'DESTROY_MODULE' && message.instanceKey === '__hcaptchaBypassInstance') {
const instance = window.__hcaptchaBypassInstance;
if (instance && typeof instance.destroy === 'function') {
instance.destroy();
delete window.__hcaptchaBypassInstance;
}
}
});