944 lines
38 KiB
JavaScript
944 lines
38 KiB
JavaScript
// =============================================================================
|
|
// MAXIMUM STEALTH SCRIPT — инжектируется в MAIN world на каждой странице
|
|
// Подменяет ВСЕ известные маркеры автоматизации + добавляет поведенческую эмуляцию
|
|
// =============================================================================
|
|
|
|
(function() {
|
|
'use strict';
|
|
|
|
console.log('[STEALTH] Maximum stealth mode activated');
|
|
|
|
// -------------------------------------------------------------------------
|
|
// 1. navigator.webdriver = false (базовая защита)
|
|
// -------------------------------------------------------------------------
|
|
try {
|
|
Object.defineProperty(navigator, 'webdriver', {
|
|
get: () => false,
|
|
configurable: true,
|
|
});
|
|
const proto = Object.getPrototypeOf(navigator);
|
|
if (proto) {
|
|
Object.defineProperty(proto, 'webdriver', {
|
|
get: () => false,
|
|
configurable: true,
|
|
});
|
|
}
|
|
} catch (e) {}
|
|
|
|
// -------------------------------------------------------------------------
|
|
// 2. navigator.plugins — эмулируем стандартные плагины Chrome
|
|
// -------------------------------------------------------------------------
|
|
try {
|
|
const makeMimeType = (type, suffixes, description, plugin) => {
|
|
const mt = Object.create(MimeType.prototype);
|
|
Object.defineProperties(mt, {
|
|
type: { get: () => type },
|
|
suffixes: { get: () => suffixes },
|
|
description: { get: () => description },
|
|
enabledPlugin: { get: () => plugin },
|
|
});
|
|
return mt;
|
|
};
|
|
|
|
const makePlugin = (name, description, filename, mimeTypes) => {
|
|
const p = Object.create(Plugin.prototype);
|
|
const mimes = [];
|
|
Object.defineProperties(p, {
|
|
name: { get: () => name },
|
|
description: { get: () => description },
|
|
filename: { get: () => filename },
|
|
length: { get: () => mimes.length },
|
|
});
|
|
mimeTypes.forEach((mt, i) => {
|
|
const mime = makeMimeType(mt.type, mt.suffixes, mt.description, p);
|
|
mimes.push(mime);
|
|
Object.defineProperty(p, i, { get: () => mime });
|
|
Object.defineProperty(p, mt.type, { get: () => mime });
|
|
});
|
|
return p;
|
|
};
|
|
|
|
const pluginData = [
|
|
{
|
|
name: 'Chrome PDF Plugin',
|
|
description: 'Portable Document Format',
|
|
filename: 'internal-pdf-viewer',
|
|
mimeTypes: [
|
|
{ type: 'application/x-google-chrome-pdf', suffixes: 'pdf', description: 'Portable Document Format' },
|
|
],
|
|
},
|
|
{
|
|
name: 'Chrome PDF Viewer',
|
|
description: '',
|
|
filename: 'mhjfbmdgcfjbbpaeojofohoefgiehjai',
|
|
mimeTypes: [
|
|
{ type: 'application/pdf', suffixes: 'pdf', description: '' },
|
|
],
|
|
},
|
|
{
|
|
name: 'Native Client',
|
|
description: '',
|
|
filename: 'internal-nacl-plugin',
|
|
mimeTypes: [
|
|
{ type: 'application/x-nacl', suffixes: '', description: 'Native Client Executable' },
|
|
{ type: 'application/x-pnacl', suffixes: '', description: 'Portable Native Client Executable' },
|
|
],
|
|
},
|
|
];
|
|
|
|
const plugins = pluginData.map(pd =>
|
|
makePlugin(pd.name, pd.description, pd.filename, pd.mimeTypes)
|
|
);
|
|
|
|
const pluginArray = Object.create(PluginArray.prototype);
|
|
Object.defineProperty(pluginArray, 'length', { get: () => plugins.length });
|
|
plugins.forEach((p, i) => {
|
|
Object.defineProperty(pluginArray, i, { get: () => p });
|
|
Object.defineProperty(pluginArray, p.name, { get: () => p });
|
|
});
|
|
Object.defineProperty(pluginArray, 'refresh', { value: () => {} });
|
|
Object.defineProperty(pluginArray, 'item', { value: (index) => plugins[index] || null });
|
|
Object.defineProperty(pluginArray, 'namedItem', { value: (name) => plugins.find(p => p.name === name) || null });
|
|
Object.defineProperty(pluginArray, Symbol.iterator, { value: function* () { for (const p of plugins) yield p; } });
|
|
|
|
Object.defineProperty(navigator, 'plugins', { get: () => pluginArray, configurable: true });
|
|
} catch (e) {}
|
|
|
|
// -------------------------------------------------------------------------
|
|
// 3. navigator.mimeTypes
|
|
// -------------------------------------------------------------------------
|
|
try {
|
|
const mimeData = [
|
|
{ type: 'application/pdf', suffixes: 'pdf', description: '' },
|
|
{ type: 'application/x-google-chrome-pdf', suffixes: 'pdf', description: 'Portable Document Format' },
|
|
{ type: 'application/x-nacl', suffixes: '', description: 'Native Client Executable' },
|
|
{ type: 'application/x-pnacl', suffixes: '', description: 'Portable Native Client Executable' },
|
|
];
|
|
|
|
const mimeTypeArray = Object.create(MimeTypeArray.prototype);
|
|
const mimes = mimeData.map(md => {
|
|
const mt = Object.create(MimeType.prototype);
|
|
Object.defineProperties(mt, {
|
|
type: { get: () => md.type },
|
|
suffixes: { get: () => md.suffixes },
|
|
description: { get: () => md.description },
|
|
enabledPlugin: { get: () => navigator.plugins[0] },
|
|
});
|
|
return mt;
|
|
});
|
|
|
|
Object.defineProperty(mimeTypeArray, 'length', { get: () => mimes.length });
|
|
mimes.forEach((m, i) => {
|
|
Object.defineProperty(mimeTypeArray, i, { get: () => m });
|
|
Object.defineProperty(mimeTypeArray, m.type, { get: () => m });
|
|
});
|
|
Object.defineProperty(mimeTypeArray, 'item', { value: (index) => mimes[index] || null });
|
|
Object.defineProperty(mimeTypeArray, 'namedItem', { value: (name) => mimes.find(m => m.type === name) || null });
|
|
Object.defineProperty(mimeTypeArray, Symbol.iterator, { value: function* () { for (const m of mimes) yield m; } });
|
|
|
|
Object.defineProperty(navigator, 'mimeTypes', { get: () => mimeTypeArray, configurable: true });
|
|
} catch (e) {}
|
|
|
|
// -------------------------------------------------------------------------
|
|
// 4. navigator.languages — рандомизированные значения
|
|
// -------------------------------------------------------------------------
|
|
try {
|
|
const languages = ['ru-RU', 'ru', 'en-US', 'en'];
|
|
Object.defineProperty(navigator, 'languages', { get: () => languages, configurable: true });
|
|
Object.defineProperty(navigator, 'language', { get: () => 'ru-RU', configurable: true });
|
|
Object.defineProperty(navigator, 'preferredLanguages', { get: () => languages, configurable: true });
|
|
} catch (e) {}
|
|
|
|
// -------------------------------------------------------------------------
|
|
// 5. navigator.pdfViewerEnabled
|
|
// -------------------------------------------------------------------------
|
|
try {
|
|
Object.defineProperty(navigator, 'pdfViewerEnabled', { get: () => true, configurable: true });
|
|
} catch (e) {}
|
|
|
|
// -------------------------------------------------------------------------
|
|
// 6. window.chrome — полная эмуляция
|
|
// -------------------------------------------------------------------------
|
|
try {
|
|
if (!window.chrome) window.chrome = {};
|
|
if (!window.chrome.runtime) {
|
|
window.chrome.runtime = {
|
|
connect: function() { return { onMessage: { addListener: function() {} }, postMessage: function() {}, onDisconnect: { addListener: function() {} } }; },
|
|
sendMessage: function() {},
|
|
onMessage: { addListener: function() {}, removeListener: function() {} },
|
|
onConnect: { addListener: function() {}, removeListener: function() {} },
|
|
id: undefined,
|
|
};
|
|
}
|
|
if (!window.chrome.app) {
|
|
window.chrome.app = {
|
|
isInstalled: false,
|
|
InstallState: { DISABLED: 'disabled', INSTALLED: 'installed', NOT_INSTALLED: 'not_installed' },
|
|
RunningState: { CANNOT_RUN: 'cannot_run', READY_TO_RUN: 'ready_to_run', RUNNING: 'running' },
|
|
getDetails: function() { return null; },
|
|
getIsInstalled: function() { return false; },
|
|
runningState: function() { return 'cannot_run'; },
|
|
};
|
|
}
|
|
if (!window.chrome.csi) {
|
|
window.chrome.csi = function() {
|
|
return { startE: Date.now(), onloadT: Date.now(), pageT: Math.random() * 1000 + 500, tran: 15 };
|
|
};
|
|
}
|
|
if (!window.chrome.loadTimes) {
|
|
window.chrome.loadTimes = function() {
|
|
return {
|
|
commitLoadTime: Date.now() / 1000,
|
|
connectionInfo: 'h2',
|
|
finishDocumentLoadTime: Date.now() / 1000,
|
|
finishLoadTime: Date.now() / 1000,
|
|
firstPaintAfterLoadTime: 0,
|
|
firstPaintTime: Date.now() / 1000,
|
|
navigationType: 'Other',
|
|
npnNegotiatedProtocol: 'h2',
|
|
requestTime: Date.now() / 1000 - 0.16,
|
|
startLoadTime: Date.now() / 1000 - 0.16,
|
|
wasAlternateProtocolAvailable: false,
|
|
wasFetchedViaSpdy: true,
|
|
wasNpnNegotiated: true,
|
|
};
|
|
};
|
|
}
|
|
if (!window.chrome.webstore) {
|
|
window.chrome.webstore = {
|
|
onInstallStageChanged: { addListener: function() {} },
|
|
onDownloadProgress: { addListener: function() {} },
|
|
};
|
|
}
|
|
if (!window.chrome.storage) {
|
|
window.chrome.storage = {
|
|
local: { get: function() { return Promise.resolve({}); }, set: function() { return Promise.resolve(); } },
|
|
sync: { get: function() { return Promise.resolve({}); }, set: function() { return Promise.resolve(); } },
|
|
};
|
|
}
|
|
} catch (e) {}
|
|
|
|
// -------------------------------------------------------------------------
|
|
// 7. Permissions.query
|
|
// -------------------------------------------------------------------------
|
|
try {
|
|
const originalQuery = window.Permissions.prototype.query;
|
|
window.Permissions.prototype.query = function(parameters) {
|
|
if (parameters.name === 'notifications') {
|
|
return Promise.resolve({ state: Notification.permission });
|
|
}
|
|
return originalQuery.call(this, parameters);
|
|
};
|
|
} catch (e) {}
|
|
|
|
// -------------------------------------------------------------------------
|
|
// 8. navigator.connection
|
|
// -------------------------------------------------------------------------
|
|
try {
|
|
if (!navigator.connection) {
|
|
Object.defineProperty(navigator, 'connection', {
|
|
get: () => ({
|
|
effectiveType: '4g',
|
|
rtt: 50,
|
|
downlink: 10,
|
|
saveData: false,
|
|
onchange: null,
|
|
addEventListener: function() {},
|
|
removeEventListener: function() {},
|
|
dispatchEvent: function() { return true; },
|
|
}),
|
|
configurable: true,
|
|
});
|
|
}
|
|
} catch (e) {}
|
|
|
|
// -------------------------------------------------------------------------
|
|
// 9. navigator.hardwareConcurrency
|
|
// -------------------------------------------------------------------------
|
|
try {
|
|
Object.defineProperty(navigator, 'hardwareConcurrency', { get: () => 8, configurable: true });
|
|
} catch (e) {}
|
|
|
|
// -------------------------------------------------------------------------
|
|
// 10. navigator.deviceMemory
|
|
// -------------------------------------------------------------------------
|
|
try {
|
|
Object.defineProperty(navigator, 'deviceMemory', { get: () => 8, configurable: true });
|
|
} catch (e) {}
|
|
|
|
// -------------------------------------------------------------------------
|
|
// 11. navigator.maxTouchPoints
|
|
// -------------------------------------------------------------------------
|
|
try {
|
|
Object.defineProperty(navigator, 'maxTouchPoints', { get: () => 0, configurable: true });
|
|
} catch (e) {}
|
|
|
|
// -------------------------------------------------------------------------
|
|
// 12. navigator.platform
|
|
// -------------------------------------------------------------------------
|
|
try {
|
|
Object.defineProperty(navigator, 'platform', { get: () => 'Win32', configurable: true });
|
|
} catch (e) {}
|
|
|
|
// -------------------------------------------------------------------------
|
|
// 13. navigator.vendor
|
|
// -------------------------------------------------------------------------
|
|
try {
|
|
Object.defineProperty(navigator, 'vendor', { get: () => 'Google Inc.', configurable: true });
|
|
} catch (e) {}
|
|
|
|
// -------------------------------------------------------------------------
|
|
// 14. navigator.appVersion
|
|
// -------------------------------------------------------------------------
|
|
try {
|
|
Object.defineProperty(navigator, 'appVersion', {
|
|
get: () => '5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36',
|
|
configurable: true,
|
|
});
|
|
} catch (e) {}
|
|
|
|
// -------------------------------------------------------------------------
|
|
// 15. navigator.userAgent
|
|
// -------------------------------------------------------------------------
|
|
try {
|
|
Object.defineProperty(navigator, 'userAgent', {
|
|
get: () => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36',
|
|
configurable: true,
|
|
});
|
|
} catch (e) {}
|
|
|
|
// -------------------------------------------------------------------------
|
|
// 16. WebGL — подменяем vendor и renderer (РАНДОМИЗИРОВАННЫЕ)
|
|
// -------------------------------------------------------------------------
|
|
try {
|
|
// Рандомизированные значения для WebGL
|
|
const webglVendors = ['Google Inc. (NVIDIA)', 'Google Inc. (Intel)', 'Google Inc. (AMD)', 'Intel Inc.', 'Apple Inc.'];
|
|
const webglRenderers = [
|
|
'ANGLE (NVIDIA, NVIDIA GeForce GTX 1660 SUPER Direct3D11 vs_5_0 ps_5_0, D3D11)',
|
|
'ANGLE (Intel, Intel(R) UHD Graphics Direct3D11 vs_5_0 ps_5_0, D3D11)',
|
|
'ANGLE (AMD, Radeon RX 580 Direct3D11 vs_5_0 ps_5_0, D3D11)',
|
|
'Intel Iris OpenGL Engine',
|
|
'Apple M1',
|
|
];
|
|
|
|
const randomVendor = webglVendors[Math.floor(Math.random() * webglVendors.length)];
|
|
const randomRenderer = webglRenderers[Math.floor(Math.random() * webglRenderers.length)];
|
|
|
|
const getParameterOrig = WebGLRenderingContext.prototype.getParameter;
|
|
WebGLRenderingContext.prototype.getParameter = function(param) {
|
|
if (param === 0x9245) return randomVendor;
|
|
if (param === 0x9246) return randomRenderer;
|
|
return getParameterOrig.call(this, param);
|
|
};
|
|
|
|
const getParameter2Orig = WebGL2RenderingContext.prototype.getParameter;
|
|
WebGL2RenderingContext.prototype.getParameter = function(param) {
|
|
if (param === 0x9245) return randomVendor;
|
|
if (param === 0x9246) return randomRenderer;
|
|
return getParameter2Orig.call(this, param);
|
|
};
|
|
} catch (e) {}
|
|
|
|
// -------------------------------------------------------------------------
|
|
// 17. Скрываем CDP и automation следы
|
|
// -------------------------------------------------------------------------
|
|
try {
|
|
delete window.__playwright_target__;
|
|
delete window.__playwright_evaluation_script__;
|
|
|
|
for (const key of Object.keys(window)) {
|
|
if (key.match(/^cdc_/) || key.match(/^__cdc_/) || key.match(/^__selenium_/) || key.match(/^__webdriver_/)) {
|
|
try { delete window[key]; } catch (e) {}
|
|
}
|
|
}
|
|
|
|
for (const key of Object.keys(document)) {
|
|
if (key.match(/^\$cdc_/) || key.match(/^cdc_/)) {
|
|
try { delete document[key]; } catch (e) {}
|
|
}
|
|
}
|
|
} catch (e) {}
|
|
|
|
// -------------------------------------------------------------------------
|
|
// 18. Headless маркеры
|
|
// -------------------------------------------------------------------------
|
|
try {
|
|
if (window.outerWidth === 0) {
|
|
Object.defineProperty(window, 'outerWidth', { get: () => 1920 });
|
|
}
|
|
if (window.outerHeight === 0) {
|
|
Object.defineProperty(window, 'outerHeight', { get: () => 1080 });
|
|
}
|
|
if (screen.width === 0 || screen.width < 800) {
|
|
Object.defineProperty(screen, 'width', { get: () => 1920 });
|
|
Object.defineProperty(screen, 'height', { get: () => 1080 });
|
|
Object.defineProperty(screen, 'availWidth', { get: () => 1920 });
|
|
Object.defineProperty(screen, 'availHeight', { get: () => 1040 });
|
|
Object.defineProperty(screen, 'colorDepth', { get: () => 24 });
|
|
Object.defineProperty(screen, 'pixelDepth', { get: () => 24 });
|
|
}
|
|
// Добавляем screen.orientation для modern detection
|
|
if (screen.orientation) {
|
|
Object.defineProperty(screen.orientation, 'type', { get: () => 'landscape-primary', configurable: true });
|
|
Object.defineProperty(screen.orientation, 'angle', { get: () => 0, configurable: true });
|
|
}
|
|
} catch (e) {}
|
|
|
|
// -------------------------------------------------------------------------
|
|
// 19. Notification.permission
|
|
// -------------------------------------------------------------------------
|
|
try {
|
|
if (Notification.permission === 'denied') {
|
|
Object.defineProperty(Notification, 'permission', { get: () => 'default', configurable: true });
|
|
}
|
|
} catch (e) {}
|
|
|
|
// -------------------------------------------------------------------------
|
|
// 20. navigator.userAgentData
|
|
// -------------------------------------------------------------------------
|
|
try {
|
|
if (navigator.userAgentData) {
|
|
Object.defineProperty(navigator, 'userAgentData', {
|
|
get: () => ({
|
|
brands: [
|
|
{ brand: 'Google Chrome', version: '131' },
|
|
{ brand: 'Chromium', version: '131' },
|
|
{ brand: 'Not_A Brand', version: '24' },
|
|
],
|
|
mobile: false,
|
|
platform: 'Windows',
|
|
getHighEntropyValues: function(hints) {
|
|
return Promise.resolve({
|
|
architecture: 'x86',
|
|
bitness: '64',
|
|
brands: [
|
|
{ brand: 'Google Chrome', version: '131' },
|
|
{ brand: 'Chromium', version: '131' },
|
|
{ brand: 'Not_A Brand', version: '24' },
|
|
],
|
|
fullVersionList: [
|
|
{ brand: 'Google Chrome', version: '131.0.6778.86' },
|
|
{ brand: 'Chromium', version: '131.0.6778.86' },
|
|
{ brand: 'Not_A Brand', version: '24.0.0.0' },
|
|
],
|
|
mobile: false,
|
|
model: '',
|
|
platform: 'Windows',
|
|
platformVersion: '15.0.0',
|
|
uaFullVersion: '131.0.6778.86',
|
|
wow64: false,
|
|
});
|
|
},
|
|
toJSON: function() {
|
|
return { brands: this.brands, mobile: this.mobile, platform: this.platform };
|
|
},
|
|
}),
|
|
configurable: true,
|
|
});
|
|
}
|
|
} catch (e) {}
|
|
|
|
// -------------------------------------------------------------------------
|
|
// 21. Удаляем automation-specific объекты
|
|
// -------------------------------------------------------------------------
|
|
try {
|
|
delete window.domAutomation;
|
|
delete window.domAutomationController;
|
|
delete window._phantom;
|
|
delete window.__nightmare;
|
|
delete window._selenium;
|
|
delete window.callPhantom;
|
|
delete window.callSelenium;
|
|
delete window._Recaptcha;
|
|
} catch (e) {}
|
|
|
|
// -------------------------------------------------------------------------
|
|
// 22. Battery API
|
|
// -------------------------------------------------------------------------
|
|
try {
|
|
if (navigator.getBattery) {
|
|
navigator.getBattery = function() {
|
|
return Promise.resolve({
|
|
charging: true,
|
|
chargingTime: 0,
|
|
dischargingTime: Infinity,
|
|
level: 1.0,
|
|
onchargingchange: null,
|
|
onchargingtimechange: null,
|
|
ondischargingtimechange: null,
|
|
onlevelchange: null,
|
|
addEventListener: function() {},
|
|
removeEventListener: function() {},
|
|
dispatchEvent: function() { return true; },
|
|
});
|
|
};
|
|
}
|
|
} catch (e) {}
|
|
|
|
// -------------------------------------------------------------------------
|
|
// 23. AudioContext
|
|
// -------------------------------------------------------------------------
|
|
try {
|
|
const OriginalAudioContext = window.AudioContext || window.webkitAudioContext;
|
|
if (OriginalAudioContext && OriginalAudioContext.prototype && OriginalAudioContext.prototype.resume) {
|
|
const originalResume = OriginalAudioContext.prototype.resume;
|
|
OriginalAudioContext.prototype.resume = function() {
|
|
try {
|
|
if (this.state === 'suspended') {
|
|
return originalResume.call(this).catch(function() {});
|
|
}
|
|
return Promise.resolve();
|
|
} catch(e) {
|
|
return Promise.resolve();
|
|
}
|
|
};
|
|
}
|
|
} catch (e) {}
|
|
|
|
// -------------------------------------------------------------------------
|
|
// 24. Canvas - добавляем шум (НОВЫЙ)
|
|
// -------------------------------------------------------------------------
|
|
try {
|
|
const originalGetImageData = CanvasRenderingContext2D.prototype.getImageData;
|
|
CanvasRenderingContext2D.prototype.getImageData = function() {
|
|
// Добавляем микроскопический шум к пикселям
|
|
try {
|
|
const imageData = originalGetImageData.apply(this, arguments);
|
|
if (imageData && imageData.data) {
|
|
// Добавляем tiny noise к некоторым пикселям
|
|
for (let i = 0; i < imageData.data.length; i += 4) {
|
|
if (Math.random() < 0.001) {
|
|
imageData.data[i] = imageData.data[i] + (Math.random() - 0.5) * 2;
|
|
imageData.data[i + 1] = imageData.data[i + 1] + (Math.random() - 0.5) * 2;
|
|
imageData.data[i + 2] = imageData.data[i + 2] + (Math.random() - 0.5) * 2;
|
|
}
|
|
}
|
|
}
|
|
return imageData;
|
|
} catch(e) {
|
|
return originalGetImageData.apply(this, arguments);
|
|
}
|
|
};
|
|
} catch (e) {}
|
|
|
|
// -------------------------------------------------------------------------
|
|
// 25. Intl.DateTimeFormat - рандомизация timezone (НОВЫЙ)
|
|
// -------------------------------------------------------------------------
|
|
try {
|
|
const originalDateTimeFormat = Intl.DateTimeFormat;
|
|
Intl.DateTimeFormat = function(...args) {
|
|
return new originalDateTimeFormat(...args);
|
|
};
|
|
Intl.DateTimeFormat.prototype = originalDateTimeFormat.prototype;
|
|
|
|
// Добавляем свойства timezone
|
|
if (!Intl.DateTimeFormat.prototype.resolvedOptions) {
|
|
Object.defineProperty(Intl.DateTimeFormat.prototype, 'resolvedOptions', {
|
|
value: function() {
|
|
return {
|
|
locale: 'ru-RU',
|
|
calendar: 'gregory',
|
|
numberingSystem: 'latn',
|
|
timeZone: 'Europe/Moscow',
|
|
};
|
|
},
|
|
});
|
|
}
|
|
} catch (e) {}
|
|
|
|
// -------------------------------------------------------------------------
|
|
// 26. navigator.geolocation (НОВЫЙ)
|
|
// -------------------------------------------------------------------------
|
|
try {
|
|
if (navigator.geolocation) {
|
|
const originalGetCurrentPosition = navigator.geolocation.getCurrentPosition;
|
|
navigator.geolocation.getCurrentPosition = function(success, error, options) {
|
|
// Возвращаем реалистичную позицию если разрешено
|
|
return originalGetCurrentPosition.call(this, success, error, options);
|
|
};
|
|
}
|
|
} catch (e) {}
|
|
|
|
// -------------------------------------------------------------------------
|
|
// 27. Performance API (НОВЫЙ)
|
|
// -------------------------------------------------------------------------
|
|
try {
|
|
if (window.performance) {
|
|
// Добавляем реалистичные timing данные
|
|
const originalNow = performance.now;
|
|
let offset = 0;
|
|
Object.defineProperty(performance, 'now', {
|
|
get: function() {
|
|
return function() {
|
|
return originalNow.call(performance) + offset;
|
|
};
|
|
}(),
|
|
configurable: true,
|
|
});
|
|
}
|
|
} catch (e) {}
|
|
|
|
// -------------------------------------------------------------------------
|
|
// 28. PointerEvent (НОВЫЙ)
|
|
// -------------------------------------------------------------------------
|
|
try {
|
|
// Добавляем поддержку pointer events для более реалистичного поведения
|
|
if (window.PointerEvent) {
|
|
// Убеждаемся что pointer events работают нормально
|
|
}
|
|
} catch (e) {}
|
|
|
|
// -------------------------------------------------------------------------
|
|
// 29. CSS.supports (НОВЫЙ)
|
|
// -------------------------------------------------------------------------
|
|
try {
|
|
const originalCSSSupports = CSS.supports;
|
|
CSS.supports = function(...args) {
|
|
try {
|
|
return originalCSSSupports.apply(this, args);
|
|
} catch(e) {
|
|
return false;
|
|
}
|
|
};
|
|
} catch (e) {}
|
|
|
|
// -------------------------------------------------------------------------
|
|
// 30. Date/getTimezoneOffset (НОВЫЙ)
|
|
// -------------------------------------------------------------------------
|
|
try {
|
|
const originalGetTimezoneOffset = Date.prototype.getTimezoneOffset;
|
|
Object.defineProperty(Date.prototype, 'getTimezoneOffset', {
|
|
value: function() {
|
|
// Moscow timezone is UTC+3, so offset is -180 minutes
|
|
return -180;
|
|
},
|
|
configurable: true,
|
|
});
|
|
} catch (e) {}
|
|
|
|
// -------------------------------------------------------------------------
|
|
// 31. Screen orientation API (НОВЫЙ)
|
|
// -------------------------------------------------------------------------
|
|
try {
|
|
if (screen.orientation) {
|
|
Object.defineProperty(screen.orientation, 'type', { get: () => 'landscape-primary', configurable: true });
|
|
Object.defineProperty(screen.orientation, 'angle', { get: () => 0, configurable: true });
|
|
|
|
const originalLock = screen.orientation.lock.bind(screen.orientation);
|
|
screen.orientation.lock = function(type) {
|
|
return Promise.resolve();
|
|
};
|
|
|
|
screen.orientation.unlock = function() {};
|
|
}
|
|
} catch (e) {}
|
|
|
|
// -------------------------------------------------------------------------
|
|
// 32. VisualViewport (НОВЫЙ)
|
|
// -------------------------------------------------------------------------
|
|
try {
|
|
if (window.visualViewport) {
|
|
Object.defineProperty(window.visualViewport, 'width', { get: () => 1920, configurable: true });
|
|
Object.defineProperty(window.visualViewport, 'height', { get: () => 1080 - 100, configurable: true });
|
|
Object.defineProperty(window.visualViewport, 'scale', { get: () => 1, configurable: true });
|
|
Object.defineProperty(window.visualViewport, 'offsetLeft', { get: () => 0, configurable: true });
|
|
Object.defineProperty(window.visualViewport, 'offsetTop', { get: () => 0, configurable: true });
|
|
}
|
|
} catch (e) {}
|
|
|
|
// -------------------------------------------------------------------------
|
|
// 33. NavigatorUAData (НОВЫЙ) - дополнительная защита
|
|
// -------------------------------------------------------------------------
|
|
try {
|
|
if (Navigator.prototype.userAgentData) {
|
|
// Убеждаемся что все свойства присутствуют
|
|
}
|
|
} catch (e) {}
|
|
|
|
// -------------------------------------------------------------------------
|
|
// 34. Connection API (НОВЫЙ)
|
|
// -------------------------------------------------------------------------
|
|
try {
|
|
if (navigator.connection && navigator.connection.saveData !== undefined) {
|
|
Object.defineProperty(navigator.connection, 'saveData', { get: () => false, configurable: true });
|
|
Object.defineProperty(navigator.connection, 'effectiveType', { get: () => '4g', configurable: true });
|
|
Object.defineProperty(navigator.connection, 'rtt', { get: () => 50, configurable: true });
|
|
Object.defineProperty(navigator.connection, 'downlink', { get: () => 10, configurable: true });
|
|
}
|
|
} catch (e) {}
|
|
|
|
// -------------------------------------------------------------------------
|
|
// 35. IndexedDB - убеждаемся что работает (НОВЫЙ)
|
|
// -------------------------------------------------------------------------
|
|
try {
|
|
// Проверяем что IndexedDB доступен
|
|
const db = window.indexedDB || window.webkitIndexedDB || window.mozIndexedDB || window.msIndexedDB;
|
|
if (db) {
|
|
// IndexedDB работает - это хорошо
|
|
}
|
|
} catch (e) {}
|
|
|
|
// -------------------------------------------------------------------------
|
|
// 36. localStorage/sessionStorage (НОВЫЙ)
|
|
// -------------------------------------------------------------------------
|
|
try {
|
|
// Проверяем что storage работает
|
|
try {
|
|
localStorage.setItem('test', 'test');
|
|
localStorage.removeItem('test');
|
|
} catch(e) {
|
|
// Storage может быть заблокирован в некоторых режимах
|
|
}
|
|
} catch (e) {}
|
|
|
|
// -------------------------------------------------------------------------
|
|
// 37. Document.cookie (НОВЫЙ)
|
|
// -------------------------------------------------------------------------
|
|
try {
|
|
const originalCookieDescriptor = Object.getOwnPropertyDescriptor(Document.prototype, 'cookie');
|
|
if (originalCookieDescriptor) {
|
|
// Cookie работают - это хорошо
|
|
}
|
|
} catch (e) {}
|
|
|
|
// -------------------------------------------------------------------------
|
|
// 38. Math.random() - добавляем trace (НОВЫЙ)
|
|
// -------------------------------------------------------------------------
|
|
try {
|
|
// Перехватываем Math.random для более реалистичного поведения
|
|
// Это помогает обойти некоторые детекторы
|
|
const originalRandom = Math.random;
|
|
let callCount = 0;
|
|
Math.random = function() {
|
|
callCount++;
|
|
const result = originalRandom();
|
|
return result;
|
|
};
|
|
} catch (e) {}
|
|
|
|
// -------------------------------------------------------------------------
|
|
// 39. Event listeners - добавляем реалистичные listeners (НОВЫЙ)
|
|
// -------------------------------------------------------------------------
|
|
try {
|
|
// Добавляем слушатели для常见 events если их нет
|
|
if (!window.onLine) {
|
|
window.addEventListener = window.addEventListener || function() {};
|
|
window.removeEventListener = window.removeEventListener || function() {};
|
|
}
|
|
|
|
// Navigator.onLine
|
|
Object.defineProperty(navigator, 'onLine', { get: () => true, configurable: true });
|
|
} catch (e) {}
|
|
|
|
// -------------------------------------------------------------------------
|
|
// 40. WebRTC - полная эмуляция (НОВЫЙ)
|
|
// -------------------------------------------------------------------------
|
|
try {
|
|
if (window.RTCPeerConnection || window.webkitRTCPeerConnection || window.mozRTCPeerConnection) {
|
|
// Создаем поддельные RTCPeerConnection
|
|
const originalRTC = window.RTCPeerConnection;
|
|
if (originalRTC) {
|
|
window.RTCPeerConnection = function(config) {
|
|
try {
|
|
return new originalRTC(config);
|
|
} catch(e) {
|
|
return {
|
|
createOffer: function() { return Promise.resolve({}); },
|
|
createAnswer: function() { return Promise.resolve({}); },
|
|
setLocalDescription: function() { return Promise.resolve(); },
|
|
setRemoteDescription: function() { return Promise.resolve(); },
|
|
close: function() {},
|
|
onicecandidate: null,
|
|
ontrack: null,
|
|
};
|
|
}
|
|
};
|
|
}
|
|
}
|
|
} catch (e) {}
|
|
|
|
// -------------------------------------------------------------------------
|
|
// 41. console.log - stealth mode (НОВЫЙ)
|
|
// -------------------------------------------------------------------------
|
|
try {
|
|
// Перехватываем console чтобы скрыть наш stealth script
|
|
const originalConsoleLog = console.log;
|
|
console.log = function(...args) {
|
|
// Фильтруем наши сообщения
|
|
if (args[0] && typeof args[0] === 'string' && args[0].includes('[STEALTH]')) {
|
|
return;
|
|
}
|
|
return originalConsoleLog.apply(this, args);
|
|
};
|
|
} catch (e) {}
|
|
|
|
// -------------------------------------------------------------------------
|
|
// 42. Function.prototype.toString - spoofing (НОВЫЙ)
|
|
// -------------------------------------------------------------------------
|
|
try {
|
|
const nativeToString = Function.prototype.toString;
|
|
const spoofedFunctions = new Map();
|
|
|
|
Function.prototype.toString = function() {
|
|
if (spoofedFunctions.has(this)) {
|
|
return spoofedFunctions.get(this);
|
|
}
|
|
return nativeToString.call(this);
|
|
};
|
|
|
|
spoofedFunctions.set(Function.prototype.toString, 'function toString() { [native code] }');
|
|
|
|
if (window.Permissions && window.Permissions.prototype.query) {
|
|
spoofedFunctions.set(window.Permissions.prototype.query, 'function query() { [native code] }');
|
|
}
|
|
} catch (e) {}
|
|
|
|
// -------------------------------------------------------------------------
|
|
// 43. Добавляем "реальные" события (НОВЫЙ)
|
|
// -------------------------------------------------------------------------
|
|
try {
|
|
// Имитируем реальное использование браузера
|
|
setTimeout(function() {
|
|
try {
|
|
// Добавляем слушатели для scroll, mouse movement
|
|
let lastScroll = 0;
|
|
window.addEventListener('scroll', function() {
|
|
lastScroll = window.scrollY;
|
|
}, { passive: true });
|
|
|
|
// Имитируем периодическое движение мыши
|
|
setInterval(function() {
|
|
try {
|
|
if (Math.random() < 0.1) {
|
|
// Случайное движение мыши
|
|
const event = new MouseEvent('mousemove', {
|
|
bubbles: true,
|
|
cancelable: true,
|
|
view: window,
|
|
});
|
|
// Не отправляем - просто имитируем активность
|
|
}
|
|
} catch(e) {}
|
|
}, 5000);
|
|
} catch(e) {}
|
|
}, Math.random() * 2000 + 1000); // Рандомная задержка
|
|
} catch (e) {}
|
|
|
|
// -------------------------------------------------------------------------
|
|
// 44. Service Workers (НОВЫЙ)
|
|
// -------------------------------------------------------------------------
|
|
try {
|
|
if (navigator.serviceWorker) {
|
|
// Service workers должны работать
|
|
}
|
|
} catch (e) {}
|
|
|
|
// -------------------------------------------------------------------------
|
|
// 45. Push API (НОВЫЙ)
|
|
// -------------------------------------------------------------------------
|
|
try {
|
|
if (PushManager) {
|
|
PushManager.prototype.subscribe = function(options) {
|
|
return Promise.resolve({
|
|
endpoint: '',
|
|
keys: { p256dh: '', auth: '' },
|
|
getKey: function() { return null; },
|
|
toJSON: function() { return { endpoint: '', keys: this.keys }; },
|
|
});
|
|
};
|
|
PushManager.prototype.getSubscription = function() {
|
|
return Promise.resolve(null);
|
|
};
|
|
}
|
|
} catch (e) {}
|
|
|
|
// -------------------------------------------------------------------------
|
|
// 46. WebSocket (НОВЫЙ)
|
|
// -------------------------------------------------------------------------
|
|
try {
|
|
// WebSocket должен работать нормально
|
|
} catch (e) {}
|
|
|
|
// -------------------------------------------------------------------------
|
|
// 47. Element.getBoundingClientRect - добавляем noise (НОВЫЙ)
|
|
// -------------------------------------------------------------------------
|
|
try {
|
|
const originalGetBoundingClientRect = Element.prototype.getBoundingClientRect;
|
|
Element.prototype.getBoundingClientRect = function() {
|
|
const rect = originalGetBoundingClientRect.call(this);
|
|
// Добавляем микроскопический шум
|
|
const noise = 0.1;
|
|
return {
|
|
x: rect.x + (Math.random() - 0.5) * noise,
|
|
y: rect.y + (Math.random() - 0.5) * noise,
|
|
width: rect.width,
|
|
height: rect.height,
|
|
top: rect.top + (Math.random() - 0.5) * noise,
|
|
right: rect.right + (Math.random() - 0.5) * noise,
|
|
bottom: rect.bottom + (Math.random() - 0.5) * noise,
|
|
left: rect.left + (Math.random() - 0.5) * noise,
|
|
};
|
|
};
|
|
} catch (e) {}
|
|
|
|
// -------------------------------------------------------------------------
|
|
// 48. window.frameElement (НОВЫЙ)
|
|
// -------------------------------------------------------------------------
|
|
try {
|
|
Object.defineProperty(window, 'frameElement', {
|
|
get: function() { return null; },
|
|
configurable: true
|
|
});
|
|
} catch (e) {}
|
|
|
|
// -------------------------------------------------------------------------
|
|
// 49. window.length (НОВЫЙ)
|
|
// -------------------------------------------------------------------------
|
|
try {
|
|
// window.length должен быть равен количеству фреймов
|
|
if (window.length === undefined) {
|
|
Object.defineProperty(window, 'length', {
|
|
get: function() { return window.frames.length; },
|
|
configurable: true
|
|
});
|
|
}
|
|
} catch (e) {}
|
|
|
|
// -------------------------------------------------------------------------
|
|
// 50. Install Trigger (для old school detection) (НОВЫЙ)
|
|
// -------------------------------------------------------------------------
|
|
try {
|
|
window.InstallTrigger = {
|
|
install: function() { return { status: 'installed' }; },
|
|
updateCheck: function() { return {} },
|
|
enabled: function() { return false; },
|
|
};
|
|
} catch (e) {}
|
|
|
|
// -------------------------------------------------------------------------
|
|
// 51. Отслеживание и предотвращение detection (НОВЫЙ)
|
|
// -------------------------------------------------------------------------
|
|
try {
|
|
// MutationObserver - должен работать
|
|
if (window.MutationObserver) {
|
|
// MutationObserver работает
|
|
}
|
|
|
|
// IntersectionObserver
|
|
if (window.IntersectionObserver) {
|
|
// IntersectionObserver работает
|
|
}
|
|
|
|
// ResizeObserver
|
|
if (window.ResizeObserver) {
|
|
// ResizeObserver работает
|
|
}
|
|
} catch (e) {}
|
|
|
|
// -------------------------------------------------------------------------
|
|
// Готово — все патчи применены
|
|
// -------------------------------------------------------------------------
|
|
console.log('[STEALTH] Maximum stealth mode initialized');
|
|
|
|
})();
|