0


014.指纹浏览器开发-修改webGL指纹(二)

指纹浏览器开发-修改webGL指纹(二)

一、webGL指纹是什么

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

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

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

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

  • 有攻才有防,先看看网站是如何通过js获取你的webGL指纹的。
  • 将下面的代码复制到F12控制台,就可以获取显示你的webGL指纹了。
asyncfunctionsha256(message){// 把字符串转换为Uint8Arrayconst msgBuffer =newTextEncoder().encode(message);// 计算散列值const hashBuffer =await crypto.subtle.digest('SHA-256', msgBuffer);// 转换为数组const hashArray = Array.from(newUint8Array(hashBuffer));// 转换为16进制字符串const hashHex = hashArray.map(b=> b.toString(16).padStart(2,'0')).join('');return hashHex;}functiongetWebGLFingerprint(){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 =newFloat32Array([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.替换为
intgetRandomIntForFoo12Modern(){static std::mt19937 generator(static_cast<unsignedlong>(time(NULL)));// 静态以确保只初始化一次
    std::uniform_int_distribution<int>distribution(0,9);returndistribution(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.");returnString();}if(!OriginClean()){
    exception_state.ThrowSecurityError("Tainted canvases may not be exported.");returnString();}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.");returnString();}if(!OriginClean()){
    exception_state.ThrowSecurityError("Tainted canvases may not be exported.");returnString();}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这个站要是知道的话,一定会想:这些人怎么这么坏~~

六、在线指纹验证网站:

标签: chrome

本文转载自: https://blog.csdn.net/w1101662433/article/details/139830277
版权归原作者 王辉辉的猫 所有, 如有侵权,请联系我们删除。

“014.指纹浏览器开发-修改webGL指纹(二)”的评论:

还没有评论