1 पॉइंट द्वारा GN⁺ 4 시간 전 | 1 टिप्पणियां | WhatsApp पर शेयर करें
  • Chrome 148 से V8 का Math.tanh बिल्ट-इन fdlibm के बजाय host के std::tanh को call करने लगा है, जिससे एक ही input पर भी Linux के glibc, macOS के libsystem_m और Windows के UCRT में अलग-अलग last bit लौटते हैं
  • Math.tanh(0.8) Linux पर 0.6640367702678491, macOS पर 0.664036770267849, और Windows पर 0.6640367702678489 होता है, इसलिए एक ही call से तीनों OS अलग किए जा सकते हैं; अगर result User-Agent द्वारा बताए गए OS से अलग हो, तो spoofing पकड़ी जाती है
  • हर engine में leakage path अलग है: V8 के Math.* में केवल tanh host math library का इस्तेमाल करता है, लेकिन Blink की पूरी CSS trigonometric functions और Web Audio की कुछ operations भी OS-specific libraries से गुजरती हैं
  • values को मनमाने ढंग से बदलने पर वे किसी भी असली OS से match नहीं करतीं और determinism भी टूटता है; इसलिए target library के coefficients, tables, range reduction और FMA behavior को bit-by-bit reproduce करना होगा या original UCRT code को सीधे map करना होगा
  • Scrapfly हर release में 871,000 inputs को असली Mac और Chrome से मिलाकर Math.tanh और 7 CSS trigonometric functions की bit match verify करता है, और सिर्फ accuracy ही नहीं बल्कि architecture differences और execution time को भी असली browser के स्तर तक match करता है

Math.tanh से सामने आने वाला OS

  • Math.tanh(0.8) का result host math library के हिसाब से बदलता है
    • Linux Chrome का glibc: 0.6640367702678491
    • macOS Chrome का libsystem_m: 0.664036770267849
    • Windows Chrome का UCRT: 0.6640367702678489
  • Apple और glibc पूरे input के लगभग एक-चौथाई हिस्से में आम तौर पर 1 ULP का अंतर दिखाते हैं, और Windows UCRT कुछ प्रतिशत inputs में दोनों libraries से अलग होता है
    • ULP (unit in the last place) किसी खास magnitude पर represent किए जा सकने वाले लगातार floating-point numbers के बीच की दूरी है, और 1 ULP वह न्यूनतम अंतर है जिसे double दिखा सकता है
  • असली Chrome 150 को Linux, Apple Silicon आधारित macOS 26, और Windows 11 पर DevTools Protocol से measure करने पर input के अनुसार classification power बदलती है
    • tanh(0.5) तीनों OS पर 0.46211715726000974 के समान है, इसलिए detection में इस्तेमाल नहीं किया जा सकता
    • tanh(0.7) में केवल Linux 1 ULP अलग है
    • tanh(0.8) में तीनों OS अलग हैं और पूरी range 2 ULP है
    • tanh(0.9) में केवल Windows 1 ULP अलग है
  • लगभग तीन-चौथाई inputs में तीनों OS एक जैसा result देते हैं, लेकिन एक सही input से OS-specific signature मिल सकता है
  • अगर कोई macOS होने का दावा करते हुए Linux के math bits लौटाता है, तो Math.tanh का result User-Agent से contradict करता है

Chrome 148 में आया बदलाव

  • Chrome 147 तक V8 Math.tanh calculate करने के लिए portable math implementation fdlibm का port built-in रखता था, इसलिए सभी OS पर वही bits लौटते थे
  • V8 commit c1486295ae5 ने built-in implementation को platform के std::tanh से replace कर दिया
    • यह बदलाव पहली बार V8 14.8.57 और Chrome 148 में शामिल हुआ
    • Chrome 148, 149 और 150 host libm के differences expose करते हैं, लेकिन Chrome 147 या उससे नीचे इस path से OS leak नहीं करते
  • IEEE 754 double के storage format को define करता है, लेकिन यह require नहीं करता कि sin, cos, tanh, exp जैसे transcendental functions हमेशा correctly rounded हों
  • हर OS की math library (libm) performance और ULP error के बीच trade-off करती है और अलग-अलग minimax approximation polynomial coefficients, lookup tables और range reduction constants इस्तेमाल करती है
    • Linux में glibc
    • macOS में Apple libsystem_m
    • Windows में UCRT का ucrtbase.dll
  • Detector को math operation itself analyze करने की जरूरत नहीं; वह असली Chrome के per-input result table से values compare कर सकता है

