014.修改chromium源码-修改webGL指纹(二)

2024-06-21 09:44

本文主要是介绍014.修改chromium源码-修改webGL指纹(二),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

修改chromium源码-修改webGL指纹(二)

一、webGL指纹是什么

  • 之前介绍过webGL指纹和常见网站绕过webGL指纹,插眼传送

二、为啥有的webGL指纹-二期

  • 上期我们通过修改gl的参数,getSupportedExtensions()函数返回值列表的顺序,绕过部分网站的指纹检测。
  • 但还有些网站通过webGL生成图形来获取指纹,我们就需要再出一期了。
  • 还有就是:上期指纹检测未通过browserscan这个网站。

三、获取浏览器的webGL指纹(通过生成图像)

  • 有攻才有防,先看看网站是如何通过js获取你的webGL指纹的。
  • 将下面的代码复制到F12控制台,就可以获取显示你的webGL指纹了。

async function sha256(message) {// 把字符串转换为Uint8Arrayconst msgBuffer = new TextEncoder().encode(message);// 计算散列值const hashBuffer = await crypto.subtle.digest('SHA-256', msgBuffer);// 转换为数组const hashArray = Array.from(new Uint8Array(hashBuffer));// 转换为16进制字符串const hashHex = hashArray.map(b => b.toString(16).padStart(2, '0')).join('');return hashHex;
}function getWebGLFingerprint() {var canvas = document.createElement('canvas');var gl = canvas.getContext("webgl") || canvas.getContext("experimental-webgl");// 设置清除颜色为黑色,不透明gl.clearColor(0.0, 0.0, 0.0, 1.0);// 清除颜色缓冲区gl.clear(gl.COLOR_BUFFER_BIT);// 创建顶点着色器var vsSource = `attribute vec4 aVertexPosition;void main(void) {gl_Position = aVertexPosition;}`;var vertexShader = gl.createShader(gl.VERTEX_SHADER);gl.shaderSource(vertexShader, vsSource);gl.compileShader(vertexShader);// 创建片段着色器var fsSource = `void main(void) {gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);}`;var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);gl.shaderSource(fragmentShader, fsSource);gl.compileShader(fragmentShader);// 创建着色器程序var shaderProgram = gl.createProgram();gl.attachShader(shaderProgram, vertexShader);gl.attachShader(shaderProgram, fragmentShader);gl.linkProgram(shaderProgram);gl.useProgram(shaderProgram);// 定义三角形的顶点var vertices = new Float32Array([0.0,  1.0,  0.0,-1.0, -1.0,  0.0,1.0, -1.0,  0.0]);// 创建顶点缓冲区对象var vertexBuffer = gl.createBuffer();gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);// 将缓冲区对象绑定到着色器变量var vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition");gl.enableVertexAttribArray(vertexPositionAttribute);gl.vertexAttribPointer(vertexPositionAttribute, 3, gl.FLOAT, false, 0, 0);// 绘制三角形gl.drawArrays(gl.TRIANGLES, 0, 3);// 读取渲染结果并生成指纹//var pixels = new Uint8Array(gl.drawingBufferWidth * gl.drawingBufferHeight * 4);//gl.readPixels(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight, gl.RGBA, gl.UNSIGNED_BYTE, pixels);//return pixels;var res = canvas.toDataURL()return res
}sha256(getWebGLFingerprint()).then(hash => console.log(hash));

可以看到:获取图像数据有2种方式,关键函数是readPixels()toDataURL()

四、修改源码的readPixels()函数

  • 打开源码文件 \third_party\blink\renderer\modules\webgl\webgl_rendering_context_base.cc
