stealth: keep the Chrome 145 identity consistent across TLS, JS, and WebGL
Stealth mode forced a Linux navigator UA and platform but reported Windows in userAgentData.getHighEntropyValues and served Windows Direct3D11 WebGL renderers, a combination no real Linux Chrome ever produces and that cross-layer fingerprint checks flag. Present one consistent Windows Chrome 145 identity instead: the wreq emulation uses Platform::Windows, and the navigator surfaces read the UA and platform from shared constants so the HTTP User-Agent header, sec-ch-ua-platform, navigator.userAgent, and userAgentData all agree. userAgentData brands are now derived from the Chrome major version via Chromium's GREASE algorithm rather than a single hardcoded token, and a Linux WebGL renderer pool is added so a Linux UA can never report a Direct3D11 renderer.
This commit is contained in:
1 parent
dc780d77e4
commit
4309935abd
4 files changed
+74
-39
No files matched your search
Vendored
+52
-33
@@ -154,7 +154,9 @@ function _fpNoise(x, y, channel) {
|
||||
var _fpCache = null;
|
||||
function _getFp() {
|
||||
if (_fpCache) return _fpCache;
|
||||
const isMac = (globalThis.__obscura_ua_platform || 'Windows') === 'macOS';
|
||||
const _uaPlat = globalThis.__obscura_ua_platform || 'Windows';
|
||||
const isMac = _uaPlat === 'macOS';
|
||||
const isLinux = _uaPlat === 'Linux';
|
||||
const gpuPool = isMac ? [
|
||||
'ANGLE (Apple, ANGLE Metal Renderer: Apple M1, Unspecified Version)',
|
||||
'ANGLE (Apple, ANGLE Metal Renderer: Apple M1 Pro, Unspecified Version)',
|
||||
@@ -162,6 +164,14 @@ function _getFp() {
|
||||
'ANGLE (Apple, ANGLE Metal Renderer: Apple M2 Pro, Unspecified Version)',
|
||||
'ANGLE (Apple, ANGLE Metal Renderer: Apple M3, Unspecified Version)',
|
||||
'ANGLE (Intel Inc., ANGLE Metal Renderer: Intel(R) Iris(TM) Plus Graphics, Unspecified Version)',
|
||||
] : isLinux ? [
|
||||
'ANGLE (Intel, Mesa Intel(R) UHD Graphics 630 (CFL GT2), OpenGL 4.6)',
|
||||
'ANGLE (Intel, Mesa Intel(R) Iris(R) Xe Graphics (TGL GT2), OpenGL 4.6)',
|
||||
'ANGLE (Intel, Mesa Intel(R) UHD Graphics 770 (RPL-S), OpenGL 4.6)',
|
||||
'ANGLE (AMD, AMD Radeon RX 580 (polaris10, LLVM 15.0.7, DRM 3.54, LLVM 15.0.7), OpenGL 4.6)',
|
||||
'ANGLE (AMD, AMD Radeon RX 6700 XT (navi22, LLVM 16.0.6, DRM 3.54, LLVM 16.0.6), OpenGL 4.6)',
|
||||
'ANGLE (NVIDIA, NVIDIA GeForce RTX 3060 OpenGL 4.6)',
|
||||
'ANGLE (NVIDIA, NVIDIA GeForce RTX 4070 OpenGL 4.6)',
|
||||
] : [
|
||||
'ANGLE (NVIDIA, NVIDIA GeForce RTX 3060 Direct3D11 vs_5_0 ps_5_0, D3D11)',
|
||||
'ANGLE (NVIDIA, NVIDIA GeForce GTX 1660 SUPER Direct3D11 vs_5_0 ps_5_0, D3D11)',
|
||||
@@ -180,6 +190,10 @@ function _getFp() {
|
||||
'Google Inc. (Apple)','Google Inc. (Apple)','Google Inc. (Apple)',
|
||||
'Google Inc. (Apple)','Google Inc. (Apple)',
|
||||
'Google Inc. (Intel Inc.)',
|
||||
] : isLinux ? [
|
||||
'Google Inc. (Intel)','Google Inc. (Intel)','Google Inc. (Intel)',
|
||||
'Google Inc. (AMD)','Google Inc. (AMD)',
|
||||
'Google Inc. (NVIDIA)','Google Inc. (NVIDIA)',
|
||||
] : [
|
||||
'Google Inc. (NVIDIA)','Google Inc. (NVIDIA)','Google Inc. (NVIDIA)',
|
||||
'Google Inc. (Intel)','Google Inc. (Intel)',
|
||||
@@ -2612,8 +2626,35 @@ globalThis.NetworkInformation = NetworkInformation;
|
||||
|
||||
globalThis.ContentIndex = class ContentIndex {};
|
||||
|
||||
function _chromeMajor() {
|
||||
var m = (globalThis.__obscura_ua || '').match(/Chrome\/(\d+)/);
|
||||
return m ? (m[1] | 0) : 145;
|
||||
}
|
||||
// Chromium derives the sec-ch-ua GREASE brand, version, and brand order
|
||||
// deterministically from the Chrome major version
|
||||
// (components/embedder_support/user_agent_utils.cc). Replicating it keeps
|
||||
// sec-ch-ua and userAgentData exact for every profile version rather than
|
||||
// hardcoding one static token.
|
||||
var _GREASE_CHARS = [' ', '(', ':', '-', '.', '/', ')', ';', '=', '?', '_'];
|
||||
var _GREASE_VER = ['8', '99', '24'];
|
||||
var _BRAND_PERMS = [[0,1,2],[0,2,1],[1,0,2],[1,2,0],[2,0,1],[2,1,0]];
|
||||
function _uaBrands() {
|
||||
var seed = _chromeMajor();
|
||||
var grease = {
|
||||
brand: 'Not' + _GREASE_CHARS[seed % 11] + 'A' + _GREASE_CHARS[(seed + 1) % 11] + 'Brand',
|
||||
version: _GREASE_VER[seed % 3],
|
||||
};
|
||||
var ordered = [
|
||||
grease,
|
||||
{brand: 'Chromium', version: String(seed)},
|
||||
{brand: 'Google Chrome', version: String(seed)},
|
||||
];
|
||||
var p = _BRAND_PERMS[seed % 6];
|
||||
return [ordered[p[0]], ordered[p[1]], ordered[p[2]]];
|
||||
}
|
||||
|
||||
globalThis.navigator = {
|
||||
get userAgent() { return globalThis.__obscura_ua || "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.0.0 Safari/537.36"; },
|
||||
get userAgent() { return globalThis.__obscura_ua || "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.0.0 Safari/537.36"; },
|
||||
get appVersion() { return this.userAgent.replace('Mozilla/', ''); },
|
||||
language: "en-US", languages: ["en-US","en"], get platform() { return globalThis.__obscura_platform || "Win32"; },
|
||||
onLine: true, cookieEnabled: true, hardwareConcurrency: 8,
|
||||
@@ -2643,24 +2684,22 @@ globalThis.navigator = {
|
||||
return m;
|
||||
},
|
||||
userAgentData: {
|
||||
brands: [
|
||||
{brand: "Google Chrome", version: "145"},
|
||||
{brand: "Chromium", version: "145"},
|
||||
{brand: "Not;A=Brand", version: "24"},
|
||||
],
|
||||
mobile: false,
|
||||
get brands() { return _uaBrands(); },
|
||||
get platform() { return globalThis.__obscura_ua_platform || "Windows"; },
|
||||
getHighEntropyValues(hints) {
|
||||
var brands = _uaBrands();
|
||||
return Promise.resolve({
|
||||
architecture: "x86",
|
||||
bitness: "64",
|
||||
brands: [{brand:"Google Chrome",version:"145"},{brand:"Chromium",version:"145"},{brand:"Not;A=Brand",version:"24"}],
|
||||
fullVersionList: [{brand:"Google Chrome",version:"145.0.0.0"},{brand:"Chromium",version:"145.0.0.0"},{brand:"Not;A=Brand",version:"24.0.0.0"}],
|
||||
brands: brands,
|
||||
fullVersionList: brands.map(function(b) { return {brand: b.brand, version: b.version + ".0.0.0"}; }),
|
||||
mobile: false,
|
||||
model: "",
|
||||
platform: globalThis.__obscura_ua_platform || "Windows",
|
||||
platformVersion: globalThis.__obscura_ua_platform_version || "15.0.0",
|
||||
uaFullVersion: "145.0.0.0",
|
||||
uaFullVersion: _chromeMajor() + ".0.0.0",
|
||||
wow64: false,
|
||||
});
|
||||
},
|
||||
toJSON() { return {brands:this.brands,mobile:this.mobile,platform:this.platform}; },
|
||||
@@ -6722,29 +6761,9 @@ globalThis.__obscura_init = function() {
|
||||
};
|
||||
globalThis.Notification.permission = "default";
|
||||
|
||||
if (globalThis.__obscura_stealth) {
|
||||
var _stealthBrands = [
|
||||
{brand: "Not:A-Brand", version: "99"},
|
||||
{brand: "Google Chrome", version: "145"},
|
||||
{brand: "Chromium", version: "145"},
|
||||
];
|
||||
globalThis.navigator.userAgentData.brands = _stealthBrands;
|
||||
globalThis.navigator.userAgentData.getHighEntropyValues = function(hints) {
|
||||
return Promise.resolve({
|
||||
architecture: "x86", bitness: "64",
|
||||
brands: _stealthBrands,
|
||||
fullVersionList: [
|
||||
{brand:"Not:A-Brand",version:"99.0.0.0"},
|
||||
{brand:"Google Chrome",version:"145.0.0.0"},
|
||||
{brand:"Chromium",version:"145.0.0.0"},
|
||||
],
|
||||
mobile: false, model: "",
|
||||
platform: "Windows",
|
||||
platformVersion: "10.0.0",
|
||||
uaFullVersion: "145.0.0.0",
|
||||
});
|
||||
};
|
||||
}
|
||||
// userAgentData brands and getHighEntropyValues now derive the Chrome
|
||||
// version from navigator.userAgent and read the platform from the page
|
||||
// globals, so every stealth surface agrees without a per-mode override.
|
||||
|
||||
// Hide internals (_*, obscura, Obscura). The set of keys is static at
|
||||
// snapshot-build time, so we precompute it ONCE below (after this
|
||||
|
||||
Reference in new issue
Block a user