Reproduction को कठिन बनाने वाले चार pitfalls

  • V8 के केवल कुछ functions leak होते हैं

    • V8 ज्यादातर math implementations को statically link करता है, इसलिए OS से independent होकर वही result देता है
    • Math.exp, Math.pow, Math.atan आदि built-in llvm-libc implementation इस्तेमाल करते हैं
    • Math.sin और Math.cos glibc से निकले built-in dbl-64 routines इस्तेमाल करते हैं
    • Chrome 148 के बाद platform std::tanh इस्तेमाल करने वाला Math.tanh ही Math.* में OS leak करता है
    • जो functions leak नहीं करते उन्हें भी target OS जैसा spoof करने पर V8 की actual call structure से mismatch होगा, और यह asymmetry कि सिर्फ tanh अलग है, खुद भी check की जा सकती है
  • JavaScript और CSS अलग paths इस्तेमाल करते हैं

    • CSS के sin(), cos(), atan2() JavaScript के Math.sin के साथ code share नहीं करते
    • Blink layout engine angle को degrees में reduce करने के बाद reduced value पर platform std::sin आदि call करता है
    • यह direct radian input calculate करने के result से अलग होता है, और सभी 7 CSS trigonometric functions host libm के जरिए OS leak करते हैं
    • bit-level reproduction में सिर्फ final math function ही नहीं, बल्कि degree-based range reduction और radian-degree conversion process भी शामिल करना होगा
  • macOS के भीतर भी दो अलग libraries हैं

    • Apple Silicon में scalar libsystem_m और Accelerate की vector routines vvsin, vvtanh साथ मौजूद हैं, और दोनों implementations समान नहीं हैं
    • 10 लाख inputs में function के आधार पर 10–89% results अलग थे
    • cos(0) scalar implementation में बिल्कुल 1.0 है
    • Accelerate में यह 0.9999999999999999 लौटाता है
    • असली Mac के Chrome को debugging protocol से measure करके call site के हिसाब से library अलग की जाती है
    • Math.tanh, CSS trigonometric functions और audio compressor के per-sample transcendental functions scalar libsystem_m इस्तेमाल करते हैं
    • Mac के Web Audio DSP, FFT, vector math और biquad filters Accelerate इस्तेमाल करते हैं
    • संबंधित Chromium paths में fft_frame_mac.cc, vector_math_mac.h, biquad.cc और BUILDFLAG(IS_MAC) हैं
    • call site से match न करने वाली Apple library चुनने पर ज्यादातर inputs में 1 ULP mismatch हो सकता है
  • CPU architecture भी result में दखल देता है

    • ARM और x86 में fused multiply-add (FMA) और NaN sign propagation में differences होते हैं
    • mathematical procedure सही होने पर भी अगर compiler केवल एक architecture पर multiply और add को fuse करे, तो result bits बदल जाते हैं