1.找到下面的代码
void WebGLRenderingContextBase::ReadPixelsHelper(GLint x,GLint y,GLsizei width,GLsizei height,GLenum format,GLenum type,DOMArrayBufferView* pixels,int64_t offset) {if (isContextLost())return;
2.替换为
int getRandomIntForFoo12Modern() {static std::mt19937 generator(static_cast<unsigned long>(time(NULL))); // 静态以确保只初始化一次std::uniform_int_distribution<int> distribution(0, 9);return distribution(generator);
}void WebGLRenderingContextBase::ReadPixelsHelper(GLint x,GLint y,GLsizei width,GLsizei height,GLenum format,GLenum type,DOMArrayBufferView* pixels,int64_t offset) {if (isContextLost())return;//追加2行width = width - getRandomIntForFoo12Modern();height = height - getRandomIntForFoo12Modern();

注意:这里我们通过裁剪了部分像素来实现改变ReadPixelsHelper方法的返回值

五、修改源码的toDataURL()函数

  • 打开源码文件 \third_party\blink\renderer\core\html\canvas\html_canvas_element.cc
1.头部加上(随便加在一个#include后面)
#include <algorithm> 
#include <random>    
#include <chrono>   
2.找到下面的代码

String HTMLCanvasElement::toDataURL(const String& mime_type,const ScriptValue& quality_argument,ExceptionState& exception_state) const {if (ContextHasOpenLayers(context_)) {exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,"`toDataURL()` cannot be called with open layers.");return String();}if (!OriginClean()) {exception_state.ThrowSecurityError("Tainted canvases may not be exported.");return String();}double quality = kUndefinedQualityValue;if (!quality_argument.IsEmpty()) {v8::Local<v8::Value> v8_value = quality_argument.V8Value();if (v8_value->IsNumber())quality = v8_value.As<v8::Number>()->Value();}String data = ToDataURLInternal(mime_type, quality, kBackBuffer);TRACE_EVENT_INSTANT(TRACE_DISABLED_BY_DEFAULT("identifiability.high_entropy_api"),"CanvasReadback", "data_url", data.Utf8());return data;
}

注意:最新源码可能和当前代码有略微差异,但基本逻辑是一样。要做的是给返回值后面加空格

3.替换为
String HTMLCanvasElement::toDataURL(const String& mime_type,const ScriptValue& quality_argument,ExceptionState& exception_state) const {if (ContextHasOpenLayers(context_)) {exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,"`toDataURL()` cannot be called with open layers.");return String();}if (!OriginClean()) {exception_state.ThrowSecurityError("Tainted canvases may not be exported.");return String();}double quality = kUndefinedQualityValue;if (!quality_argument.IsEmpty()) {v8::Local<v8::Value> v8_value = quality_argument.V8Value();if (v8_value->IsNumber())quality = v8_value.As<v8::Number>()->Value();}String data = ToDataURLInternal(mime_type, quality, kBackBuffer);TRACE_EVENT_INSTANT(TRACE_DISABLED_BY_DEFAULT("identifiability.high_entropy_api"),"CanvasReadback", "data_url", data.Utf8());//这里追加几行std::srand(std::time(nullptr));int randomNum = std::rand() % 100 + 1;std::string spaces(randomNum, ' ');data = data + String(spaces);//LOG(ERROR) << "data:('" << data << "') data";return data;
}

注意:data返回的是base64字符串,我们随机给后面加多个空格,这样不但不影响函数的功能,hash的也就是乱的了。

4.编译
ninja  -C  out/Default chrome

browserscan这个站要是知道的话,一定会想:这些人怎么这么坏~~

六、在线指纹验证网站:

  • https://abrahamjuliot.github.io/creepjs/
  • https://www.browserscan.net/

这篇关于014.修改chromium源码-修改webGL指纹(二)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1080879

相关文章

python修改字符串值的三种方法

《python修改字符串值的三种方法》本文主要介绍了python修改字符串值的三种方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学... 目录第一种方法:第二种方法:第三种方法:在python中,字符串对象是不可变类型,所以我们没办法直接

Mysql8.0修改配置文件my.ini的坑及解决

《Mysql8.0修改配置文件my.ini的坑及解决》使用记事本直接编辑my.ini文件保存后,可能会导致MySQL无法启动,因为MySQL会以ANSI编码读取该文件,解决方法是使用Notepad++... 目录Myhttp://www.chinasem.cnsql8.0修改配置文件my.ini的坑出现的问题

Java汇编源码如何查看环境搭建

《Java汇编源码如何查看环境搭建》:本文主要介绍如何在IntelliJIDEA开发环境中搭建字节码和汇编环境,以便更好地进行代码调优和JVM学习,首先,介绍了如何配置IntelliJIDEA以方... 目录一、简介二、在IDEA开发环境中搭建汇编环境2.1 在IDEA中搭建字节码查看环境2.1.1 搭建步

JAVA智听未来一站式有声阅读平台听书系统小程序源码

智听未来,一站式有声阅读平台听书系统 🌟&nbsp;开篇:遇见未来,从“智听”开始 在这个快节奏的时代,你是否渴望在忙碌的间隙,找到一片属于自己的宁静角落?是否梦想着能随时随地,沉浸在知识的海洋,或是故事的奇幻世界里?今天,就让我带你一起探索“智听未来”——这一站式有声阅读平台听书系统,它正悄悄改变着我们的阅读方式,让未来触手可及! 📚&nbsp;第一站:海量资源,应有尽有 走进“智听

Java ArrayList扩容机制 (源码解读)

结论:初始长度为10,若所需长度小于1.5倍原长度,则按照1.5倍扩容。若不够用则按照所需长度扩容。 一. 明确类内部重要变量含义         1:数组默认长度         2:这是一个共享的空数组实例,用于明确创建长度为0时的ArrayList ,比如通过 new ArrayList<>(0),ArrayList 内部的数组 elementData 会指向这个 EMPTY_EL

如何在Visual Studio中调试.NET源码

今天偶然在看别人代码时,发现在他的代码里使用了Any判断List<T>是否为空。 我一般的做法是先判断是否为null,再判断Count。 看了一下Count的源码如下: 1 [__DynamicallyInvokable]2 public int Count3 {4 [__DynamicallyInvokable]5 get

工厂ERP管理系统实现源码(JAVA)

工厂进销存管理系统是一个集采购管理、仓库管理、生产管理和销售管理于一体的综合解决方案。该系统旨在帮助企业优化流程、提高效率、降低成本,并实时掌握各环节的运营状况。 在采购管理方面,系统能够处理采购订单、供应商管理和采购入库等流程,确保采购过程的透明和高效。仓库管理方面,实现库存的精准管理,包括入库、出库、盘点等操作,确保库存数据的准确性和实时性。 生产管理模块则涵盖了生产计划制定、物料需求计划、

Spring 源码解读:自定义实现Bean定义的注册与解析

引言 在Spring框架中,Bean的注册与解析是整个依赖注入流程的核心步骤。通过Bean定义,Spring容器知道如何创建、配置和管理每个Bean实例。本篇文章将通过实现一个简化版的Bean定义注册与解析机制,帮助你理解Spring框架背后的设计逻辑。我们还将对比Spring中的BeanDefinition和BeanDefinitionRegistry,以全面掌握Bean注册和解析的核心原理。

两个月冲刺软考——访问位与修改位的题型(淘汰哪一页);内聚的类型;关于码制的知识点;地址映射的相关内容

1.访问位与修改位的题型(淘汰哪一页) 访问位:为1时表示在内存期间被访问过,为0时表示未被访问;修改位:为1时表示该页面自从被装入内存后被修改过,为0时表示未修改过。 置换页面时,最先置换访问位和修改位为00的,其次是01(没被访问但被修改过)的,之后是10(被访问了但没被修改过),最后是11。 2.内聚的类型 功能内聚:完成一个单一功能,各个部分协同工作,缺一不可。 顺序内聚:

音视频入门基础:WAV专题(10)——FFmpeg源码中计算WAV音频文件每个packet的pts、dts的实现

一、引言 从文章《音视频入门基础:WAV专题(6)——通过FFprobe显示WAV音频文件每个数据包的信息》中我们可以知道,通过FFprobe命令可以打印WAV音频文件每个packet(也称为数据包或多媒体包)的信息,这些信息包含该packet的pts、dts: 打印出来的“pts”实际是AVPacket结构体中的成员变量pts,是以AVStream->time_base为单位的显