feat : better browser spoofing
This commit is contained in:
+66
-165
@@ -1,55 +1,35 @@
|
||||
|
||||
// Core automation masking
|
||||
Object.defineProperty(navigator, 'webdriver', {get: () => undefined});
|
||||
delete window.cdc_adoQpoasnfa76pfcZLmcfl_Array;
|
||||
delete window.cdc_adoQpoasnfa76pfcZLmcfl_Promise;
|
||||
delete window.cdc_adoQpoasnfa76pfcZLmcfl_Symbol;
|
||||
|
||||
window.RTCPeerConnection = undefined;
|
||||
window.webkitRTCPeerConnection = undefined;
|
||||
window.mozRTCPeerConnection = undefined;
|
||||
|
||||
window.Notification = class Notification {
|
||||
constructor(title, options = {}) {
|
||||
this.title = title;
|
||||
this.options = options;
|
||||
}
|
||||
static permission = 'granted';
|
||||
static requestPermission = () => Promise.resolve('granted');
|
||||
close() {}
|
||||
onclick = null;
|
||||
onerror = null;
|
||||
onclose = null;
|
||||
onshow = null;
|
||||
};
|
||||
|
||||
Object.keys(window).forEach((key) => {
|
||||
if (key.includes("webdriver") || key.includes("selenium") || key.includes("driver")) {
|
||||
delete window[key];
|
||||
}
|
||||
});
|
||||
|
||||
// Forceful chrome object spoofing
|
||||
try {
|
||||
Object.defineProperty(window, 'chrome', {
|
||||
writable: true,
|
||||
configurable: true,
|
||||
value: {
|
||||
app: {isInstalled: false},
|
||||
webstore: {onInstallStageChanged: {}, onDownloadProgress: {}},
|
||||
runtime: {
|
||||
PlatformOs: {MAC: 'mac', WIN: 'win', ANDROID: 'android'},
|
||||
PlatformArch: {ARM: 'arm', X86_32: 'x86-32', X86_64: 'x86-64'},
|
||||
PlatformNaclArch: {ARM: 'arm', X86_32: 'x86-32', X86_64: 'x86-64'},
|
||||
RequestUpdateCheckStatus: {
|
||||
THROTTLED: 'throttled',
|
||||
NO_UPDATE: 'no_update',
|
||||
UPDATE_AVAILABLE: 'update_available'
|
||||
},
|
||||
OnInstalledReason: {
|
||||
INSTALL: 'install',
|
||||
UPDATE: 'update',
|
||||
SHARED_MODULE_UPDATE: 'shared_module_update'
|
||||
},
|
||||
OnRestartRequiredReason: {
|
||||
APP_UPDATE: 'app_update',
|
||||
OS_UPDATE: 'os_update',
|
||||
PERIODIC: 'periodic'
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (e) {
|
||||
console.log("Error in defining window.chrome: ", e);
|
||||
// Fallback: direct assignment
|
||||
window.chrome = window.chrome || {};
|
||||
window.chrome.app = {isInstalled: false};
|
||||
window.chrome.webstore = {onInstallStageChanged: {}, onDownloadProgress: {}};
|
||||
}
|
||||
|
||||
// Randomize plugins
|
||||
|
||||
const pluginsList = [
|
||||
{type: 'application/x-google-chrome-pdf', description: 'Portable Document Format', filename: 'internal-pdf-viewer', name: 'Chrome PDF Plugin'},
|
||||
{type: 'application/x-nacl', description: 'Native Client Executable', filename: 'internal-nacl-plugin', name: 'Native Client'},
|
||||
@@ -59,7 +39,8 @@ Object.defineProperty(navigator, 'plugins', {
|
||||
get: () => pluginsList.slice(0, Math.floor(Math.random() * pluginsList.length) + 1)
|
||||
});
|
||||
|
||||
// Font spoofing with randomized font list
|
||||
// Font spoofing
|
||||
|
||||
const fontList = ['Arial', 'Helvetica', 'Times New Roman', 'Courier New', 'Verdana'];
|
||||
Object.defineProperty(document, 'fonts', {
|
||||
value: {
|
||||
@@ -74,64 +55,53 @@ Object.defineProperty(document, 'fonts', {
|
||||
});
|
||||
|
||||
// Canvas fingerprint spoofing
|
||||
const originalToDataURL = HTMLCanvasElement.prototype.toDataURL;
|
||||
|
||||
HTMLCanvasElement.prototype.toDataURL = function() {
|
||||
const ctx = this.getContext('2d');
|
||||
ctx.fillStyle = `rgba(${Math.random() * 10},${Math.random() * 10},${Math.random() * 10},0.01)`;
|
||||
ctx.fillRect(0, 0, 1, 1);
|
||||
// Add varied noise to avoid consistent fingerprints
|
||||
for (let i = 0; i < 10; i++) {
|
||||
ctx.fillStyle = `rgba(${Math.random() * 5}, ${Math.random() * 5}, ${Math.random() * 5}, 0.005)`;
|
||||
ctx.fillRect(Math.random() * this.width, Math.random() * this.height, 1, 1);
|
||||
}
|
||||
return originalToDataURL.apply(this, arguments);
|
||||
};
|
||||
|
||||
// Screen resolution spoofing
|
||||
const resolutions = [[1920, 1080], [1366, 768], [1440, 900]];
|
||||
const [w, h] = resolutions[Math.floor(Math.random() * resolutions.length)];
|
||||
const [w, h] = [1920, 1080];
|
||||
Object.defineProperty(window, 'screen', {
|
||||
value: {
|
||||
width: w,
|
||||
height: h,
|
||||
availWidth: w,
|
||||
availHeight: h - 50,
|
||||
colorDepth: 24,
|
||||
pixelDepth: 24
|
||||
}
|
||||
value: {
|
||||
width: w,
|
||||
height: h,
|
||||
availWidth: w - 20,
|
||||
availHeight: h - 100,
|
||||
colorDepth: 24,
|
||||
pixelDepth: 24
|
||||
}
|
||||
});
|
||||
|
||||
// Timezone and language spoofing
|
||||
Object.defineProperty(navigator, 'language', {get: () => 'en-US'});
|
||||
Intl.DateTimeFormat = function() {
|
||||
return {resolvedOptions: () => ({timeZone: 'America/New_York'})};
|
||||
|
||||
// ===== WebGL Consistency =====
|
||||
const os = navigator.userAgent.includes('Windows') ? 'Windows' : 'Mac';
|
||||
const webGLParams = {
|
||||
'Windows': {
|
||||
37445: 'Google Inc. (NVIDIA)', // VENDOR
|
||||
37446: 'ANGLE (NVIDIA, NVIDIA GeForce RTX 3060)', // RENDERER
|
||||
36349: 'NVIDIA Corporation', // UNMASKED_VENDOR_WEBGL
|
||||
37444: 'NVIDIA GeForce RTX 3060', // UNMASKED_RENDERER_WEBGL
|
||||
35661: 'WebGL 2.0' // VERSION
|
||||
},
|
||||
'Mac': {
|
||||
37445: 'Apple Inc.',
|
||||
37446: 'Apple M1 Pro',
|
||||
36349: 'Apple',
|
||||
37444: 'Apple M1 Pro',
|
||||
35661: 'WebGL 2.0 (Metal)'
|
||||
}
|
||||
};
|
||||
|
||||
// AudioContext spoofing
|
||||
const originalCreate = window.AudioContext || window.webkitAudioContext;
|
||||
window.AudioContext = window.webkitAudioContext = function() {
|
||||
const context = new originalCreate();
|
||||
const dest = context.createAnalyser();
|
||||
dest.fake = true;
|
||||
return context;
|
||||
};
|
||||
|
||||
// WebRTC spoofing
|
||||
Object.defineProperty(navigator, 'mediaDevices', {
|
||||
get: () => undefined
|
||||
});
|
||||
Object.defineProperty(navigator, 'getUserMedia', {
|
||||
get: () => undefined
|
||||
});
|
||||
|
||||
// web gl spoofing
|
||||
const getParameter = WebGLRenderingContext.prototype.getParameter;
|
||||
// replace WebGL parameters
|
||||
WebGLRenderingContext.prototype.getParameter = function(parameter) {
|
||||
// Common WebGL parameters
|
||||
const params = {
|
||||
37445: 'Intel Open Source Technology Center', // VENDOR
|
||||
37446: 'Mesa DRI Intel® HD Graphics 4000', // RENDERER
|
||||
34076: 'WebKit WebGL', // SHADING_LANGUAGE_VERSION
|
||||
35661: '2.1 INTEL-16.4.5', // VERSION
|
||||
36349: 'Intel Inc.' // UNMASKED_VENDOR_WEBGL
|
||||
};
|
||||
return params[parameter] || getParameter.call(this, parameter);
|
||||
};
|
||||
return webGLParams[os][parameter] || getParameter.call(this, parameter);
|
||||
};
|
||||
|
||||
// Performance API spoofing
|
||||
if ('performance' in window) {
|
||||
@@ -145,81 +115,12 @@ if ('performance' in window) {
|
||||
});
|
||||
}
|
||||
|
||||
// Battery API spoofing
|
||||
if ('getBattery' in navigator) {
|
||||
Object.defineProperty(navigator, 'getBattery', {
|
||||
value: () => Promise.resolve({
|
||||
level: 0.85,
|
||||
charging: true,
|
||||
chargingTime: 1800,
|
||||
dischargingTime: Infinity,
|
||||
onchargingchange: null,
|
||||
onchargingtimechange: null,
|
||||
ondischargingtimechange: null,
|
||||
onlevelchange: null
|
||||
}),
|
||||
configurable: true
|
||||
});
|
||||
}
|
||||
|
||||
window.RTCPeerConnection = undefined;
|
||||
window.webkitRTCPeerConnection = undefined;
|
||||
window.mozRTCPeerConnection = undefined;
|
||||
|
||||
Object.defineProperty(navigator, 'permissions', {
|
||||
value: {
|
||||
query: () => Promise.resolve({ state: 'denied' })
|
||||
}
|
||||
});
|
||||
Object.defineProperty(navigator, 'languages', {
|
||||
get: () => ['en-US', 'en'],
|
||||
});
|
||||
|
||||
const canvas = document.createElement('canvas');
|
||||
const gl = canvas.getContext('webgl') || canvas.getContext('experimental-webgl');
|
||||
|
||||
if (gl) {
|
||||
// Store original getParameter function
|
||||
const originalGetParameter = gl.getParameter;
|
||||
// Override getParameter to spoof values
|
||||
gl.getParameter = function(parameter) {
|
||||
// UNMASKED_VENDOR_WEBGL
|
||||
if (parameter === 37445) return 'Intel Inc.';
|
||||
// UNMASKED_RENDERER_WEBGL
|
||||
if (parameter === 37446) return 'Intel Iris Pro OpenGL Engine';
|
||||
// Other common fingerprint points
|
||||
if (parameter === gl.VERSION) return 'WebGL 2.0 (OpenGL ES 3.0 Intel)';
|
||||
if (parameter === gl.SHADING_LANGUAGE_VERSION) return 'WebGL GLSL ES 3.00 (OpenGL ES GLSL ES 3.0)';
|
||||
|
||||
// Default to original behavior
|
||||
return originalGetParameter.call(gl, parameter);
|
||||
};
|
||||
|
||||
// Spoof debug renderer info extension
|
||||
const debugInfo = {
|
||||
getExtension: function(name) {
|
||||
if (name === 'WEBGL_debug_renderer_info') {
|
||||
return {
|
||||
UNMASKED_VENDOR_WEBGL: 37445,
|
||||
UNMASKED_RENDERER_WEBGL: 37446,
|
||||
__proto__: WebGLExtension.prototype
|
||||
};
|
||||
}
|
||||
return null;
|
||||
},
|
||||
__proto__: WebGLRenderingContext.prototype
|
||||
};
|
||||
|
||||
// Override getExtension
|
||||
const originalGetExtension = gl.getExtension;
|
||||
gl.getExtension = function(name) {
|
||||
if (name === 'WEBGL_debug_renderer_info') {
|
||||
return debugInfo;
|
||||
}
|
||||
return originalGetExtension.call(gl, name);
|
||||
};
|
||||
|
||||
// Freeze objects to prevent detection
|
||||
Object.freeze(gl);
|
||||
Object.freeze(debugInfo);
|
||||
}
|
||||
const originalCreate = window.AudioContext || window.webkitAudioContext;
|
||||
window.AudioContext = window.webkitAudioContext = function() {
|
||||
const context = new originalCreate();
|
||||
const analyser = context.createAnalyser();
|
||||
analyser.fake = true; // Mark as spoofed
|
||||
// Spoof common methods
|
||||
analyser.getFloatFrequencyData = () => new Float32Array(1024).fill(Math.random() * -100);
|
||||
return context;
|
||||
};
|
||||
Reference in New Issue
Block a user