Engine और feature के हिसाब से leakage paths

  • JavaScript का V8 Math.* लगभग पूरी तरह built-in implementation इस्तेमाल करता है, और host libm से जुड़ने वाला point केवल Math.tanh है
    • sin, cos, tan, asin, acos, atan, atan2, exp, log, log2, log10, pow V8 built-in implementation इस्तेमाल करते हैं
    • sqrt, abs, arithmetic operations hardware operations हैं
  • CSS calc() के math functions में Blink platform library को सीधे call करता है
    • sin, cos, tan, asin, acos, atan, atan2, exp, log, log2, log10, pow host libm इस्तेमाल करते हैं
    • CSS में corresponding tanh path नहीं है
  • Web Audio call site के अनुसार कई implementations मिलाकर इस्तेमाल करता है
    • Mac के oscillator FFT, vector addition/multiplication/scale और FFT Accelerate का vDSP इस्तेमाल करते हैं
    • DynamicsCompressor के sin, exp, log10f, powf जैसे per-sample transcendental functions scalar libsystem_m इस्तेमाल करते हैं
    • एक audio graph V8 built-in math, scalar library और Accelerate जैसी तीन libraries में फैल सकता है
  • WebAssembly में transcendental function instructions नहीं हैं
    • sin आदि के results module में शामिल libm पर निर्भर करते हैं
    • f64.sqrt, f64.mul जैसी arithmetic hardware में execute होती है, इसलिए OS के हिसाब से समान रहती है
    • बची हुई fingerprint axis ARM और x86 के बीच NaN normalization और कुछ SIMD rounding differences हैं
  • Detection signals Math.tanh, सभी CSS trigonometric functions और Web Audio पर केंद्रित हैं
    • Web Audio का Accelerate FFT CPU architecture दिखाता है
    • compressor का scalar libsystem_m OS दिखाता है

Values को बदलने के बजाय सटीक reproduce करना

  • Noise fail क्यों होता है

    • result में noise जोड़ने पर वह reference table में मौजूद किसी भी असली OS value से match नहीं कर सकता
    • हर call पर random value बदलने से determinism टूटता है, और यह phenomenon खुद एक अलग detection signal बन जाता है
    • लक्ष्य similar value नहीं, बल्कि दावा किए गए OS द्वारा लौटाई जाने वाली value से bit-for-bit समान result है
  • Target algorithm के सभी elements restore करना

    • target libm से minimax approximation coefficients, exponent tables और range reduction constants recover करके portable C code में ले जाए जाते हैं
    • target library जिन inputs को गलत direction में round करती है, उन्हें भी ठीक उसी तरह match करना होगा
    • Apple sin reproduction में libsystem_m से निकाले गए coefficients के exact bit patterns और explicit fma() calls इस्तेमाल होते हैं
    • coefficients को decimal में ले जाने पर transcription के दौरान फिर rounding हो सकती है, इसलिए उन्हें hexadecimal floating-point values के रूप में preserve किया जाता है
    • Apple जिन multiply-adds को fuse करता है, code में भी उन्हें explicitly fuse किया जाता है
  • FMA को deterministic बनाना

    • -ffp-contract=off से compile करके compiler को मनमाने ढंग से FMA जोड़ने या हटाने से रोका जाता है
    • code में explicitly लिखे गए fma() ही Apple जैसी जगहों पर execute होते हैं, इसलिए ARM mimic करते हुए x86 server पर चलाने पर भी वही bits मिलते हैं
    • hardware FMA और correctly rounded software FMA वही bits लौटाते हैं

Windows UCRT original code का इस्तेमाल

  • Windows UCRT Linux server जैसी x86-64 ISA इस्तेमाल करता है और position-independent है, इसलिए actual ucrtbase.dll को runtime memory में map करके math function exports को सीधे call किया जा सकता है
  • original code चलाने के कारण अलग से math algorithm reverse engineering के बिना actual UCRT bits मिलते हैं
  • Linux के System V ABI और Windows x64 ABI के differences handle करने होंगे
    • Windows x64 में callee return address के ऊपर 32-byte shadow space इस्तेमाल करता है
    • callee-saved register set भी System V से अलग है
    • function pointer को ms_abi के रूप में declare न करने पर shadow-space writes clang stack frame को damage कर देती हैं और indirect call गलत address पर जा सकता है
  • mapped DLL code CFI में registered indirect call target नहीं है
    • production का -fsanitize=cfi-icall हर call पर #UD trap और SIGILL पैदा कर सकता है
    • function pointer call करने वाले wrapper को clang::no_sanitize("cfi-icall") चाहिए
  • UCRT math functions शुरुआत में mov eax, [rip+disp32] से CPU dispatch flag पढ़कर scalar या FMA/AVX2 path चुनते हैं
    • नए mapped DLL में flag 0 होता है, इसलिए slow scalar path चुना जाता है
    • इस path का result modern Windows systems के result bits से अलग होता है
    • tanh prologue में flag address ढूंढकर first call से पहले FMA path force करना होगा ताकि actual Windows से bit-for-bit match हो

