- Chrome 148'den itibaren V8'deki
Math.tanh, yerleşik fdlibm yerine host sisteminstd::tanhçağrısını kullanıyor; bu da aynı girdinin Linux'un glibc'si, macOS'inlibsystem_m'i ve Windows'un UCRT'sinde farklı son bitler döndürmesine yol açıyor Math.tanh(0.8), Linux'ta0.6640367702678491, macOS'te0.664036770267849, Windows'ta0.6640367702678489veriyor; böylece tek bir çağrıyla üç işletim sistemi ayırt edilebiliyor ve sonuç User-Agent'in iddia ettiği işletim sistemiyle uyuşmazsa sahtecilik ortaya çıkıyor- Sızıntı yolu motora göre değişiyor: V8'in
Math.*içinde yalnızcatanhhost matematik kütüphanesini kullanırken, Blink'in tüm CSS trigonometrik fonksiyonları ve Web Audio'daki bazı işlemler de işletim sistemine özgü kütüphanelerden geçiyor - Değeri rastgele oynatmak onu hiçbir gerçek işletim sisteminin çıktısıyla eşleştirmez ve determinizmi de bozar; bu yüzden hedef kütüphanenin katsayılarını, tablolarını, aralık daraltmasını ve FMA davranışını bit düzeyinde yeniden üretmek ya da doğrudan özgün UCRT kodunu eşlemek gerekiyor
- Scrapfly, her sürümde 871.000 girdiyi gerçek Mac ve Chrome ile karşılaştırarak
Math.tanhile 7 CSS trigonometrik fonksiyonunun bit eşleşmesini doğruluyor; yalnızca doğruluğu değil, mimari farkları ve çalışma süresini de gerçek tarayıcı düzeyine getiriyor
Math.tanh'ın ortaya çıkardığı işletim sistemi
Math.tanh(0.8)sonucunun değeri, host matematik kütüphanesine göre değişiyor- Linux Chrome'da glibc:
0.6640367702678491 - macOS Chrome'da
libsystem_m:0.664036770267849 - Windows Chrome'da UCRT:
0.6640367702678489
- Linux Chrome'da glibc:
- Apple ve glibc, tüm girdilerin yaklaşık dörtte birinde çoğunlukla 1 ULP fark gösterirken, Windows UCRT birkaç yüzde girdide bu iki kütüphaneden ayrılıyor
- ULP (unit in the last place), belirli bir büyüklükte temsil edilebilen ardışık kayan noktalı sayılar arasındaki aralıktır; 1 ULP ise
double'ın gösterebildiği en küçük farktır
- ULP (unit in the last place), belirli bir büyüklükte temsil edilebilen ardışık kayan noktalı sayılar arasındaki aralıktır; 1 ULP ise
- Gerçek Chrome 150, Linux, Apple Silicon tabanlı macOS 26 ve Windows 11 üzerinde DevTools Protocol ile ölçüldüğünde, sınıflandırma gücü girdiye göre değişiyor
tanh(0.5)üç işletim sisteminde de0.46211715726000974olduğundan tespit için kullanılamaztanh(0.7)yalnızca Linux'ta 1 ULP farklıdırtanh(0.8)için üç işletim sistemi de birbirinden farklıdır ve toplam aralık 2 ULP'dirtanh(0.9)için yalnızca Windows 1 ULP farklıdır
- Girdilerin yaklaşık dörtte üçünde üç işletim sistemi aynı sonucu üretse de, uygun tek bir girdi ile işletim sistemine özgü bir imza elde etmek mümkündür
- macOS olduğunu iddia ederken Linux'un matematik bitlerini döndürmek,
Math.tanhsonucunun User-Agent ile çelişmesine neden olur
Chrome 148 ile gelen değişiklik
- Chrome 147'ye kadar V8, taşınabilir bir matematik uygulaması olan fdlibm portunu yerleşik olarak kullanarak
Math.tanhhesaplıyordu; bu yüzden tüm işletim sistemlerinde aynı bitler döndürülüyordu - V8 commit'i
c1486295ae5, yerleşik uygulamayı platformunstd::tanh'ı ile değiştirdi- Bu değişiklik ilk kez V8 14.8.57 ve Chrome 148'de yer aldı
- Chrome 148·149·150, host
libmfarklarını görünür kılarken, Chrome 147 ve öncesi bu yoldan işletim sistemi sızdırmıyor
- IEEE 754,
double'ın nasıl saklandığını tanımlar; ancaksin,cos,tanh,expgibi aşkın fonksiyonların mutlaka doğru yuvarlanmasını şart koşmaz - Her işletim sisteminin matematik kütüphanesi (
libm), performans ile ULP hatası arasında denge kurarken farklı minimax yaklaşım polinom katsayıları, arama tabloları ve aralık daraltma sabitleri kullanır- Linux: glibc
- macOS: Apple
libsystem_m - Windows: UCRT'nin
ucrtbase.dll
- Tespit sistemleri, matematik işleminin kendisini analiz etmek zorunda kalmadan, gerçek Chrome'un girdiye göre ürettiği sonuç tablosuyla değerleri karşılaştırabilir
Yeniden üretimi zorlaştıran dört tuzak
-
Yalnızca V8'in bazı fonksiyonları sızdırıyor
- V8, çoğu matematik uygulamasını statik olarak bağladığı için işletim sisteminden bağımsız aynı sonuçları verir
Math.exp,Math.pow,Math.atangibi fonksiyonlar yerleşik llvm-libc uygulamasını kullanırMath.sinveMath.cos, glibc kökenli yerleşikdbl-64rutinlerini kullanır- Chrome 148 sonrasında platform
std::tanhkullananMath.tanh,Math.*içinde işletim sistemini sızdıran tek fonksiyondur - Sızıntı yapmayan fonksiyonları da hedef işletim sistemi gibi taklit etmek, V8'in gerçek çağrı yapısıyla çelişir;
tanh'ın tek başına farklı olması şeklindeki asimetri de denetlenebilir
-
JavaScript ve CSS farklı yollar kullanıyor
- CSS'teki
sin(),cos(),atan2(), JavaScript'tekiMath.sinile aynı kodu paylaşmaz - Blink yerleşim motoru, açıyı derece cinsinden daralttıktan sonra daraltılmış değere platform
std::sinvb. çağrıları yapar - Sonuç, doğrudan radyan girdisiyle hesaplanan sonuçtan farklı olur ve 7 CSS trigonometrik fonksiyonunun tamamı host
libmüzerinden işletim sistemini sızdırır - Bit düzeyinde yeniden üretim için yalnızca son matematik fonksiyonu değil, derece cinsinden aralık daraltma ile radyan-derece dönüşümü de yeniden üretilmelidir
- CSS'teki
-
macOS içinde bile iki farklı kütüphane var
- Apple Silicon'da skaler
libsystem_mile Accelerate'ın vektör rutinlerivvsin,vvtanhbirlikte bulunur ve bu iki uygulama aynı değildir - 1 milyon girdi üzerinde, fonksiyona bağlı olarak sonuçların %10 ila %89'u farklı çıkmıştır
cos(0), skaler uygulamada tam olarak1.0'dır- Accelerate ise
0.9999999999999999döndürür - Gerçek Mac üzerindeki Chrome, hata ayıklama protokolü ile ölçülerek hangi çağrı noktasında hangi kütüphanenin kullanıldığı ayrıştırılmıştır
Math.tanh, CSS trigonometrik fonksiyonları ve ses sıkıştırıcısındaki örnek başına aşkın fonksiyonlar skalerlibsystem_mkullanır- Mac'teki Web Audio DSP, FFT, vektör matematiği ve biquad filtreleri ise Accelerate kullanır
- İlgili Chromium yolları arasında
fft_frame_mac.cc,vector_math_mac.h,biquad.ccveBUILDFLAG(IS_MAC)bulunur - Çağrı noktasına uymayan Apple kütüphanesini seçmek, girdilerin çoğunda 1 ULP sapmaya yol açabilir
- Apple Silicon'da skaler
-
CPU mimarisi de sonuca etki eder
- ARM ve x86, fused multiply-add (FMA) ve NaN işaret yayılımında farklılık gösterir
- Matematiksel prosedür doğru olsa bile, derleyici yalnızca bir mimaride çarpma ve toplama işlemlerini birleştirirse sonuç bitleri değişebilir
Motor ve özellik bazında sızıntı yolları
- JavaScript tarafında V8
Math.*neredeyse tamamen yerleşik uygulamaları kullanır ve hostlibm'e bağlanan tek noktaMath.tanh'dırsin,cos,tan,asin,acos,atan,atan2,exp,log,log2,log10,powV8'in yerleşik uygulamalarını kullanırsqrt,absve dört işlem ise donanım işlemleridir
- CSS
calc()içindeki matematik fonksiyonlarında Blink doğrudan platform kütüphanesini çağırırsin,cos,tan,asin,acos,atan,atan2,exp,log,log2,log10,powhostlibmkullanır- CSS tarafında buna karşılık gelen bir
tanhyolu yoktur
- Web Audio, çağrı noktasına göre birden fazla uygulamayı karışık şekilde kullanır
- Mac'te osilatör FFT'si, vektör toplama-çarpma-ölçekleme ve FFT, Accelerate'ın
vDSP'sini kullanır - DynamicsCompressor içindeki
sin,exp,log10f,powfgibi örnek başına aşkın fonksiyonlar skalerlibsystem_mkullanır - Tek bir ses grafiği, V8 yerleşik matematiği, skaler kütüphane ve Accelerate gibi üç farklı kütüphane üzerine yayılabilir
- Mac'te osilatör FFT'si, vektör toplama-çarpma-ölçekleme ve FFT, Accelerate'ın
- WebAssembly'de aşkın fonksiyon talimatları yoktur
singibi sonuçlar, modüle gömülülibm'e göre belirlenirf64.sqrt,f64.mulgibi aritmetik işlemler donanımda çalıştığından işletim sistemleri arasında aynıdır- Geriye kalan parmak izi eksenleri, ARM ile x86 arasındaki NaN normalizasyonu ve bazı SIMD yuvarlama farklarıdır
- Tespit sinyali
Math.tanh, tüm CSS trigonometrik fonksiyonları ve Web Audio etrafında yoğunlaşır- Web Audio'daki Accelerate FFT, CPU mimarisini ortaya çıkarır
- Sıkıştırıcının skaler
libsystem_mkullanımı ise işletim sistemini ortaya çıkarır
Değeri oynatmak yerine tam olarak yeniden üretmek
-
Gürültü ekleme neden başarısız olur
- Sonuca gürültü eklemek, onu referans tablodaki hiçbir gerçek işletim sistemi değeriyle eşleştirmeyebilir
- Her çağrıda rastgele farklı bir değer üretilirse determinizm bozulur ve bu durum başlı başına ayrı bir tespit sinyali haline gelir
- Hedef, benzer bir değer değil; iddia edilen işletim sisteminin döndürdüğü değerle bit düzeyinde aynı sonucu üretmektir
-
Hedef algoritmanın tüm unsurlarını geri kazanmak
- Hedef
libmiçindeki minimax yaklaşım katsayıları, üs tabloları ve aralık daraltma sabitleri geri çıkarılıp taşınabilir C koduna aktarılır - Hedef kütüphanenin yanlış yönde yuvarladığı girdilerde bile aynı sonuç birebir üretilmelidir
- Apple
sinyeniden üretiminde,libsystem_m'den çıkarılan katsayıların tam bit desenleri ve açıkfma()çağrıları kullanılır - Katsayılar ondalık biçimde taşınırsa aktarım sırasında tekrar yuvarlanabileceğinden, onaltılık kayan nokta değerleri olarak korunur
- Apple'ın birleştirdiği her çarpma-toplama işlemi, kodda da açıkça birleştirilir
- Hedef
-
FMA'yi deterministik olarak sabitlemek
- Derleme sırasında
-ffp-contract=offkullanılarak derleyicinin rastgele FMA eklemesi veya kaldırması engellenir - Kodda açıkça belirtilen
fma()çağrıları yalnızca Apple ile aynı noktalarda çalışır; bu sayede ARM taklit edilirken kod x86 sunucuda çalışsa bile aynı bitler elde edilir - Donanım FMA ile doğru yuvarlanan yazılım FMA aynı bitleri döndürür
- Derleme sırasında
Windows UCRT'nin özgün kodunu kullanmak
- Windows UCRT, Linux sunucularla aynı x86-64 ISA'yı kullanır ve konumdan bağımsızdır; bu nedenle gerçek
ucrtbase.dllçalışma zamanı belleğine eşlenip matematik fonksiyon export'ları doğrudan çağrılabilir - Özgün kod çalıştırıldığı için, ayrı bir matematik algoritması tersine mühendisliği yapmadan gerçek UCRT bitleri elde edilir
- Linux'un System V ABI'si ile Windows x64 ABI'si arasındaki farkların ele alınması gerekir
- Windows x64'te çağrılan fonksiyon, dönüş adresinin üzerindeki 32 baytlık shadow space alanını kullanır
- Çağrılan tarafça korunan register kümesi de System V'den farklıdır
- Fonksiyon pointer'ı
ms_abiolarak bildirilmezse, shadow-space yazımı clang stack frame'ini bozabilir ve dolaylı çağrı yanlış adrese gidebilir
- Eşlenen DLL kodu, CFI'ye kayıtlı dolaylı çağrı hedefi değildir
- Production'daki
-fsanitize=cfi-icall, her çağrıda#UDtrap veSIGILLoluşturabilir - Fonksiyon pointer'ını çağıran sarmalayıcıda
clang::no_sanitize("cfi-icall")gerekir
- Production'daki
- UCRT matematik fonksiyonları, başlangıçtaki
mov eax, [rip+disp32]ile CPU dispatch bayrağını okuyup skaler veya FMA/AVX2 yolunu seçer- Yeni eşlenen DLL'de bu bayrak 0 olduğundan yavaş skaler yol seçilir
- Bu yolun sonuç bitleri, modern Windows sistemlerindeki sonuçlardan farklıdır
- Gerçek Windows ile bit düzeyinde eşleşmek için
tanhprologundaki bayrak adresi bulunup ilk çağrıdan önce FMA yoluna zorlanmalıdır
Yama noktası ve performans kısıtları
- Motorun
libmçağırdığı tek darboğaz noktası hook'lanır ve yol, tarayıcının iddia ettiği işletim sistemine göre seçilir- Linux iddia ediliyorsa glibc korunur
- macOS iddia ediliyorsa Apple yeniden üretim uygulaması kullanılır
- Sonuçlar doğru olsa bile, çalışma süresi gerçek tarayıcıdan farklıysa tespit mümkün olabilir
- İlk derlemede varsayılan x86 tabanı, donanım FMA'den daha eski olduğundan tüm
fma()çağrılarını yazılım çağrılarına indirgedi ve yerel çalışmaya göre 2,5 ila 6 kat daha yavaştı Math.tanhileMath.sindöngülerinin zaman oranı karşılaştırıldığında, gerçek tarayıcıda bulunmayan performans desenleri açığa çıkabilir- Donanım FMA etkinleştirildiğinde, her birleşik işlem tek talimata dönüştü ve yaklaşık 6 kat hızlandı; sonuç bitleri aynı kalırken glibc'den bile daha hızlı hale geldi
871.000 girdi ile doğrulama
- Doğrulama harness'i, her sürümde 871.000 girdiyi tüm dallar ve tanım kümeleri boyunca çalıştırır
- yoğun girdi ızgarası
- aralık sınırları
- denormal sayılar
- işaretli sıfır
- sonsuzluk
- NaN
- Referans olarak iki tür gerçek ortam kullanılır
- Gerçek bir Mac, tüm girdiler için skaler ve Accelerate sonuçlarını ayrı ayrı hesaplayarak iki uygulamanın ayrıştığı noktaları belirler
- Gerçek Mac üzerindeki Chrome, hata ayıklama protokolü üzerinden çalıştırılarak
Math.tanhve tüm CSS trigonometrik fonksiyonlarının tam hassasiyetli sonuçları toplanır
Math.tanhile CSS tarafındakisin,cos,tan,asin,acos,atan,atan2, gerçek Mac Chrome ile bit düzeyinde eşleşir- Yeniden üretim uygulamasının, dağıtım ikilisindeki gerçek makine koduyla aynı şekilde davrandığı da doğrulanır
- Tanım kümesi sınırlarındaki tarayıcı son işleme adımları da eşleştirilmelidir
- Gerçek Mac'te CSS
asin(2)tanım kümesi dışı olduğu için NaN olur ve CSS NaN'i 0'a kısıtladığından nihai değer0olur - Basit bir yeniden üretim uygulaması bunu yanlış biçimde 90 derece olarak döndürebilir
- Gerçek Mac'te CSS
Tarayıcı kamuflajında matematik neden önemli?
- Matematik sonuçları deterministik ve düşük maliyetle doğrulanabilir, ancak doğru kamuflaj için vendor
libmiç yapıları ile motora özgü çağrı yollarının bilinmesi gerekir - Gerçek tarayıcıyla eşleşmek için, V8·Blink·Web Audio'nun her çağrı noktasında hangi matematik kütüphanesini seçtiğini belirlemek ve son bit, mimariye özgü davranışlar ile çalışma süresine kadar bunu tutturmak gerekir
- Scrapfly'ın Scrapium sistemi, macOS gibi görünmesi istendiğinde kosinüsün yuvarlama bitine kadar gerçek macOS trafiğiyle eşleşecek şekilde yapılandırılır
1 yorum
Hacker News görüşleri
Doğru girdide
tanhfonksiyonunun bir kez çağrılmasının sonucunun işletim sistemine göre bir imza haline geldiği açıklaması, tarayıcı sürüm aralığını tespit etme ihtimalini gözden kaçırıyorÇoğu kişi User-Agent içindeki işletim sistemini taklit etmez ve fingerprinting, işletim sisteminin kendisinden çok yarı benzersiz özellik kombinasyonlarıyla ilgilenir. Keşif ilginç ama yazı fazlasıyla LLM tarafından yazılmış görünüyor ve bu da güveni azaltıyor
Böylece bot tespitini daha kolay atlatıp başka web sitelerinden topladıkları verileri müşterilerine satabiliyorlar
LLM ile yazıldığı hem yazıda hem blogda açıkça belirtilmişti; saklanmadı ya da insan yazmış gibi davranılmadı. Zaman az olduğu için aksi halde yazı hiç yayımlanamayacaktı ve bu tercihin sorumluluğunu üstleniyorum
Tarayıcılar sürekli yeni özellikler ekliyor ve hataları düzeltiyor; bunların çoğu JavaScript ile tespit edilebilir
Tüm fingerprinting tekniklerini yapay zekayla analiz edip yayımlayarak, tartışmaların ardından tarayıcıların bunları engellemesini sağlamak; böylece kendi scraping işlerinin daha çok para kazanmasını hedeflemek akıllıca bir strateji
Bu şirketler olmasaydı tarayıcı fingerprinting'i bugün bu kadar yaygın olmayabilirdi ve internet daha iyi bir yer olurdu. Ben yine de çıkar ilişkisi açıkça belli olan karşı tarafın, örneğin fingerprint.js'in yazılarını tercih ederim
Doğru yuvarlanan transandantal fonksiyonlar için çalışmak adına bir neden daha çıktı
Yakın zamanda bu sorunun fiilen çözülmüş olduğunu öğrendim. https://arith2026.org/program.html bağlantısındaki ikinci açılış konuşmasına bakın
libmfonksiyonları harika ama geçmişte glibc'ninpowfonksiyonunda olduğu gibi en kötü durum performansı korkunç olmamalıYuvarlama sınırına yakın durumlarda kullanılan yüksek hassasiyetli alternatif yolu elle SLP vektörleştirerek en kötü durum performansı iyileştirilebilir ama çoğu kullanım için şimdiden yeterince iyi. JavaScript motorlarının, ECMAScript spesifikasyonunun önerdiği
fdlibm'i kullanmıyor olması şaşırtıcı; ayrıcaMath.tanhJavaScript'te bir darboğaz yol ise bu oldukça sıra dışı bir kod olurMühendislikte çok daha basit donanımlarda çalıştığı ve hata matematiksel olarak daha kolay modellenebildiği için sabit noktalı aritmetik sık kullanılırdı. IEEE 754 kayan nokta teorik olarak da şüpheli; ayrıca hassasiyet kaybı açısından, mantisadan küçük tamsayılar yani 24 bitten küçük tamsayılar bazen 32 bit kayan noktadan daha iyi olabilir
Bu tekniğin https://coveryourtracks.eff.org/ sitesine eklenmesi güzel olurdu; böylece matematik fonksiyonu sonuçlarımın daha büyük bir popülasyonda ne kadar benzersiz olduğunu görebilirdim
Doğru mu bilmiyorum ama coveryourtracks.eff.org'un kullandığı sinyal sayısı sanırım 25 civarında
Yazı Claude tarafından yazılmış gibi duruyor
Claude bağlantısına tıklanınca şu prompt gönderiliyor:
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/>)Tor Browser ve Mullvad Browser da sonunda işletim sistemini gizleme işinden vazgeçti ama belki de vazgeçmemeleri gerekirdi
Görünüşe göre fingerprinting yolları fazlasıyla çok
Tarayıcının içinde ve dışında işletim sistemine göre o kadar çok davranış farkı ortaya çıkıyor ki hepsini ele almak zor. Canvas çıkarımını engelleseniz ya da gürültü ekleseniz bile render farkları açığa çıkabiliyor; ayrıca Tor Browser geliştiricileri, tamamen farklı işletim sistemlerini bırakın, X11 ile Wayland arasındaki farkı bile gizleyemediklerini doğruladı. https://forum.torproject.org/t/linux-is-it-alright-to-run-th...
navigator.platformdeğerini bile değiştirmediği için Windows dışı bir ortamı tespit etmek çok kolayTercih ettiğiniz JavaScript enjeksiyon eklentisine şu kodu koymanız yeterli:
let oldTanh = Math.tanh; Math.tanh = x => oldTanh(x) + Math.random()/10000000;Math.tanh = Math.random;seçeneğini tercih ederimGüncel glibc, CORE-MATH'in doğru yuvarlanan
tanhuygulamasını kullanıyor; bu yüzden yazıda alıntılanan değerlerden farklı sonuç döndürüyorDiğer transandantal fonksiyonların da makul performansla doğru yuvarlanıp yuvarlanamayacağı hâlâ net değil; bu yüzden her fonksiyon kendi benzersiz fingerprint'ini bırakıyor
Chrome'un çalıştırılan kodu tek başına yüzlerce MB olduğuna göre kullanıcı alanı kütüphanelerinin en az yarısını statik olarak bağladığını sanıyordum
Ayrıca
tanh'in bir fonksiyon çağrısı değil, JavaScript JIT tarafından CPU talimatlarına dönüştürülen yerleşik bir işlem olduğunu düşünüyordum; matematik işlemi içindlsym()üzerinden dallanılması garip geliyor. CPU talimatlarının kendisi de fingerprinting için kullanılabilirMikrokod, dallanma tahmini gibi avantajlardan yararlanamadığı için pratikte yazılım uygulamasından daha yavaş
Bu mücadelede kazanmanın mümkün olup olmadığını merak ediyorum
Yeterince çok fonksiyon çalıştırılırsa, yürütme süresi oranları ile yuvarlama sonuçları birleştirilerek yalnızca işletim sistemi ve tam model değil, aynı cihazda çalışan diğer işler bile tahmin edilebilir gibi görünüyor. Tamamen engellemekten çok biraz zorlaştırmak mümkün olabilir
Sonunda toplumun ve hukukun yetişmesi gerekecek. Kapı kilitleri izinsiz girişi tamamen durdurmasa da toplumsal kınama ve cezai yaptırımlar bunu tamamladığı gibi, bu tür kişisel takip yöntemleri yasadışı ilan edilmeli ve bundan çıkar sağlayan şirketlerle oralarda çalışan insanlar toplumsal olarak dışlanmalı
Rusya, Myanmar ve Kuzey Kore gibi yerlerde hukukun üstünlüğü işlemiyor ve yerel makamlar yabancıları dolandıran suçluları aktif biçimde koruyabiliyor; bu yüzden kapı kilidi benzetmesi burada işlemiyor