jumpy-lion 0.1.1 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser-controller.d.ts +22 -3
- package/dist/browser-controller.d.ts.map +1 -1
- package/dist/browser-controller.js +316 -71
- package/dist/browser-controller.js.map +1 -1
- package/dist/browser-plugin.d.ts +56 -7
- package/dist/browser-plugin.d.ts.map +1 -1
- package/dist/browser-plugin.js +268 -56
- package/dist/browser-plugin.js.map +1 -1
- package/dist/browser-process/browser.d.ts +39 -0
- package/dist/browser-process/browser.d.ts.map +1 -1
- package/dist/browser-process/browser.js +125 -16
- package/dist/browser-process/browser.js.map +1 -1
- package/dist/browser-process/process.d.ts +9 -0
- package/dist/browser-process/process.d.ts.map +1 -1
- package/dist/browser-process/process.js +100 -6
- package/dist/browser-process/process.js.map +1 -1
- package/dist/browser-profiles/chrome/default.d.ts +116 -0
- package/dist/browser-profiles/chrome/default.d.ts.map +1 -1
- package/dist/browser-profiles/chrome/default.js +118 -1
- package/dist/browser-profiles/chrome/default.js.map +1 -1
- package/dist/browser-profiles/chrome/populate-profile.d.ts +76 -0
- package/dist/browser-profiles/chrome/populate-profile.d.ts.map +1 -0
- package/dist/browser-profiles/chrome/populate-profile.js +300 -0
- package/dist/browser-profiles/chrome/populate-profile.js.map +1 -0
- package/dist/browser-profiles/index.d.ts +1 -0
- package/dist/browser-profiles/index.d.ts.map +1 -1
- package/dist/browser-profiles/index.js +2 -0
- package/dist/browser-profiles/index.js.map +1 -1
- package/dist/crawler.d.ts +81 -9
- package/dist/crawler.d.ts.map +1 -1
- package/dist/crawler.js +26 -10
- package/dist/crawler.js.map +1 -1
- package/dist/fingerprinting/all-fingerprint-defender/_locales/en/messages.json +95 -0
- package/dist/fingerprinting/all-fingerprint-defender/assets/chunk-16ff15da.d.ts +2 -0
- package/dist/fingerprinting/all-fingerprint-defender/assets/chunk-16ff15da.d.ts.map +1 -0
- package/dist/fingerprinting/all-fingerprint-defender/assets/chunk-16ff15da.js +1 -0
- package/dist/fingerprinting/all-fingerprint-defender/assets/chunk-16ff15da.js.map +1 -0
- package/dist/fingerprinting/all-fingerprint-defender/assets/chunk-1a1456ec.d.ts +2 -0
- package/dist/fingerprinting/all-fingerprint-defender/assets/chunk-1a1456ec.d.ts.map +1 -0
- package/dist/fingerprinting/all-fingerprint-defender/assets/chunk-1a1456ec.js +1 -0
- package/dist/fingerprinting/all-fingerprint-defender/assets/chunk-1a1456ec.js.map +1 -0
- package/dist/fingerprinting/all-fingerprint-defender/assets/chunk-3a7b59dd.d.ts +83 -0
- package/dist/fingerprinting/all-fingerprint-defender/assets/chunk-3a7b59dd.d.ts.map +1 -0
- package/dist/fingerprinting/all-fingerprint-defender/assets/chunk-3a7b59dd.js +1 -0
- package/dist/fingerprinting/all-fingerprint-defender/assets/chunk-3a7b59dd.js.map +1 -0
- package/dist/fingerprinting/all-fingerprint-defender/assets/chunk-7ce85519.d.ts +2 -0
- package/dist/fingerprinting/all-fingerprint-defender/assets/chunk-7ce85519.d.ts.map +1 -0
- package/dist/fingerprinting/all-fingerprint-defender/assets/chunk-7ce85519.js +1 -0
- package/dist/fingerprinting/all-fingerprint-defender/assets/chunk-7ce85519.js.map +1 -0
- package/dist/fingerprinting/all-fingerprint-defender/assets/chunk-aaea1190.d.ts +2 -0
- package/dist/fingerprinting/all-fingerprint-defender/assets/chunk-aaea1190.d.ts.map +1 -0
- package/dist/fingerprinting/all-fingerprint-defender/assets/chunk-aaea1190.js +1 -0
- package/dist/fingerprinting/all-fingerprint-defender/assets/chunk-aaea1190.js.map +1 -0
- package/dist/fingerprinting/all-fingerprint-defender/assets/chunk-b4410958.d.ts +2 -0
- package/dist/fingerprinting/all-fingerprint-defender/assets/chunk-b4410958.d.ts.map +1 -0
- package/dist/fingerprinting/all-fingerprint-defender/assets/chunk-b4410958.js +1 -0
- package/dist/fingerprinting/all-fingerprint-defender/assets/chunk-b4410958.js.map +1 -0
- package/dist/fingerprinting/all-fingerprint-defender/assets/chunk-dfed3562.d.ts +2 -0
- package/dist/fingerprinting/all-fingerprint-defender/assets/chunk-dfed3562.d.ts.map +1 -0
- package/dist/fingerprinting/all-fingerprint-defender/assets/chunk-dfed3562.js +1 -0
- package/dist/fingerprinting/all-fingerprint-defender/assets/chunk-dfed3562.js.map +1 -0
- package/dist/fingerprinting/all-fingerprint-defender/assets/debounce-09920c81.css +1 -0
- package/dist/fingerprinting/all-fingerprint-defender/assets/options-fe2fb5aa.css +1 -0
- package/dist/fingerprinting/all-fingerprint-defender/assets/popup-1886d2ef.css +1 -0
- package/dist/fingerprinting/all-fingerprint-defender/img/icon-128.png +0 -0
- package/dist/fingerprinting/all-fingerprint-defender/img/icon-16.png +0 -0
- package/dist/fingerprinting/all-fingerprint-defender/img/icon-24.png +0 -0
- package/dist/fingerprinting/all-fingerprint-defender/img/icon-32-disabled.png +0 -0
- package/dist/fingerprinting/all-fingerprint-defender/img/icon-32.png +0 -0
- package/dist/fingerprinting/all-fingerprint-defender/img/icon-48.png +0 -0
- package/dist/fingerprinting/all-fingerprint-defender/manifest.json +83 -0
- package/dist/fingerprinting/all-fingerprint-defender/options.html +17 -0
- package/dist/fingerprinting/all-fingerprint-defender/popup.html +23 -0
- package/dist/fingerprinting/anti-webgpu/background.d.ts +2 -0
- package/dist/fingerprinting/anti-webgpu/background.d.ts.map +1 -0
- package/dist/fingerprinting/anti-webgpu/background.js +4 -0
- package/dist/fingerprinting/anti-webgpu/background.js.map +1 -0
- package/dist/fingerprinting/anti-webgpu/data/content_script/inject.d.ts +2 -0
- package/dist/fingerprinting/anti-webgpu/data/content_script/inject.d.ts.map +1 -0
- package/dist/fingerprinting/anti-webgpu/data/content_script/inject.js +50 -0
- package/dist/fingerprinting/anti-webgpu/data/content_script/inject.js.map +1 -0
- package/dist/fingerprinting/anti-webgpu/data/content_script/page_context/inject.d.ts +2 -0
- package/dist/fingerprinting/anti-webgpu/data/content_script/page_context/inject.d.ts.map +1 -0
- package/dist/fingerprinting/anti-webgpu/data/content_script/page_context/inject.js +172 -0
- package/dist/fingerprinting/anti-webgpu/data/content_script/page_context/inject.js.map +1 -0
- package/dist/fingerprinting/anti-webgpu/data/icons/128.png +0 -0
- package/dist/fingerprinting/anti-webgpu/data/icons/16.png +0 -0
- package/dist/fingerprinting/anti-webgpu/data/icons/32.png +0 -0
- package/dist/fingerprinting/anti-webgpu/data/icons/48.png +0 -0
- package/dist/fingerprinting/anti-webgpu/data/icons/64.png +0 -0
- package/dist/fingerprinting/anti-webgpu/data/popup/popup.css +88 -0
- package/dist/fingerprinting/anti-webgpu/data/popup/popup.d.ts +2 -0
- package/dist/fingerprinting/anti-webgpu/data/popup/popup.d.ts.map +1 -0
- package/dist/fingerprinting/anti-webgpu/data/popup/popup.html +58 -0
- package/dist/fingerprinting/anti-webgpu/data/popup/popup.js +96 -0
- package/dist/fingerprinting/anti-webgpu/data/popup/popup.js.map +1 -0
- package/dist/fingerprinting/anti-webgpu/lib/chrome.d.ts +2 -0
- package/dist/fingerprinting/anti-webgpu/lib/chrome.d.ts.map +1 -0
- package/dist/fingerprinting/anti-webgpu/lib/chrome.js +249 -0
- package/dist/fingerprinting/anti-webgpu/lib/chrome.js.map +1 -0
- package/dist/fingerprinting/anti-webgpu/lib/common.d.ts +2 -0
- package/dist/fingerprinting/anti-webgpu/lib/common.d.ts.map +1 -0
- package/dist/fingerprinting/anti-webgpu/lib/common.js +86 -0
- package/dist/fingerprinting/anti-webgpu/lib/common.js.map +1 -0
- package/dist/fingerprinting/anti-webgpu/lib/config.d.ts +2 -0
- package/dist/fingerprinting/anti-webgpu/lib/config.d.ts.map +1 -0
- package/dist/fingerprinting/anti-webgpu/lib/config.js +14 -0
- package/dist/fingerprinting/anti-webgpu/lib/config.js.map +1 -0
- package/dist/fingerprinting/anti-webgpu/lib/runtime.d.ts +2 -0
- package/dist/fingerprinting/anti-webgpu/lib/runtime.d.ts.map +1 -0
- package/dist/fingerprinting/anti-webgpu/lib/runtime.js +107 -0
- package/dist/fingerprinting/anti-webgpu/lib/runtime.js.map +1 -0
- package/dist/fingerprinting/anti-webgpu/manifest.json +58 -0
- package/dist/fingerprinting/custom-fingerprint-injector.d.ts +87 -0
- package/dist/fingerprinting/custom-fingerprint-injector.d.ts.map +1 -0
- package/dist/fingerprinting/custom-fingerprint-injector.js +342 -0
- package/dist/fingerprinting/custom-fingerprint-injector.js.map +1 -0
- package/dist/fingerprinting/fingerprint-injector.d.ts +157 -0
- package/dist/fingerprinting/fingerprint-injector.d.ts.map +1 -0
- package/dist/fingerprinting/fingerprint-injector.js +632 -0
- package/dist/fingerprinting/fingerprint-injector.js.map +1 -0
- package/dist/fingerprinting/fingerprint-overrides/audio-spoofing.d.ts +6 -0
- package/dist/fingerprinting/fingerprint-overrides/audio-spoofing.d.ts.map +1 -0
- package/dist/fingerprinting/fingerprint-overrides/audio-spoofing.js +119 -0
- package/dist/fingerprinting/fingerprint-overrides/audio-spoofing.js.map +1 -0
- package/dist/fingerprinting/fingerprint-overrides/canvas-protection.d.ts +6 -0
- package/dist/fingerprinting/fingerprint-overrides/canvas-protection.d.ts.map +1 -0
- package/dist/fingerprinting/fingerprint-overrides/canvas-protection.js +149 -0
- package/dist/fingerprinting/fingerprint-overrides/canvas-protection.js.map +1 -0
- package/dist/fingerprinting/fingerprint-overrides/cdp-detection-bypass.d.ts +14 -0
- package/dist/fingerprinting/fingerprint-overrides/cdp-detection-bypass.d.ts.map +1 -0
- package/dist/fingerprinting/fingerprint-overrides/cdp-detection-bypass.js +763 -0
- package/dist/fingerprinting/fingerprint-overrides/cdp-detection-bypass.js.map +1 -0
- package/dist/fingerprinting/fingerprint-overrides/client-rect-spoofing.d.ts +6 -0
- package/dist/fingerprinting/fingerprint-overrides/client-rect-spoofing.d.ts.map +1 -0
- package/dist/fingerprinting/fingerprint-overrides/client-rect-spoofing.js +195 -0
- package/dist/fingerprinting/fingerprint-overrides/client-rect-spoofing.js.map +1 -0
- package/dist/fingerprinting/fingerprint-overrides/coalesced-events-spoofing.d.ts +10 -0
- package/dist/fingerprinting/fingerprint-overrides/coalesced-events-spoofing.d.ts.map +1 -0
- package/dist/fingerprinting/fingerprint-overrides/coalesced-events-spoofing.js +195 -0
- package/dist/fingerprinting/fingerprint-overrides/coalesced-events-spoofing.js.map +1 -0
- package/dist/fingerprinting/fingerprint-overrides/datadome-bypass.d.ts +28 -0
- package/dist/fingerprinting/fingerprint-overrides/datadome-bypass.d.ts.map +1 -0
- package/dist/fingerprinting/fingerprint-overrides/datadome-bypass.js +1181 -0
- package/dist/fingerprinting/fingerprint-overrides/datadome-bypass.js.map +1 -0
- package/dist/fingerprinting/fingerprint-overrides/font-spoofing.d.ts +7 -0
- package/dist/fingerprinting/fingerprint-overrides/font-spoofing.d.ts.map +1 -0
- package/dist/fingerprinting/fingerprint-overrides/font-spoofing.js +171 -0
- package/dist/fingerprinting/fingerprint-overrides/font-spoofing.js.map +1 -0
- package/dist/fingerprinting/fingerprint-overrides/index.d.ts +36 -0
- package/dist/fingerprinting/fingerprint-overrides/index.d.ts.map +1 -0
- package/dist/fingerprinting/fingerprint-overrides/index.js +40 -0
- package/dist/fingerprinting/fingerprint-overrides/index.js.map +1 -0
- package/dist/fingerprinting/fingerprint-overrides/keyboard-humanization.d.ts +45 -0
- package/dist/fingerprinting/fingerprint-overrides/keyboard-humanization.d.ts.map +1 -0
- package/dist/fingerprinting/fingerprint-overrides/keyboard-humanization.js +268 -0
- package/dist/fingerprinting/fingerprint-overrides/keyboard-humanization.js.map +1 -0
- package/dist/fingerprinting/fingerprint-overrides/locale-spoofing.d.ts +6 -0
- package/dist/fingerprinting/fingerprint-overrides/locale-spoofing.d.ts.map +1 -0
- package/dist/fingerprinting/fingerprint-overrides/locale-spoofing.js +301 -0
- package/dist/fingerprinting/fingerprint-overrides/locale-spoofing.js.map +1 -0
- package/dist/fingerprinting/fingerprint-overrides/mouse-humanization.d.ts +7 -0
- package/dist/fingerprinting/fingerprint-overrides/mouse-humanization.d.ts.map +1 -0
- package/dist/fingerprinting/fingerprint-overrides/mouse-humanization.js +58 -0
- package/dist/fingerprinting/fingerprint-overrides/mouse-humanization.js.map +1 -0
- package/dist/fingerprinting/fingerprint-overrides/performance-spoofing.d.ts +6 -0
- package/dist/fingerprinting/fingerprint-overrides/performance-spoofing.d.ts.map +1 -0
- package/dist/fingerprinting/fingerprint-overrides/performance-spoofing.js +249 -0
- package/dist/fingerprinting/fingerprint-overrides/performance-spoofing.js.map +1 -0
- package/dist/fingerprinting/fingerprint-overrides/platform-consistency.d.ts +33 -0
- package/dist/fingerprinting/fingerprint-overrides/platform-consistency.d.ts.map +1 -0
- package/dist/fingerprinting/fingerprint-overrides/platform-consistency.js +618 -0
- package/dist/fingerprinting/fingerprint-overrides/platform-consistency.js.map +1 -0
- package/dist/fingerprinting/fingerprint-overrides/prototype-integrity.d.ts +13 -0
- package/dist/fingerprinting/fingerprint-overrides/prototype-integrity.d.ts.map +1 -0
- package/dist/fingerprinting/fingerprint-overrides/prototype-integrity.js +356 -0
- package/dist/fingerprinting/fingerprint-overrides/prototype-integrity.js.map +1 -0
- package/dist/fingerprinting/fingerprint-overrides/runtime-enable-bypass.d.ts +18 -0
- package/dist/fingerprinting/fingerprint-overrides/runtime-enable-bypass.d.ts.map +1 -0
- package/dist/fingerprinting/fingerprint-overrides/runtime-enable-bypass.js +171 -0
- package/dist/fingerprinting/fingerprint-overrides/runtime-enable-bypass.js.map +1 -0
- package/dist/fingerprinting/fingerprint-overrides/scroll-humanization.d.ts +55 -0
- package/dist/fingerprinting/fingerprint-overrides/scroll-humanization.d.ts.map +1 -0
- package/dist/fingerprinting/fingerprint-overrides/scroll-humanization.js +244 -0
- package/dist/fingerprinting/fingerprint-overrides/scroll-humanization.js.map +1 -0
- package/dist/fingerprinting/fingerprint-overrides/stealth-script.d.ts +14 -0
- package/dist/fingerprinting/fingerprint-overrides/stealth-script.d.ts.map +1 -0
- package/dist/fingerprinting/fingerprint-overrides/stealth-script.js +925 -0
- package/dist/fingerprinting/fingerprint-overrides/stealth-script.js.map +1 -0
- package/dist/fingerprinting/fingerprint-overrides/storage-consistency.d.ts +13 -0
- package/dist/fingerprinting/fingerprint-overrides/storage-consistency.d.ts.map +1 -0
- package/dist/fingerprinting/fingerprint-overrides/storage-consistency.js +346 -0
- package/dist/fingerprinting/fingerprint-overrides/storage-consistency.js.map +1 -0
- package/dist/fingerprinting/fingerprint-overrides/timing-consistency.d.ts +13 -0
- package/dist/fingerprinting/fingerprint-overrides/timing-consistency.d.ts.map +1 -0
- package/dist/fingerprinting/fingerprint-overrides/timing-consistency.js +264 -0
- package/dist/fingerprinting/fingerprint-overrides/timing-consistency.js.map +1 -0
- package/dist/fingerprinting/fingerprint-overrides/ua-ch.d.ts +27 -0
- package/dist/fingerprinting/fingerprint-overrides/ua-ch.d.ts.map +1 -0
- package/dist/fingerprinting/fingerprint-overrides/ua-ch.js +213 -0
- package/dist/fingerprinting/fingerprint-overrides/ua-ch.js.map +1 -0
- package/dist/fingerprinting/fingerprint-overrides/utils.d.ts +12 -0
- package/dist/fingerprinting/fingerprint-overrides/utils.d.ts.map +1 -0
- package/dist/fingerprinting/fingerprint-overrides/utils.js +517 -0
- package/dist/fingerprinting/fingerprint-overrides/utils.js.map +1 -0
- package/dist/fingerprinting/fingerprint-overrides/webgl-spoofing.d.ts +12 -0
- package/dist/fingerprinting/fingerprint-overrides/webgl-spoofing.d.ts.map +1 -0
- package/dist/fingerprinting/fingerprint-overrides/webgl-spoofing.js +215 -0
- package/dist/fingerprinting/fingerprint-overrides/webgl-spoofing.js.map +1 -0
- package/dist/fingerprinting/fingerprint-overrides/webgpu-spoofing.d.ts +6 -0
- package/dist/fingerprinting/fingerprint-overrides/webgpu-spoofing.d.ts.map +1 -0
- package/dist/fingerprinting/fingerprint-overrides/webgpu-spoofing.js +202 -0
- package/dist/fingerprinting/fingerprint-overrides/webgpu-spoofing.js.map +1 -0
- package/dist/fingerprinting/fingerprint-overrides/webrtc-spoofing.d.ts +6 -0
- package/dist/fingerprinting/fingerprint-overrides/webrtc-spoofing.d.ts.map +1 -0
- package/dist/fingerprinting/fingerprint-overrides/webrtc-spoofing.js +188 -0
- package/dist/fingerprinting/fingerprint-overrides/webrtc-spoofing.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/launcher-wrap.d.ts +2 -2
- package/dist/launcher-wrap.d.ts.map +1 -1
- package/dist/launcher-wrap.js.map +1 -1
- package/dist/page.d.ts +160 -13
- package/dist/page.d.ts.map +1 -1
- package/dist/page.js +1027 -42
- package/dist/page.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +8 -4
|
@@ -0,0 +1,925 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base stealth script for hiding automation indicators
|
|
3
|
+
* Includes error stack hiding, console patching, and automation flags removal
|
|
4
|
+
*
|
|
5
|
+
* 2024-2025 Enhancements:
|
|
6
|
+
* - deviceMemory spoofing
|
|
7
|
+
* - pdfViewerEnabled consistency
|
|
8
|
+
* - Notification.permission handling
|
|
9
|
+
* - Bluetooth/USB/Serial API masking
|
|
10
|
+
* - Speech synthesis voice spoofing
|
|
11
|
+
* - Credentials API consistency
|
|
12
|
+
*/
|
|
13
|
+
export const createStealthScript = () => {
|
|
14
|
+
return `
|
|
15
|
+
(() => {
|
|
16
|
+
'use strict';
|
|
17
|
+
|
|
18
|
+
// Enhanced stealth script for 2025 - December
|
|
19
|
+
|
|
20
|
+
// Helper functions
|
|
21
|
+
const wrapNative = (fnName) => {
|
|
22
|
+
const nativeCode = 'function ' + fnName + '() { [native code] }';
|
|
23
|
+
return new Proxy(function() {}, {
|
|
24
|
+
get(target, prop) {
|
|
25
|
+
if (prop === 'toString') {
|
|
26
|
+
return () => nativeCode;
|
|
27
|
+
}
|
|
28
|
+
return Reflect.get(target, prop);
|
|
29
|
+
},
|
|
30
|
+
apply(target, thisArg, args) {
|
|
31
|
+
return undefined;
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
// Generate consistent session seed for stable values
|
|
37
|
+
const generateSessionSeed = () => {
|
|
38
|
+
const ua = navigator.userAgent || '';
|
|
39
|
+
const screen = window.screen;
|
|
40
|
+
const seed = ua.length + (screen.width || 0) + (screen.height || 0);
|
|
41
|
+
return seed;
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const sessionSeed = generateSessionSeed();
|
|
45
|
+
|
|
46
|
+
// Helper to safely define property with guards
|
|
47
|
+
const safeDefineProperty = (obj, prop, descriptor) => {
|
|
48
|
+
try {
|
|
49
|
+
const existing = Object.getOwnPropertyDescriptor(obj, prop);
|
|
50
|
+
if (existing && existing.configurable === false) {
|
|
51
|
+
return false; // Cannot redefine
|
|
52
|
+
}
|
|
53
|
+
// Always use configurable: true to allow other scripts to modify
|
|
54
|
+
Object.defineProperty(obj, prop, {
|
|
55
|
+
...descriptor,
|
|
56
|
+
configurable: true
|
|
57
|
+
});
|
|
58
|
+
return true;
|
|
59
|
+
} catch (e) {
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
// Helper to safely define getter property
|
|
65
|
+
const safeDefineGetter = (obj, prop, getter, enumerable = true) => {
|
|
66
|
+
return safeDefineProperty(obj, prop, {
|
|
67
|
+
get: getter,
|
|
68
|
+
enumerable: enumerable
|
|
69
|
+
});
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
// 1. Error Stack Hiding
|
|
73
|
+
// NOTE: Removed - this was returning a HARDCODED fake stack for ALL errors
|
|
74
|
+
// (chrome-extension://invalid/0.js) with configurable:false, which blocked
|
|
75
|
+
// runtime-enable-bypass.ts from applying proper stack sanitization.
|
|
76
|
+
// Stack trace protection is now handled by runtime-enable-bypass.ts.
|
|
77
|
+
const hideErrorStack = () => {};
|
|
78
|
+
|
|
79
|
+
// 2. Console Patching
|
|
80
|
+
// NOTE: Removed - wrapping ALL console methods in double-Proxy is detectable
|
|
81
|
+
// and conflicts with runtime-enable-bypass.ts which handles the actual
|
|
82
|
+
// detection vector (console.debug Error serialization) surgically.
|
|
83
|
+
const patchConsole = () => {};
|
|
84
|
+
|
|
85
|
+
// 3. WebDriver and Automation Flags Removal (2025)
|
|
86
|
+
const removeAutomationFlags = () => {
|
|
87
|
+
// Remove webdriver (with guard)
|
|
88
|
+
if (navigator.webdriver) {
|
|
89
|
+
safeDefineGetter(navigator, 'webdriver', () => undefined, false);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Remove automation indicators
|
|
93
|
+
const automationProperties = [
|
|
94
|
+
'webdriver', '_Selenium_IDE_Recorder', '_selenium', 'callSelenium',
|
|
95
|
+
'_WEBDRIVER_ELEM_CACHE', '__webdriver_script_fn', '__driver_evaluate',
|
|
96
|
+
'__webdriver_evaluate', '__selenium_evaluate', '__fxdriver_evaluate',
|
|
97
|
+
'__driver_unwrapped', '__webdriver_unwrapped', '__selenium_unwrapped',
|
|
98
|
+
'__fxdriver_unwrapped', '__webdriver_scripts_executed',
|
|
99
|
+
'__webdriver_script_func', '__webdriver_script_function',
|
|
100
|
+
'$cdc_asdjflasutopfhvcZLmcfl_', '$chrome_asyncScriptInfo',
|
|
101
|
+
'__$webdriverAsyncExecutor', '__lastWatirAlert', '__lastWatirConfirm',
|
|
102
|
+
'__lastWatirPrompt', '_WEBDRIVER_ELEM_CACHE', 'ChromeDriverw',
|
|
103
|
+
'driver-evaluate', 'webdriver-evaluate', 'selenium-evaluate',
|
|
104
|
+
'webdriverCommand', 'webdriver-evaluate-response'
|
|
105
|
+
];
|
|
106
|
+
|
|
107
|
+
automationProperties.forEach(prop => {
|
|
108
|
+
try {
|
|
109
|
+
delete window[prop];
|
|
110
|
+
delete document[prop];
|
|
111
|
+
delete navigator[prop];
|
|
112
|
+
} catch (e) {}
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
// Ensure window.chrome exists (handled more fully by spoofChromeRuntime)
|
|
116
|
+
// NOTE: Removed stack-trace-based chrome getter that created new Error()
|
|
117
|
+
// on every access - expensive and broken since stack sanitization removes
|
|
118
|
+
// the markers it checked for.
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
// 4. CDP Runtime.enable Detection Prevention
|
|
122
|
+
// NOTE: Removed entirely. This was:
|
|
123
|
+
// - Blocking ALL Object.defineProperty(*, 'stack', ...) calls (broke our own code)
|
|
124
|
+
// - Replacing Error constructor with Proxy returning hardcoded fake stacks
|
|
125
|
+
// Both are handled properly by runtime-enable-bypass.ts with surgical stack sanitization.
|
|
126
|
+
const preventRuntimeEnableDetection = () => {};
|
|
127
|
+
|
|
128
|
+
// 5. Plugin and MimeType Spoofing (2025)
|
|
129
|
+
const spoofPlugins = () => {
|
|
130
|
+
// Chrome 120+ only reports PDF-related plugins
|
|
131
|
+
// Native Client was removed in Chrome 76 (2019)
|
|
132
|
+
const pluginData = [
|
|
133
|
+
{
|
|
134
|
+
name: 'PDF Viewer',
|
|
135
|
+
filename: 'internal-pdf-viewer',
|
|
136
|
+
description: 'Portable Document Format'
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
name: 'Chrome PDF Viewer',
|
|
140
|
+
filename: 'internal-pdf-viewer',
|
|
141
|
+
description: 'Portable Document Format'
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
name: 'Chromium PDF Viewer',
|
|
145
|
+
filename: 'internal-pdf-viewer',
|
|
146
|
+
description: 'Portable Document Format'
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
name: 'Microsoft Edge PDF Viewer',
|
|
150
|
+
filename: 'internal-pdf-viewer',
|
|
151
|
+
description: 'Portable Document Format'
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
name: 'WebKit built-in PDF',
|
|
155
|
+
filename: 'internal-pdf-viewer',
|
|
156
|
+
description: 'Portable Document Format'
|
|
157
|
+
}
|
|
158
|
+
];
|
|
159
|
+
|
|
160
|
+
const mimeData = [
|
|
161
|
+
{
|
|
162
|
+
type: 'application/pdf',
|
|
163
|
+
suffixes: 'pdf',
|
|
164
|
+
description: 'Portable Document Format'
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
type: 'text/pdf',
|
|
168
|
+
suffixes: 'pdf',
|
|
169
|
+
description: 'Portable Document Format'
|
|
170
|
+
}
|
|
171
|
+
];
|
|
172
|
+
|
|
173
|
+
// Create fake plugins using Object.defineProperty for read-only properties
|
|
174
|
+
const fakePlugins = pluginData.map((p, index) => {
|
|
175
|
+
const plugin = Object.create(Plugin.prototype);
|
|
176
|
+
Object.defineProperty(plugin, 'name', { value: p.name, writable: false, enumerable: true });
|
|
177
|
+
Object.defineProperty(plugin, 'filename', { value: p.filename, writable: false, enumerable: true });
|
|
178
|
+
Object.defineProperty(plugin, 'description', { value: p.description, writable: false, enumerable: true });
|
|
179
|
+
Object.defineProperty(plugin, 'length', { value: 1, writable: false, enumerable: true });
|
|
180
|
+
plugin[0] = mimeData[index] || mimeData[0];
|
|
181
|
+
return plugin;
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
// Create fake mimeTypes using Object.defineProperty for read-only properties
|
|
185
|
+
const fakeMimeTypes = mimeData.map((m, index) => {
|
|
186
|
+
const mimeType = Object.create(MimeType.prototype);
|
|
187
|
+
Object.defineProperty(mimeType, 'type', { value: m.type, writable: false, enumerable: true });
|
|
188
|
+
Object.defineProperty(mimeType, 'suffixes', { value: m.suffixes, writable: false, enumerable: true });
|
|
189
|
+
Object.defineProperty(mimeType, 'description', { value: m.description, writable: false, enumerable: true });
|
|
190
|
+
Object.defineProperty(mimeType, 'enabledPlugin', { value: fakePlugins[0], writable: false, enumerable: true });
|
|
191
|
+
return mimeType;
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
// Override navigator.plugins (with guard)
|
|
195
|
+
try {
|
|
196
|
+
const pluginsGetter = () => {
|
|
197
|
+
const arr = Object.create(PluginArray.prototype);
|
|
198
|
+
fakePlugins.forEach((p, i) => {
|
|
199
|
+
arr[i] = p;
|
|
200
|
+
arr[p.name] = p;
|
|
201
|
+
});
|
|
202
|
+
// Use Object.defineProperty for read-only properties
|
|
203
|
+
Object.defineProperty(arr, 'length', { value: fakePlugins.length, writable: false, enumerable: true });
|
|
204
|
+
Object.defineProperty(arr, 'item', { value: (index) => arr[index] || null, writable: false, enumerable: false });
|
|
205
|
+
Object.defineProperty(arr, 'namedItem', { value: (name) => arr[name] || null, writable: false, enumerable: false });
|
|
206
|
+
Object.defineProperty(arr, 'refresh', { value: () => {}, writable: false, enumerable: false });
|
|
207
|
+
return arr;
|
|
208
|
+
};
|
|
209
|
+
safeDefineGetter(navigator, 'plugins', pluginsGetter);
|
|
210
|
+
|
|
211
|
+
// Override navigator.mimeTypes (with guard)
|
|
212
|
+
const mimeTypesGetter = () => {
|
|
213
|
+
const arr = Object.create(MimeTypeArray.prototype);
|
|
214
|
+
fakeMimeTypes.forEach((m, i) => {
|
|
215
|
+
arr[i] = m;
|
|
216
|
+
arr[m.type] = m;
|
|
217
|
+
});
|
|
218
|
+
// Use Object.defineProperty for read-only properties
|
|
219
|
+
Object.defineProperty(arr, 'length', { value: fakeMimeTypes.length, writable: false, enumerable: true });
|
|
220
|
+
Object.defineProperty(arr, 'item', { value: (index) => arr[index] || null, writable: false, enumerable: false });
|
|
221
|
+
Object.defineProperty(arr, 'namedItem', { value: (name) => arr[name] || null, writable: false, enumerable: false });
|
|
222
|
+
return arr;
|
|
223
|
+
};
|
|
224
|
+
safeDefineGetter(navigator, 'mimeTypes', mimeTypesGetter);
|
|
225
|
+
} catch (e) {}
|
|
226
|
+
};
|
|
227
|
+
|
|
228
|
+
// 6. Permission API Spoofing (2025) - Fixed to return consistent Promise identity
|
|
229
|
+
const spoofPermissions = () => {
|
|
230
|
+
if (!navigator.permissions) return;
|
|
231
|
+
|
|
232
|
+
const promiseCache = new Map();
|
|
233
|
+
const originalQuery = navigator.permissions.query;
|
|
234
|
+
|
|
235
|
+
navigator.permissions.query = function(descriptor) {
|
|
236
|
+
// Common permissions that should be granted for a normal user
|
|
237
|
+
const allowedPermissions = ['geolocation', 'notifications', 'camera', 'microphone'];
|
|
238
|
+
|
|
239
|
+
if (descriptor && allowedPermissions.includes(descriptor.name)) {
|
|
240
|
+
// Return the same Promise instance for identical queries (Datadome checks this)
|
|
241
|
+
const key = JSON.stringify(descriptor);
|
|
242
|
+
if (promiseCache.has(key)) {
|
|
243
|
+
return promiseCache.get(key);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
const promise = Promise.resolve({
|
|
247
|
+
state: 'prompt',
|
|
248
|
+
onchange: null,
|
|
249
|
+
addEventListener: () => {},
|
|
250
|
+
removeEventListener: () => {},
|
|
251
|
+
dispatchEvent: () => true
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
promiseCache.set(key, promise);
|
|
255
|
+
return promise;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
return originalQuery.apply(this, arguments);
|
|
259
|
+
};
|
|
260
|
+
};
|
|
261
|
+
|
|
262
|
+
// 7. Battery API Spoofing (2025)
|
|
263
|
+
const spoofBatteryAPI = () => {
|
|
264
|
+
if ('getBattery' in navigator) {
|
|
265
|
+
// Use session seed for deterministic battery level
|
|
266
|
+
const batteryLevel = 0.92 + ((sessionSeed % 80) / 1000); // 0.92-0.999
|
|
267
|
+
navigator.getBattery = async () => {
|
|
268
|
+
return {
|
|
269
|
+
charging: true,
|
|
270
|
+
chargingTime: 0,
|
|
271
|
+
dischargingTime: Infinity,
|
|
272
|
+
level: batteryLevel,
|
|
273
|
+
onchargingchange: null,
|
|
274
|
+
onchargingtimechange: null,
|
|
275
|
+
ondischargingtimechange: null,
|
|
276
|
+
onlevelchange: null,
|
|
277
|
+
addEventListener: () => {},
|
|
278
|
+
removeEventListener: () => {},
|
|
279
|
+
dispatchEvent: () => true
|
|
280
|
+
};
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
};
|
|
284
|
+
|
|
285
|
+
// 8. Connection API Spoofing (2025)
|
|
286
|
+
const spoofConnectionAPI = () => {
|
|
287
|
+
if ('connection' in navigator || 'mozConnection' in navigator || 'webkitConnection' in navigator) {
|
|
288
|
+
const connection = navigator.connection || navigator.mozConnection || navigator.webkitConnection;
|
|
289
|
+
if (connection) {
|
|
290
|
+
try {
|
|
291
|
+
Object.defineProperty(connection, 'rtt', { value: 50, writable: false });
|
|
292
|
+
Object.defineProperty(connection, 'downlink', { value: 10.0, writable: false });
|
|
293
|
+
Object.defineProperty(connection, 'effectiveType', { value: '4g', writable: false });
|
|
294
|
+
Object.defineProperty(connection, 'saveData', { value: false, writable: false });
|
|
295
|
+
} catch (e) {}
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
};
|
|
299
|
+
|
|
300
|
+
// 9. Chrome Runtime API Spoofing (2025) - NEW
|
|
301
|
+
const spoofChromeRuntime = () => {
|
|
302
|
+
if (!window.chrome?.runtime) {
|
|
303
|
+
const runtime = {
|
|
304
|
+
PlatformOs: { MAC: 'mac', WIN: 'win', ANDROID: 'android', CROS: 'cros', LINUX: 'linux', OPENBSD: 'openbsd' },
|
|
305
|
+
PlatformArch: { ARM: 'arm', ARM64: 'arm64', MIPS: 'mips', MIPS64: 'mips64', X86_32: 'x86-32', X86_64: 'x86-64' },
|
|
306
|
+
PlatformNaclArch: { ARM: 'arm', MIPS: 'mips', MIPS64: 'mips64', X86_32: 'x86-32', X86_64: 'x86-64' },
|
|
307
|
+
RequestUpdateCheckStatus: { THROTTLED: 'throttled', NO_UPDATE: 'no_update', UPDATE_AVAILABLE: 'update_available' },
|
|
308
|
+
OnInstalledReason: { INSTALL: 'install', UPDATE: 'update', CHROME_UPDATE: 'chrome_update', SHARED_MODULE_UPDATE: 'shared_module_update' },
|
|
309
|
+
OnRestartRequiredReason: { APP_UPDATE: 'app_update', OS_UPDATE: 'os_update', PERIODIC: 'periodic' },
|
|
310
|
+
getManifest: () => ({}),
|
|
311
|
+
// Real Chrome extension IDs are 32 lowercase alpha chars (a-p, base16 with a-p)
|
|
312
|
+
id: undefined,
|
|
313
|
+
connect: () => ({
|
|
314
|
+
name: '',
|
|
315
|
+
disconnect: () => {},
|
|
316
|
+
onDisconnect: { addListener: () => {}, removeListener: () => {} },
|
|
317
|
+
onMessage: { addListener: () => {}, removeListener: () => {} },
|
|
318
|
+
postMessage: () => {}
|
|
319
|
+
}),
|
|
320
|
+
sendMessage: () => {},
|
|
321
|
+
getURL: (path) => '',
|
|
322
|
+
onConnect: { addListener: () => {}, removeListener: () => {} },
|
|
323
|
+
onMessage: { addListener: () => {}, removeListener: () => {} },
|
|
324
|
+
onStartup: { addListener: () => {}, removeListener: () => {} },
|
|
325
|
+
onInstalled: { addListener: () => {}, removeListener: () => {} },
|
|
326
|
+
onSuspend: { addListener: () => {}, removeListener: () => {} },
|
|
327
|
+
onSuspendCanceled: { addListener: () => {}, removeListener: () => {} },
|
|
328
|
+
onUpdateAvailable: { addListener: () => {}, removeListener: () => {} },
|
|
329
|
+
onBrowserUpdateAvailable: { addListener: () => {}, removeListener: () => {} },
|
|
330
|
+
onRestartRequired: { addListener: () => {}, removeListener: () => {} },
|
|
331
|
+
openOptionsPage: () => {},
|
|
332
|
+
setUninstallURL: () => {},
|
|
333
|
+
reload: () => {},
|
|
334
|
+
requestUpdateCheck: () => Promise.resolve(['no_update', {}]),
|
|
335
|
+
restart: () => {},
|
|
336
|
+
restartAfterDelay: () => {},
|
|
337
|
+
getPlatformInfo: () => Promise.resolve({
|
|
338
|
+
os: 'win',
|
|
339
|
+
arch: 'x86-64',
|
|
340
|
+
nacl_arch: 'x86-64'
|
|
341
|
+
}),
|
|
342
|
+
getPackageDirectoryEntry: () => Promise.resolve({}),
|
|
343
|
+
lastError: null
|
|
344
|
+
};
|
|
345
|
+
|
|
346
|
+
if (!window.chrome) window.chrome = {};
|
|
347
|
+
safeDefineProperty(window.chrome, 'runtime', {
|
|
348
|
+
value: runtime,
|
|
349
|
+
enumerable: true,
|
|
350
|
+
writable: false
|
|
351
|
+
});
|
|
352
|
+
}
|
|
353
|
+
};
|
|
354
|
+
|
|
355
|
+
// 10. Device Memory Spoofing (2024-2025)
|
|
356
|
+
const spoofDeviceMemory = () => {
|
|
357
|
+
const platform = navigator.platform || 'Win32';
|
|
358
|
+
|
|
359
|
+
// Platform-appropriate device memory values
|
|
360
|
+
const memoryConfig = {
|
|
361
|
+
'Win32': [4, 8, 16], // Most Windows PCs have 4-16GB
|
|
362
|
+
'MacIntel': [8, 16], // Macs typically have 8-16GB
|
|
363
|
+
'Linux x86_64': [4, 8, 16]
|
|
364
|
+
};
|
|
365
|
+
|
|
366
|
+
const memories = memoryConfig[platform] || memoryConfig['Win32'];
|
|
367
|
+
// Use session seed for consistency
|
|
368
|
+
const selectedMemory = memories[sessionSeed % memories.length];
|
|
369
|
+
|
|
370
|
+
// Use guard to avoid conflicts with other scripts
|
|
371
|
+
if ('deviceMemory' in navigator) {
|
|
372
|
+
safeDefineGetter(navigator, 'deviceMemory', () => selectedMemory);
|
|
373
|
+
}
|
|
374
|
+
};
|
|
375
|
+
|
|
376
|
+
// 11. PDF Viewer Enabled Spoofing (2024-2025)
|
|
377
|
+
const spoofPdfViewerEnabled = () => {
|
|
378
|
+
// Chrome always has PDF viewer enabled (use guard)
|
|
379
|
+
safeDefineGetter(navigator, 'pdfViewerEnabled', () => true);
|
|
380
|
+
};
|
|
381
|
+
|
|
382
|
+
// 12. Notification Permission Spoofing (2024-2025)
|
|
383
|
+
const spoofNotificationPermission = () => {
|
|
384
|
+
if ('Notification' in window) {
|
|
385
|
+
// Override the permission property to return 'default' (user hasn't been asked) - with guard
|
|
386
|
+
safeDefineGetter(Notification, 'permission', () => 'default');
|
|
387
|
+
|
|
388
|
+
// Override requestPermission to behave normally
|
|
389
|
+
const originalRequestPermission = Notification.requestPermission;
|
|
390
|
+
Notification.requestPermission = function(callback) {
|
|
391
|
+
// Return a promise that resolves to 'default' or 'denied'
|
|
392
|
+
const result = Promise.resolve('default');
|
|
393
|
+
if (callback && typeof callback === 'function') {
|
|
394
|
+
result.then(callback);
|
|
395
|
+
}
|
|
396
|
+
return result;
|
|
397
|
+
};
|
|
398
|
+
}
|
|
399
|
+
};
|
|
400
|
+
|
|
401
|
+
// 13. Bluetooth API Spoofing (2024-2025)
|
|
402
|
+
const spoofBluetoothAPI = () => {
|
|
403
|
+
if ('bluetooth' in navigator) {
|
|
404
|
+
// Make bluetooth appear available but return empty results
|
|
405
|
+
const fakeBluetooth = {
|
|
406
|
+
getAvailability: () => Promise.resolve(true),
|
|
407
|
+
requestDevice: () => Promise.reject(new DOMException('User cancelled the requestDevice() chooser.', 'NotFoundError')),
|
|
408
|
+
getDevices: () => Promise.resolve([]),
|
|
409
|
+
addEventListener: () => {},
|
|
410
|
+
removeEventListener: () => {},
|
|
411
|
+
dispatchEvent: () => true
|
|
412
|
+
};
|
|
413
|
+
|
|
414
|
+
safeDefineGetter(navigator, 'bluetooth', () => fakeBluetooth);
|
|
415
|
+
}
|
|
416
|
+
};
|
|
417
|
+
|
|
418
|
+
// 14. USB API Spoofing (2024-2025)
|
|
419
|
+
const spoofUSBAPI = () => {
|
|
420
|
+
if ('usb' in navigator) {
|
|
421
|
+
const fakeUSB = {
|
|
422
|
+
getDevices: () => Promise.resolve([]),
|
|
423
|
+
requestDevice: () => Promise.reject(new DOMException('No device selected.', 'NotFoundError')),
|
|
424
|
+
addEventListener: () => {},
|
|
425
|
+
removeEventListener: () => {},
|
|
426
|
+
dispatchEvent: () => true,
|
|
427
|
+
onconnect: null,
|
|
428
|
+
ondisconnect: null
|
|
429
|
+
};
|
|
430
|
+
|
|
431
|
+
safeDefineGetter(navigator, 'usb', () => fakeUSB);
|
|
432
|
+
}
|
|
433
|
+
};
|
|
434
|
+
|
|
435
|
+
// 15. Serial API Spoofing (2024-2025)
|
|
436
|
+
const spoofSerialAPI = () => {
|
|
437
|
+
if ('serial' in navigator) {
|
|
438
|
+
const fakeSerial = {
|
|
439
|
+
getPorts: () => Promise.resolve([]),
|
|
440
|
+
requestPort: () => Promise.reject(new DOMException('No port selected.', 'NotFoundError')),
|
|
441
|
+
addEventListener: () => {},
|
|
442
|
+
removeEventListener: () => {},
|
|
443
|
+
dispatchEvent: () => true,
|
|
444
|
+
onconnect: null,
|
|
445
|
+
ondisconnect: null
|
|
446
|
+
};
|
|
447
|
+
|
|
448
|
+
safeDefineGetter(navigator, 'serial', () => fakeSerial);
|
|
449
|
+
}
|
|
450
|
+
};
|
|
451
|
+
|
|
452
|
+
// 16. Speech Synthesis Voices Spoofing (2024-2025)
|
|
453
|
+
const spoofSpeechSynthesis = () => {
|
|
454
|
+
if ('speechSynthesis' in window) {
|
|
455
|
+
const platform = navigator.platform || 'Win32';
|
|
456
|
+
|
|
457
|
+
// Platform-specific voices
|
|
458
|
+
const voiceConfigs = {
|
|
459
|
+
'Win32': [
|
|
460
|
+
{ name: 'Microsoft David - English (United States)', lang: 'en-US', localService: true, default: true },
|
|
461
|
+
{ name: 'Microsoft Zira - English (United States)', lang: 'en-US', localService: true, default: false },
|
|
462
|
+
{ name: 'Microsoft Mark - English (United States)', lang: 'en-US', localService: true, default: false },
|
|
463
|
+
{ name: 'Google US English', lang: 'en-US', localService: false, default: false },
|
|
464
|
+
{ name: 'Google UK English Female', lang: 'en-GB', localService: false, default: false },
|
|
465
|
+
{ name: 'Google UK English Male', lang: 'en-GB', localService: false, default: false }
|
|
466
|
+
],
|
|
467
|
+
'MacIntel': [
|
|
468
|
+
{ name: 'Alex', lang: 'en-US', localService: true, default: true },
|
|
469
|
+
{ name: 'Samantha', lang: 'en-US', localService: true, default: false },
|
|
470
|
+
{ name: 'Daniel', lang: 'en-GB', localService: true, default: false },
|
|
471
|
+
{ name: 'Google US English', lang: 'en-US', localService: false, default: false }
|
|
472
|
+
],
|
|
473
|
+
'Linux x86_64': [
|
|
474
|
+
{ name: 'Google US English', lang: 'en-US', localService: false, default: true },
|
|
475
|
+
{ name: 'Google UK English Female', lang: 'en-GB', localService: false, default: false }
|
|
476
|
+
]
|
|
477
|
+
};
|
|
478
|
+
|
|
479
|
+
const voices = voiceConfigs[platform] || voiceConfigs['Win32'];
|
|
480
|
+
|
|
481
|
+
// Create SpeechSynthesisVoice-like objects
|
|
482
|
+
const fakeVoices = voices.map(v => ({
|
|
483
|
+
voiceURI: v.name,
|
|
484
|
+
name: v.name,
|
|
485
|
+
lang: v.lang,
|
|
486
|
+
localService: v.localService,
|
|
487
|
+
default: v.default
|
|
488
|
+
}));
|
|
489
|
+
|
|
490
|
+
// Override getVoices
|
|
491
|
+
const originalGetVoices = speechSynthesis.getVoices;
|
|
492
|
+
speechSynthesis.getVoices = function() {
|
|
493
|
+
// Return our platform-appropriate voices
|
|
494
|
+
return fakeVoices;
|
|
495
|
+
};
|
|
496
|
+
|
|
497
|
+
// Trigger voiceschanged event after a delay to simulate loading
|
|
498
|
+
setTimeout(() => {
|
|
499
|
+
try {
|
|
500
|
+
const event = new Event('voiceschanged');
|
|
501
|
+
speechSynthesis.dispatchEvent(event);
|
|
502
|
+
} catch (e) {}
|
|
503
|
+
}, 100);
|
|
504
|
+
}
|
|
505
|
+
};
|
|
506
|
+
|
|
507
|
+
// 17. Credentials API Spoofing (2024-2025)
|
|
508
|
+
const spoofCredentialsAPI = () => {
|
|
509
|
+
if ('credentials' in navigator) {
|
|
510
|
+
const originalGet = navigator.credentials.get;
|
|
511
|
+
const originalCreate = navigator.credentials.create;
|
|
512
|
+
const originalStore = navigator.credentials.store;
|
|
513
|
+
|
|
514
|
+
// Make credentials API behave like a normal browser
|
|
515
|
+
navigator.credentials.get = function(options) {
|
|
516
|
+
// For publicKey (WebAuthn), reject like a normal user cancellation
|
|
517
|
+
if (options && options.publicKey) {
|
|
518
|
+
return Promise.reject(new DOMException(
|
|
519
|
+
'The operation either timed out or was not allowed.',
|
|
520
|
+
'NotAllowedError'
|
|
521
|
+
));
|
|
522
|
+
}
|
|
523
|
+
// For password credentials, return null (no saved credentials)
|
|
524
|
+
return Promise.resolve(null);
|
|
525
|
+
};
|
|
526
|
+
|
|
527
|
+
navigator.credentials.create = function(options) {
|
|
528
|
+
if (options && options.publicKey) {
|
|
529
|
+
return Promise.reject(new DOMException(
|
|
530
|
+
'The operation either timed out or was not allowed.',
|
|
531
|
+
'NotAllowedError'
|
|
532
|
+
));
|
|
533
|
+
}
|
|
534
|
+
return originalCreate.apply(this, arguments);
|
|
535
|
+
};
|
|
536
|
+
|
|
537
|
+
navigator.credentials.store = function(credential) {
|
|
538
|
+
// Accept but don't actually store
|
|
539
|
+
return Promise.resolve(credential);
|
|
540
|
+
};
|
|
541
|
+
}
|
|
542
|
+
};
|
|
543
|
+
|
|
544
|
+
// 18. HID API Spoofing (2024-2025)
|
|
545
|
+
const spoofHIDAPI = () => {
|
|
546
|
+
if ('hid' in navigator) {
|
|
547
|
+
const fakeHID = {
|
|
548
|
+
getDevices: () => Promise.resolve([]),
|
|
549
|
+
requestDevice: () => Promise.reject(new DOMException('No device selected.', 'NotFoundError')),
|
|
550
|
+
addEventListener: () => {},
|
|
551
|
+
removeEventListener: () => {},
|
|
552
|
+
dispatchEvent: () => true,
|
|
553
|
+
onconnect: null,
|
|
554
|
+
ondisconnect: null
|
|
555
|
+
};
|
|
556
|
+
|
|
557
|
+
safeDefineGetter(navigator, 'hid', () => fakeHID);
|
|
558
|
+
}
|
|
559
|
+
};
|
|
560
|
+
|
|
561
|
+
// 19. Gamepad API Spoofing (2024-2025)
|
|
562
|
+
const spoofGamepadAPI = () => {
|
|
563
|
+
// Return empty array for getGamepads
|
|
564
|
+
const originalGetGamepads = navigator.getGamepads;
|
|
565
|
+
if (originalGetGamepads) {
|
|
566
|
+
navigator.getGamepads = function() {
|
|
567
|
+
// Return empty array like no gamepads connected
|
|
568
|
+
return [];
|
|
569
|
+
};
|
|
570
|
+
}
|
|
571
|
+
};
|
|
572
|
+
|
|
573
|
+
// 20. Clipboard API Protection (2024-2025)
|
|
574
|
+
const spoofClipboardAPI = () => {
|
|
575
|
+
if (navigator.clipboard) {
|
|
576
|
+
const originalReadText = navigator.clipboard.readText;
|
|
577
|
+
const originalRead = navigator.clipboard.read;
|
|
578
|
+
|
|
579
|
+
// Make clipboard read behave like permission not granted
|
|
580
|
+
navigator.clipboard.readText = function() {
|
|
581
|
+
return Promise.reject(new DOMException(
|
|
582
|
+
'Read permission denied.',
|
|
583
|
+
'NotAllowedError'
|
|
584
|
+
));
|
|
585
|
+
};
|
|
586
|
+
|
|
587
|
+
navigator.clipboard.read = function() {
|
|
588
|
+
return Promise.reject(new DOMException(
|
|
589
|
+
'Read permission denied.',
|
|
590
|
+
'NotAllowedError'
|
|
591
|
+
));
|
|
592
|
+
};
|
|
593
|
+
}
|
|
594
|
+
};
|
|
595
|
+
|
|
596
|
+
// 21. Do Not Track Spoofing (2024-2025)
|
|
597
|
+
const spoofDoNotTrack = () => {
|
|
598
|
+
// Most real users have DNT disabled or not set
|
|
599
|
+
safeDefineGetter(navigator, 'doNotTrack', () => null);
|
|
600
|
+
};
|
|
601
|
+
|
|
602
|
+
// 22. Global Privacy Control Spoofing (2024-2025)
|
|
603
|
+
const spoofGlobalPrivacyControl = () => {
|
|
604
|
+
// Most users don't have GPC enabled
|
|
605
|
+
safeDefineGetter(navigator, 'globalPrivacyControl', () => false);
|
|
606
|
+
};
|
|
607
|
+
|
|
608
|
+
// 23. Keyboard API Spoofing (2024-2025) - DataDome checks getLayoutMap()
|
|
609
|
+
const spoofKeyboardAPI = () => {
|
|
610
|
+
// Full US QWERTY keyboard layout map
|
|
611
|
+
const qwertyLayoutMap = new Map([
|
|
612
|
+
['Backquote', '\`'], ['Digit1', '1'], ['Digit2', '2'], ['Digit3', '3'],
|
|
613
|
+
['Digit4', '4'], ['Digit5', '5'], ['Digit6', '6'], ['Digit7', '7'],
|
|
614
|
+
['Digit8', '8'], ['Digit9', '9'], ['Digit0', '0'], ['Minus', '-'],
|
|
615
|
+
['Equal', '='], ['Backspace', ''], ['Tab', ''], ['KeyQ', 'q'],
|
|
616
|
+
['KeyW', 'w'], ['KeyE', 'e'], ['KeyR', 'r'], ['KeyT', 't'],
|
|
617
|
+
['KeyY', 'y'], ['KeyU', 'u'], ['KeyI', 'i'], ['KeyO', 'o'],
|
|
618
|
+
['KeyP', 'p'], ['BracketLeft', '['], ['BracketRight', ']'],
|
|
619
|
+
['Backslash', '\\\\'], ['CapsLock', ''], ['KeyA', 'a'], ['KeyS', 's'],
|
|
620
|
+
['KeyD', 'd'], ['KeyF', 'f'], ['KeyG', 'g'], ['KeyH', 'h'],
|
|
621
|
+
['KeyJ', 'j'], ['KeyK', 'k'], ['KeyL', 'l'], ['Semicolon', ';'],
|
|
622
|
+
['Quote', "'"], ['Enter', ''], ['ShiftLeft', ''], ['KeyZ', 'z'],
|
|
623
|
+
['KeyX', 'x'], ['KeyC', 'c'], ['KeyV', 'v'], ['KeyB', 'b'],
|
|
624
|
+
['KeyN', 'n'], ['KeyM', 'm'], ['Comma', ','], ['Period', '.'],
|
|
625
|
+
['Slash', '/'], ['ShiftRight', ''], ['ControlLeft', ''],
|
|
626
|
+
['AltLeft', ''], ['Space', ' '], ['AltRight', ''], ['ControlRight', ''],
|
|
627
|
+
['ArrowLeft', ''], ['ArrowUp', ''], ['ArrowDown', ''], ['ArrowRight', ''],
|
|
628
|
+
['NumpadDivide', '/'], ['NumpadMultiply', '*'], ['NumpadSubtract', '-'],
|
|
629
|
+
['Numpad7', '7'], ['Numpad8', '8'], ['Numpad9', '9'], ['NumpadAdd', '+'],
|
|
630
|
+
['Numpad4', '4'], ['Numpad5', '5'], ['Numpad6', '6'], ['Numpad1', '1'],
|
|
631
|
+
['Numpad2', '2'], ['Numpad3', '3'], ['NumpadEnter', ''], ['Numpad0', '0'],
|
|
632
|
+
['NumpadDecimal', '.']
|
|
633
|
+
]);
|
|
634
|
+
|
|
635
|
+
// Create a KeyboardLayoutMap-like object
|
|
636
|
+
const createLayoutMap = () => {
|
|
637
|
+
const map = {
|
|
638
|
+
entries: function* () { yield* qwertyLayoutMap.entries(); },
|
|
639
|
+
keys: function* () { yield* qwertyLayoutMap.keys(); },
|
|
640
|
+
values: function* () { yield* qwertyLayoutMap.values(); },
|
|
641
|
+
forEach: (callback) => qwertyLayoutMap.forEach(callback),
|
|
642
|
+
get: (key) => qwertyLayoutMap.get(key),
|
|
643
|
+
has: (key) => qwertyLayoutMap.has(key),
|
|
644
|
+
size: qwertyLayoutMap.size,
|
|
645
|
+
[Symbol.iterator]: function* () { yield* qwertyLayoutMap.entries(); }
|
|
646
|
+
};
|
|
647
|
+
|
|
648
|
+
// Make it look like a KeyboardLayoutMap
|
|
649
|
+
Object.defineProperty(map, Symbol.toStringTag, {
|
|
650
|
+
value: 'KeyboardLayoutMap',
|
|
651
|
+
configurable: true
|
|
652
|
+
});
|
|
653
|
+
|
|
654
|
+
return map;
|
|
655
|
+
};
|
|
656
|
+
|
|
657
|
+
// Cache the layout map promise for consistency (DataDome may check promise identity)
|
|
658
|
+
let cachedLayoutMapPromise = null;
|
|
659
|
+
|
|
660
|
+
const fakeKeyboard = {
|
|
661
|
+
getLayoutMap: function() {
|
|
662
|
+
if (!cachedLayoutMapPromise) {
|
|
663
|
+
cachedLayoutMapPromise = Promise.resolve(createLayoutMap());
|
|
664
|
+
}
|
|
665
|
+
return cachedLayoutMapPromise;
|
|
666
|
+
},
|
|
667
|
+
lock: function() { return Promise.resolve(); },
|
|
668
|
+
unlock: function() {}
|
|
669
|
+
};
|
|
670
|
+
|
|
671
|
+
// Register with stealth utils for centralized toString masking
|
|
672
|
+
const _s = typeof __stealth !== 'undefined' ? __stealth : {};
|
|
673
|
+
if (_s.utils) {
|
|
674
|
+
_s.utils.registerNativeFunction(fakeKeyboard.getLayoutMap, 'getLayoutMap');
|
|
675
|
+
_s.utils.registerNativeFunction(fakeKeyboard.lock, 'lock');
|
|
676
|
+
_s.utils.registerNativeFunction(fakeKeyboard.unlock, 'unlock');
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
safeDefineGetter(navigator, 'keyboard', () => fakeKeyboard);
|
|
680
|
+
};
|
|
681
|
+
|
|
682
|
+
// 24. MediaDevices API Spoofing
|
|
683
|
+
// NOTE: Removed - webrtc-spoofing.ts handles enumerateDevices with
|
|
684
|
+
// realistic hex device IDs. Having two overrides creates detectable
|
|
685
|
+
// double-wrapping and inconsistent device ID formats.
|
|
686
|
+
const spoofMediaDevicesAPI = () => {};
|
|
687
|
+
|
|
688
|
+
// 25. ServiceWorker API Protection (2024-2025) - DataDome checks ready/register
|
|
689
|
+
const spoofServiceWorkerAPI = () => {
|
|
690
|
+
if (!navigator.serviceWorker) return;
|
|
691
|
+
|
|
692
|
+
const sw = navigator.serviceWorker;
|
|
693
|
+
|
|
694
|
+
// Wrap register to work normally but look native
|
|
695
|
+
const originalRegister = sw.register;
|
|
696
|
+
if (originalRegister) {
|
|
697
|
+
sw.register = function(scriptURL, options) {
|
|
698
|
+
return originalRegister.apply(this, arguments);
|
|
699
|
+
};
|
|
700
|
+
|
|
701
|
+
const _s2 = typeof __stealth !== 'undefined' ? __stealth : {};
|
|
702
|
+
if (_s2.utils) _s2.utils.registerNativeFunction(sw.register, 'register');
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
// Ensure ready returns a proper promise
|
|
706
|
+
// Note: ready is a getter, we shouldn't override it as it's already a promise
|
|
707
|
+
};
|
|
708
|
+
|
|
709
|
+
// 26. Undefined Navigator Properties (2024-2025) - DataDome checks these
|
|
710
|
+
const spoofUndefinedNavigatorProps = () => {
|
|
711
|
+
// navigator.brave - Only present in Brave browser, must be undefined for Chrome
|
|
712
|
+
safeDefineGetter(navigator, 'brave', () => undefined);
|
|
713
|
+
|
|
714
|
+
// navigator.buildID - Firefox-specific, undefined for Chrome
|
|
715
|
+
safeDefineGetter(navigator, 'buildID', () => undefined);
|
|
716
|
+
|
|
717
|
+
// navigator.contacts - Not widely supported, should be undefined
|
|
718
|
+
safeDefineGetter(navigator, 'contacts', () => undefined);
|
|
719
|
+
|
|
720
|
+
// navigator.cookieDeprecationLabel - Chrome 120+ API, undefined in most cases
|
|
721
|
+
safeDefineGetter(navigator, 'cookieDeprecationLabel', () => undefined);
|
|
722
|
+
|
|
723
|
+
// navigator.loadPurpose - Should be undefined
|
|
724
|
+
safeDefineGetter(navigator, 'loadPurpose', () => undefined);
|
|
725
|
+
};
|
|
726
|
+
|
|
727
|
+
// 27. Worker Constructor Protection - Prevent fingerprint leakage in worker contexts
|
|
728
|
+
const protectWorkerConstructor = () => {
|
|
729
|
+
if (typeof Worker === 'undefined') return;
|
|
730
|
+
|
|
731
|
+
// Cache fingerprint values to inject into workers
|
|
732
|
+
const fingerprintValues = {
|
|
733
|
+
userAgent: navigator.userAgent,
|
|
734
|
+
platform: navigator.platform,
|
|
735
|
+
vendor: navigator.vendor || '',
|
|
736
|
+
language: navigator.language,
|
|
737
|
+
languages: JSON.stringify(navigator.languages || ['en-US']),
|
|
738
|
+
hardwareConcurrency: navigator.hardwareConcurrency || 8,
|
|
739
|
+
deviceMemory: navigator.deviceMemory || 8,
|
|
740
|
+
};
|
|
741
|
+
|
|
742
|
+
// Create the worker override script
|
|
743
|
+
const workerOverrideScript = \`
|
|
744
|
+
// Worker fingerprint consistency overrides
|
|
745
|
+
(function() {
|
|
746
|
+
const fingerprintValues = \${JSON.stringify(fingerprintValues)};
|
|
747
|
+
|
|
748
|
+
// Override navigator properties in worker context
|
|
749
|
+
if (typeof WorkerNavigator !== 'undefined' && self.navigator) {
|
|
750
|
+
try {
|
|
751
|
+
Object.defineProperty(self.navigator, 'userAgent', { get: () => fingerprintValues.userAgent });
|
|
752
|
+
Object.defineProperty(self.navigator, 'platform', { get: () => fingerprintValues.platform });
|
|
753
|
+
Object.defineProperty(self.navigator, 'vendor', { get: () => fingerprintValues.vendor });
|
|
754
|
+
Object.defineProperty(self.navigator, 'language', { get: () => fingerprintValues.language });
|
|
755
|
+
Object.defineProperty(self.navigator, 'languages', { get: () => JSON.parse(fingerprintValues.languages) });
|
|
756
|
+
Object.defineProperty(self.navigator, 'hardwareConcurrency', { get: () => fingerprintValues.hardwareConcurrency });
|
|
757
|
+
Object.defineProperty(self.navigator, 'deviceMemory', { get: () => fingerprintValues.deviceMemory });
|
|
758
|
+
} catch (e) {}
|
|
759
|
+
}
|
|
760
|
+
})();
|
|
761
|
+
\`;
|
|
762
|
+
|
|
763
|
+
const OriginalWorker = Worker;
|
|
764
|
+
|
|
765
|
+
window.Worker = function(scriptURL, options) {
|
|
766
|
+
// For blob URLs, we can try to prepend our overrides
|
|
767
|
+
if (typeof scriptURL === 'string' && scriptURL.startsWith('blob:')) {
|
|
768
|
+
// Can't modify blob URLs easily, but the worker will still get our overrides
|
|
769
|
+
// if it was created from same-origin code
|
|
770
|
+
}
|
|
771
|
+
|
|
772
|
+
// Create the worker normally
|
|
773
|
+
const worker = new OriginalWorker(scriptURL, options);
|
|
774
|
+
|
|
775
|
+
// Intercept postMessage to detect fingerprint requests
|
|
776
|
+
const originalPostMessage = worker.postMessage.bind(worker);
|
|
777
|
+
worker.postMessage = function(message, transfer) {
|
|
778
|
+
return originalPostMessage(message, transfer);
|
|
779
|
+
};
|
|
780
|
+
|
|
781
|
+
return worker;
|
|
782
|
+
};
|
|
783
|
+
|
|
784
|
+
// Copy static properties
|
|
785
|
+
window.Worker.prototype = OriginalWorker.prototype;
|
|
786
|
+
|
|
787
|
+
Object.defineProperty(window.Worker, 'name', { value: 'Worker', configurable: true });
|
|
788
|
+
const _s3 = typeof __stealth !== 'undefined' ? __stealth : {};
|
|
789
|
+
if (_s3.utils) _s3.utils.registerNativeFunction(window.Worker, 'Worker');
|
|
790
|
+
};
|
|
791
|
+
|
|
792
|
+
// 28. SharedWorker Protection - Similar to Worker
|
|
793
|
+
const protectSharedWorkerConstructor = () => {
|
|
794
|
+
if (typeof SharedWorker === 'undefined') return;
|
|
795
|
+
|
|
796
|
+
const OriginalSharedWorker = SharedWorker;
|
|
797
|
+
|
|
798
|
+
window.SharedWorker = function(scriptURL, options) {
|
|
799
|
+
const worker = new OriginalSharedWorker(scriptURL, options);
|
|
800
|
+
return worker;
|
|
801
|
+
};
|
|
802
|
+
|
|
803
|
+
// Copy prototype
|
|
804
|
+
window.SharedWorker.prototype = OriginalSharedWorker.prototype;
|
|
805
|
+
|
|
806
|
+
Object.defineProperty(window.SharedWorker, 'name', { value: 'SharedWorker', configurable: true });
|
|
807
|
+
const _s4 = typeof __stealth !== 'undefined' ? __stealth : {};
|
|
808
|
+
if (_s4.utils) _s4.utils.registerNativeFunction(window.SharedWorker, 'SharedWorker');
|
|
809
|
+
};
|
|
810
|
+
|
|
811
|
+
// 29. PostMessage Fingerprint Protection - Prevent cross-context fingerprint detection
|
|
812
|
+
const protectPostMessage = () => {
|
|
813
|
+
// Cache consistent fingerprint values
|
|
814
|
+
const consistentFingerprint = {
|
|
815
|
+
navigator: {
|
|
816
|
+
userAgent: navigator.userAgent,
|
|
817
|
+
platform: navigator.platform,
|
|
818
|
+
vendor: navigator.vendor,
|
|
819
|
+
language: navigator.language,
|
|
820
|
+
languages: navigator.languages ? [...navigator.languages] : ['en-US'],
|
|
821
|
+
hardwareConcurrency: navigator.hardwareConcurrency,
|
|
822
|
+
deviceMemory: navigator.deviceMemory,
|
|
823
|
+
maxTouchPoints: navigator.maxTouchPoints,
|
|
824
|
+
webdriver: undefined,
|
|
825
|
+
},
|
|
826
|
+
screen: {
|
|
827
|
+
width: screen.width,
|
|
828
|
+
height: screen.height,
|
|
829
|
+
availWidth: screen.availWidth,
|
|
830
|
+
availHeight: screen.availHeight,
|
|
831
|
+
colorDepth: screen.colorDepth,
|
|
832
|
+
pixelDepth: screen.pixelDepth,
|
|
833
|
+
}
|
|
834
|
+
};
|
|
835
|
+
|
|
836
|
+
// Listen for fingerprint requests from iframes/workers
|
|
837
|
+
window.addEventListener('message', function(event) {
|
|
838
|
+
// Detect common fingerprint request patterns
|
|
839
|
+
if (event.data && typeof event.data === 'object') {
|
|
840
|
+
// If message looks like a fingerprint request, respond with consistent values
|
|
841
|
+
if (event.data.type === 'fingerprintRequest' ||
|
|
842
|
+
event.data.action === 'getFingerprint' ||
|
|
843
|
+
event.data.cmd === 'getNavigator') {
|
|
844
|
+
|
|
845
|
+
if (event.source) {
|
|
846
|
+
try {
|
|
847
|
+
event.source.postMessage({
|
|
848
|
+
type: 'fingerprintResponse',
|
|
849
|
+
data: consistentFingerprint
|
|
850
|
+
}, event.origin || '*');
|
|
851
|
+
} catch (e) {}
|
|
852
|
+
}
|
|
853
|
+
}
|
|
854
|
+
}
|
|
855
|
+
}, false);
|
|
856
|
+
|
|
857
|
+
// Wrap postMessage to ensure consistent data
|
|
858
|
+
const originalPostMessage = window.postMessage.bind(window);
|
|
859
|
+
window.postMessage = function(message, targetOrigin, transfer) {
|
|
860
|
+
return originalPostMessage(message, targetOrigin, transfer);
|
|
861
|
+
};
|
|
862
|
+
|
|
863
|
+
const _s5 = typeof __stealth !== 'undefined' ? __stealth : {};
|
|
864
|
+
if (_s5.utils) _s5.utils.registerNativeFunction(window.postMessage, 'postMessage');
|
|
865
|
+
};
|
|
866
|
+
|
|
867
|
+
// Initialize all protections
|
|
868
|
+
const DEBUG_PREFIX = '[CDP-FP-DEBUG]';
|
|
869
|
+
const ERROR_PREFIX = '[CDP-FP-ERROR]';
|
|
870
|
+
|
|
871
|
+
console.log(DEBUG_PREFIX, 'Starting stealth protection injection...');
|
|
872
|
+
|
|
873
|
+
const applyProtection = (name, fn) => {
|
|
874
|
+
try {
|
|
875
|
+
fn();
|
|
876
|
+
console.log(DEBUG_PREFIX, \`✓ Applied \${name}\`);
|
|
877
|
+
return true;
|
|
878
|
+
} catch (e) {
|
|
879
|
+
console.error(ERROR_PREFIX, \`✗ Failed to apply \${name}:\`, e);
|
|
880
|
+
throw e; // Rethrow to make errors visible
|
|
881
|
+
}
|
|
882
|
+
};
|
|
883
|
+
|
|
884
|
+
try {
|
|
885
|
+
applyProtection('Error Stack Hiding', hideErrorStack);
|
|
886
|
+
applyProtection('Console Patching', patchConsole);
|
|
887
|
+
applyProtection('Automation Flags Removal', removeAutomationFlags);
|
|
888
|
+
applyProtection('Runtime.enable Detection Prevention', preventRuntimeEnableDetection);
|
|
889
|
+
applyProtection('Plugin Spoofing', spoofPlugins);
|
|
890
|
+
applyProtection('Permissions API Spoofing', spoofPermissions);
|
|
891
|
+
applyProtection('Battery API Spoofing', spoofBatteryAPI);
|
|
892
|
+
applyProtection('Connection API Spoofing', spoofConnectionAPI);
|
|
893
|
+
applyProtection('Chrome Runtime API Spoofing', spoofChromeRuntime);
|
|
894
|
+
// New 2024-2025 protections
|
|
895
|
+
applyProtection('Device Memory Spoofing', spoofDeviceMemory);
|
|
896
|
+
applyProtection('PDF Viewer Enabled Spoofing', spoofPdfViewerEnabled);
|
|
897
|
+
applyProtection('Notification Permission Spoofing', spoofNotificationPermission);
|
|
898
|
+
applyProtection('Bluetooth API Spoofing', spoofBluetoothAPI);
|
|
899
|
+
applyProtection('USB API Spoofing', spoofUSBAPI);
|
|
900
|
+
applyProtection('Serial API Spoofing', spoofSerialAPI);
|
|
901
|
+
applyProtection('Speech Synthesis Spoofing', spoofSpeechSynthesis);
|
|
902
|
+
applyProtection('Credentials API Spoofing', spoofCredentialsAPI);
|
|
903
|
+
applyProtection('HID API Spoofing', spoofHIDAPI);
|
|
904
|
+
applyProtection('Gamepad API Spoofing', spoofGamepadAPI);
|
|
905
|
+
applyProtection('Clipboard API Protection', spoofClipboardAPI);
|
|
906
|
+
applyProtection('Do Not Track Spoofing', spoofDoNotTrack);
|
|
907
|
+
applyProtection('Global Privacy Control Spoofing', spoofGlobalPrivacyControl);
|
|
908
|
+
// DataDome-specific protections
|
|
909
|
+
applyProtection('Keyboard API Spoofing', spoofKeyboardAPI);
|
|
910
|
+
applyProtection('MediaDevices API Spoofing', spoofMediaDevicesAPI);
|
|
911
|
+
applyProtection('ServiceWorker API Protection', spoofServiceWorkerAPI);
|
|
912
|
+
applyProtection('Undefined Navigator Props', spoofUndefinedNavigatorProps);
|
|
913
|
+
// Cross-context consistency protections
|
|
914
|
+
applyProtection('Worker Constructor Protection', protectWorkerConstructor);
|
|
915
|
+
applyProtection('SharedWorker Protection', protectSharedWorkerConstructor);
|
|
916
|
+
applyProtection('PostMessage Protection', protectPostMessage);
|
|
917
|
+
|
|
918
|
+
console.log(DEBUG_PREFIX, '✓ All stealth protections applied successfully');
|
|
919
|
+
} catch (e) {
|
|
920
|
+
console.error(ERROR_PREFIX, '✗ Failed to apply stealth protections:', e);
|
|
921
|
+
throw e; // Rethrow to make errors visible
|
|
922
|
+
}
|
|
923
|
+
})();`;
|
|
924
|
+
};
|
|
925
|
+
//# sourceMappingURL=stealth-script.js.map
|