Patch location और performance constraints

  • engine जिस single bottleneck point पर libm call करता है उसे hook करके, browser जिस OS का दावा करता है उसके अनुसार path चुना जाता है
    • Linux का दावा हो तो glibc कायम रखा जाता है
    • macOS का दावा हो तो Apple reproduction implementation इस्तेमाल किया जाता है
  • result exact हो, फिर भी execution time actual browser से अलग हो तो detect किया जा सकता है
  • पहले build में default x86 baseline hardware FMA से पुराना था, इसलिए सभी fma() software calls में lower हो गए और native से 2.5–6 गुना धीमे थे
  • Math.tanh और Math.sin loops के timing ratio compare करने पर actual browser में मौजूद न होने वाला performance pattern सामने आ सकता है
  • hardware FMA enable करने पर हर fused operation single instruction बन गया, जिससे करीब 6 गुना speedup हुआ; यह glibc से तेज था, फिर भी result bits identical रहे

871,000 inputs से verification

  • verification harness हर release में 871,000 inputs को सभी branches और domains में run करता है
    • dense input grid
    • interval boundaries
    • subnormal numbers
    • signed zero
    • infinity
    • NaN
  • दो तरह के real environments को reference values के रूप में इस्तेमाल किया जाता है
    • actual Mac सभी inputs पर scalar और Accelerate results अलग-अलग calculate करके उन points को identify करता है जहां दोनों implementations diverge करते हैं
    • actual Mac के Chrome को debugging protocol से चलाकर Math.tanh और सभी CSS trigonometric functions के full-precision results collect किए जाते हैं
  • Math.tanh और CSS के sin, cos, tan, asin, acos, atan, atan2 actual Mac Chrome से bit-for-bit match करते हैं
  • यह भी verify किया जाता है कि reproduction implementation deployed binary में actual machine code की तरह ही behave करता है
  • domain boundary पर browser post-processing भी match करनी होगी
    • actual Mac पर CSS asin(2) domain से बाहर होने के कारण NaN बनता है और CSS NaN को 0 तक clamp करता है, इसलिए final value 0 है
    • simple reproduction implementation इसे गलत तरीके से 90 degrees लौटा सकता है

Browser spoofing में math क्यों महत्वपूर्ण है

  • math results deterministic और सस्ते में check किए जा सकते हैं, लेकिन सही spoofing के लिए vendor libm internals और engine-specific call paths जानना जरूरी है
  • actual browser से match करने के लिए समझना होगा कि V8, Blink और Web Audio हर call site पर कौन-सी math library चुनते हैं, और last bit, architecture-specific behavior और execution time तक match करना होगा
  • Scrapfly का Scrapium जब macOS के रूप में दिखने का request पाता है, तो cosine के rounding bits तक actual macOS traffic से match करने के लिए configured होता है

1 टिप्पणियां

 
GN⁺ 4 시간 전
Hacker News की राय
  • यह व्याख्या कि सही input के साथ tanh को एक बार call करने का परिणाम OS-specific signature बन जाता है, browser version range पहचानने की संभावना को नज़रअंदाज़ करती है
    ज़्यादातर लोग User-Agent में OS को spoof नहीं करते, और fingerprinting OS itself से ज़्यादा quasi-unique traits के combination में रुचि रखती है। खोज दिलचस्प है, लेकिन article बहुत ज़्यादा LLM से लिखा हुआ लगता है, जिससे भरोसा कम होता है

    • इस article को बनाने वाली company वास्तव में Linux VM bots को Windows या macOS physical machines जैसा दिखाने की कोशिश कर रही है
      ताकि वे bot detection को आसानी से पार कर सकें और दूसरे websites से scraped data customers को बेच सकें
    • सिर्फ इस method से अभी केवल इतना पता चलता है कि Chromium 148 या ऊपर है, लेकिन हर version में जोड़ी गई V8·Blink features को JavaScript या CSS से check करें तो करीब version 120 के बाद से major version को भरोसे से pinpoint किया जा सकता है
      यह बात कि इसे LLM से लिखा गया है, article और blog में disclose की गई है; इसे छिपाया नहीं गया और न ही इंसान होने का दिखावा किया गया। समय कम था, वरना article publish ही नहीं हो पाता, और इस choice की जिम्मेदारी लेने को तैयार हूं
    • version range identify की जा सकती है, लेकिन ऐसे तरीकों की पहले से गिनती नहीं है
      browsers लगातार features add करते और bugs fix करते रहते हैं, और उनमें से ज़्यादातर को JavaScript से detect किया जा सकता है
    • अगर content सच है, तो किसने लिखा इससे फर्क नहीं पड़ता, और LLM की core argument भी valid है
  • सभी fingerprinting techniques को AI से analyze करके public कर देना, और विवाद के बाद browsers को इन्हें block करने की ओर धकेलना, एक चालाक strategy है क्योंकि इससे उनकी scraping business ज़्यादा पैसा कमा सकती है
    ऐसी companies न होतीं तो browser fingerprinting आज जितनी फैली है उतनी नहीं होती, और internet भी बेहतर होता। बल्कि fingerprint.js जैसी clear opposing interest वाली तरफ़ की posts मुझे ज़्यादा पसंद हैं

    • scrapers हों या न हों, humans को track करने के लिए fingerprinting की जरूरत होगी और आखिरकार इसका use होगा, इसलिए इससे सहमत होना मुश्किल है
  • correctly rounded transcendental functions को push करने की एक और वजह मिल गई
    हाल ही में पता चला कि यह problem practically solve हो चुकी है। https://arith2026.org/program.html की दूसरी keynote देखें

    • exactly rounded libm functions शानदार हैं, लेकिन पुराने glibc के pow की तरह worst-case performance भयानक नहीं होनी चाहिए
      rounding boundary के करीब इस्तेमाल होने वाले high-precision fallback path को खुद SLP vectorize करके worst-case performance improve करने की कोशिश की जा सकती है, लेकिन यह पहले ही ज़्यादातर uses के लिए काफी है। यह आश्चर्यजनक है कि JavaScript engines ECMAScript spec में recommended fdlibm का इस्तेमाल जारी नहीं रखते, और अगर Math.tanh JavaScript का bottleneck path है तो वह काफी असामान्य code होगा
    • समझना मुश्किल है कि fixed precision और integer arithmetic ज्यादा widely used क्यों नहीं हैं
      engineering में fixed-point अक्सर इस्तेमाल होता था क्योंकि वह कहीं ज्यादा simple hardware पर चलता है और errors को mathematically आसानी से model किया जा सकता है। IEEE 754 floating-point theoretically भी संदिग्ध है, और precision loss के मामले में mantissa से छोटे integers, यानी 24-bit से कम integers, कभी-कभी 32-bit floating-point से बेहतर होते हैं
    • हैरानी है कि क्या वे हर साल new domain register करके permanently renew करने का तरीका अपनाते हैं
  • अच्छा होगा अगर यह technique https://coveryourtracks.eff.org/ में add हो जाए, ताकि मैं देख सकूं कि मेरी math function results बड़ी population में कितनी unique हैं

    • यह company दावा करती है कि उसने Chromium की 550 से ज़्यादा C++ files में 4,000 से ज्यादा signals patch किए हैं
      पता नहीं यह सच है या नहीं, लेकिन लगता है कि coveryourtracks.eff.org करीब 25 signals use करता है
  • article में Claude ने लिखा है, ऐसा साफ झलकता है

    • article के top पर AI summary link अजीब है क्योंकि वह चुने गए AI provider से सिर्फ article summary नहीं, बल्कि product ad भी मांगता है
      Claude link पर click करने से यह prompt भेजा जाता है: summarize+this+article+and+explain+how+scrapfly+helps+me+scrape+any+website+at+scale+and+bypass+anti-bot+systems+for+my+use+case:+[https://scrapfly.dev/posts/browser-math-os-fingerprint/](<https://scrapfly.dev/posts/browser-math-os-fingerprint/>;)
    • title वाली discovery दिलचस्प है, लेकिन बाकी essentially Claude-written content है
    • पिछले कुछ महीनों में HN activity कम रही, लेकिन लगता है community content को low-quality label करने और LLM usage detect करने को लेकर paranoid obsession में है
  • Tor Browser और Mullvad Browser ने भी आखिरकार OS hiding छोड़ दी, लेकिन शायद उन्हें ऐसा नहीं करना चाहिए था
    ऐसा लगता है कि fingerprinting paths बहुत ज्यादा हैं

    • यह भी clear नहीं कि OS छिपाना possible है या नहीं, इसलिए मुझे लगता है decision सही था
      browser के अंदर और बाहर OS-specific behavior differences बहुत ज्यादा होते हैं, सभी को handle करना मुश्किल है। canvas extraction block करने या noise add करने पर भी rendering differences expose हो सकते हैं, और Tor Browser developers ने confirm किया है कि वे पूरी तरह अलग OS तो दूर, X11 और Wayland के differences भी hide नहीं कर सकते। https://forum.torproject.org/t/linux-is-it-alright-to-run-th...
    • Tor Browser navigator.platform तक modify नहीं करता, इसलिए non-Windows environment पता लगाना बहुत आसान है
  • अपने पसंदीदा JavaScript injection plugin से यह code डाल दें: let oldTanh = Math.tanh; Math.tanh = x => oldTanh(x) + Math.random()/10000000;

    • और concise रूप में मुझे Math.tanh = Math.random; पसंद है
    • article में इसे पहले ही cover किया गया है, बस “No noise” search करें
    • कई anti-bot vendors इस replacement को detect करके fingerprinting signal के रूप में use करेंगे
    • अब normal value के बजाय आप fingerprint छिपाने वाले user के रूप में सामने आ सकते हैं, जिससे identify करना उल्टा और आसान हो सकता है
  • latest glibc CORE-MATH का correctly rounded tanh use करता है, इसलिए यह article में quoted values से अलग result return करता है
    बाकी transcendental functions के लिए भी reasonable performance के साथ correct rounding implement की जा सकती है या नहीं, यह अभी clear नहीं है, इसलिए हर function अपनी unique fingerprint छोड़ता है

  • Chrome का executable code ही सैकड़ों MB का है, तो मुझे लगा था कि user-space libraries का लगभग आधा हिस्सा statically linked होगा
    साथ ही मुझे लगा था कि tanh function call नहीं, बल्कि JavaScript JIT द्वारा CPU instruction में emit किया गया built-in operation होगा; math operation के लिए dlsym() function से branch करना अजीब है। CPU instruction खुद भी fingerprinting में इस्तेमाल हो सकता है

    • x87 FPU ने transcendental functions को microcode में implement किया था, लेकिन ज़्यादातर instruction sets यह provide नहीं करते
      microcode को branch prediction जैसे फायदे नहीं मिलते, इसलिए practically वह software implementation से धीमा होता है
    • जहां तक याद है, Chrome non-JIT mode में NaN value के unused bits preserve करने वाला इकलौता browser है, और code JIT होने पर वे bits 0 हो जाते हैं
  • शक है कि यह लड़ाई जीती जा सकती है
    पर्याप्त functions run करने पर execution time ratios और rounding results को combine करके OS और exact model ही नहीं, उसी machine पर चल रहे दूसरे tasks तक estimate किए जा सकते हैं। पूरी तरह रोकने के बजाय शायद इसे थोड़ा मुश्किल बनाना ही possible है
    आखिर society और law को catch up करना होगा। जैसे door locks intrusion को पूरी तरह नहीं रोकते, लेकिन social condemnation और criminal penalties उन्हें complement करते हैं, वैसे ही इस तरह की individual tracking को illegal बनाना चाहिए और इससे फायदा उठाने वाली companies और employees को socially ostracize करना चाहिए

    • cyberspace में illegal या illegal होने चाहिए ऐसे काम करने वाले लोग अक्सर ऐसे jurisdictions में होते हैं जहां enforcement possible नहीं होता
      Russia, Myanmar, North Korea जैसी जगहों पर rule of law काम नहीं करता, और local authorities कभी-कभी foreigners को ठगने वाले criminals को actively protect भी करती हैं, इसलिए door lock analogy लागू नहीं होती