14.Chromium指纹浏览器开发教程之WebGL指纹定制

news2025/5/11 14:37:35

WebGL指纹概述

当在浏览器打开的网页上浏览内容时,看到的大多是平面的、静态的图像和文字。但是有时想要在网页上看到更加生动、立体的图像,如3D游戏、虚拟现实应用等。这时,就需要用到WebGL。

简单来说,WebGL(Web Graphics Library)是一种在网页浏览器中运行的技术,它可以用计算机程序在网页上展示出立体的、动态的图像。它基于OpenGL(一种专门用于处理图形的开放标准)。使用WebGL可以在网页上创建各种各样的3D场景和动画。例如可以在网页上看到一个旋转的立方体,或者一个飞行的飞机,甚至是一个完整的3D游戏世界,这些都是通过编写一些特殊的程序代码来实现的,这些代码会告诉浏览器如何绘制这些图像,并且如何根据用户的操作来进行交互。WebGL的一个很大的优势是,它可以在几乎所有现代网页浏览器上运行,而且不需要用户安装任何额外的插件或软件。这意味着,无论是用计算机、平板电脑还是手机,只要有一个支持WebGL的浏览器,就可以享受到生动的3D图像。

浏览器中的WebGL指纹是一种用于识别和跟踪用户的浏览器的技术。它是通过获取浏览器在使用WebGL时的硬件和软件配置信息,如显卡型号、驱动版本、操作系统等,然后通过这些信息生成一个唯一的标识符来实现的。由于每台计算机的硬件和软件配置都不相同,因此生成的WebGL指纹也是唯一的,可以用来识别用户的设备。

图4-5是本机在browserleaks网站查看的WebGL指纹信息,可以看出该指纹信息搜集的是WebGL上下文和显卡相关信息。因此,如果想修改WebGL指纹,只需要对这类硬件信息进行修改即可。

WebGL指纹获取

本节会编写一个JavaScript指纹检测脚本,用来获取WebGL相关信息,由此得出浏览器的WebGL指纹。通过明晰指纹获取的流程,可以更容易地找到指纹的修改点。以下是获取浏览器WebGL指纹信息的JavaScript代码:

function getUnmaskedInfo() {
   var canvas = document.createElement('canvas');
   var gl;
   // 获取WebGL上下文    
   try {
       gl = canvas.getContext('webgl') ||

canvas.getContext('experimental-webgl');
   } catch (e) {
       return "WebGL not supported or disabled";
   }
   if (!gl) {
       return "WebGL not supported or disabled";
   }
   var unmaskedVendor = "";
   var unmaskedRenderer = "";
   var extensions = gl.getSupportedExtensions();
   if (extensions.indexOf('WEBGL_debug_renderer_info') !== -1) {
       var debugInfo = gl.getExtension('WEBGL_debug_renderer_info');
       unmaskedVendor = gl.getParameter(debugInfo.UNMASKED_VENDOR_WEBGL);
       unmaskedRenderer = gl.getParameter(debugInfo.UNMASKED_RENDERER_WEBGL);
   } else {
       return "WEBGL_debug_renderer_info extension not supported";
   }
   var info = {
       "Unmasked Vendor": unmaskedVendor,
       "Unmasked Renderer": unmaskedRenderer
   };
   info.vendor = gl.getParameter(gl.VENDOR);
   info.renderer = gl.getParameter(gl.RENDERER);
   info.version = gl.getParameter(gl.VERSION);
   info.maxTextureSize = gl.getParameter(gl.MAX_TEXTURE_SIZE);
   info.maxRenderBufferSize = gl.getParameter(gl.MAX_RENDERBUFFER_SIZE);
   info.maxViewportDims = gl.getParameter(gl.MAX_VIEWPORT_DIMS);
   info.extensions = gl.getSupportedExtensions();
   return info;
}
// 调用函数并输出结果        
var unmaskedInfo = getUnmaskedInfo();
console.log(unmaskedInfo);

将上述代码运行在浏览器之中,即可打印出WebGL相关信息。WebGL指纹是通过搜集如图4-6所示的信息,经过特殊编码后生成哈希值,从而得到用户的浏览器指纹信息的。

这段代码是用来获取用户浏览器中WebGL相关信息的函数。在这段代码中,getUnmaskedInfo首先创建一个canvas元素,然后尝试获取WebGL上下文。如果获取成功,则尝试获取更多的WebGL相关信息,如厂商、渲染器、版本等,并返回一个包含这些信息的对象。如果获取不成功,则返回相应的错误信息。最后,通过调用getUnmaskedInfo来获取浏览器中的WebGL信息,并将其打印到控制台中。

利用这些WebGL信息,就可以生成任意编码的值作为指纹信息,传递给网站服务端进行判别。

WebGL指纹修改

由于WebGL相关信息众多,要想成功修改WebGL指纹,需要对要进行指纹修改的网站进行具体分析,了解其搜集的指纹信息进行对症下药,才能顺利完成指纹修改。本节将带领读者修改WebGL中的Debug Renderer info信息,代码如下:

unmaskedVendor = gl.getParameter(debugInfo.UNMASKED_VENDOR_WEBGL);

unmaskedRenderer = gl.getParameter(debugInfo.UNMASKED_RENDERER_WEBGL);

gl.getParamete是WebGL API中的一个函数,用于获取特定参数的当前值。它接受一个参数,该参数指定要查询的信息类型,并返回相应的值。UNMASKED_VENDOR_WEBGL用于获取WebGL渲染上下文的厂商信息,而UNMASKED_RENDERER_WEBGL用于获取渲染器信息。通常情况下,修改这两个值,WebGL相关指纹信息就会发生改变。

关于WebGL指纹信息的代码文件位于“src\third_party\blink\renderer\modules\webgl”当中,其中的webgl_rendering_context_base.cc文件包含了最基础的WebGL渲染信息。

先来修改其中的vendor厂商信息,具体代码如下:

case WebGLDebugRendererInfo::kUnmaskedVendorWebgl:

  if (ExtensionEnabled(kWebGLDebugRendererInfoName)) {

    if (IdentifiabilityStudySettings::Get()->ShouldSampleType(

            blink::IdentifiableSurface::Type::kWebGLParameter)) {

      RecordIdentifiableGLParameterDigest(

          pname, IdentifiabilityBenignStringToken(

                     String(ContextGL()->GetString(GL_VENDOR))));

    }

    return WebGLAny(script_state,

                    String(ContextGL()->GetString(GL_VENDOR)));

  }

  SynthesizeGLError(

      GL_INVALID_ENUM, "getParameter",

      "invalid parameter name, WEBGL_debug_renderer_info not enabled");

  return ScriptValue::CreateNull(script_state->GetIsolate());

可以看出,该代码判断到条件语句WebGLDebugRendererInfo::kUnmaskedVendorWebgl的时候,会判别kWebGLDebugRendererInfoName扩展是否已经启用,该拓展可以提供额外的WebGL渲染器信息。

  1. 启用了扩展:如果启用,代码进一步处理获取显卡供应商的信息,并记录这些信息用于标识能力研究。这个扩展提供了一种方式来获取通常不公开的详细WebGL渲染器信息。
  2. 未启用拓展:如果扩展没有被启用,代码则会生成一个错误。错误指出无法获取请求的参数,因为相关的调试扩展没有启用。随后,代码返回一个空值作为函数的结果,表明操作未能成功执行。

要修改此处的WebGL厂商信息,可以选择在启用拓展时候修改,如果未启用就正常返回空值。通过传递名为webgl_vendor的命令行参数,即可完成厂商信息的修改。代码如下:

//ruyi

const base::CommandLine* ruyi_command_line =

base::CommandLine::ForCurrentProcess();

if (ruyi_command_line->HasSwitch(blink::switches::kRuyi)) {

    const std::string ruyi_fp = ruyi_command_line->

GetSwitchValueASCII(blink::switches::kRuyi);

    absl::optional<base::Value> json_reader =

base::JSONReader::Read(ruyi_fp);

    std::string webgl_vendor =

*(json_reader->GetDict().FindString("webgl_vendor"));

    return WebGLAny(script_state,String(webgl_vendor));

}

//ruyi end

接着,再来看看显卡信息,代码如下:

case WebGLDebugRendererInfo::kUnmaskedRendererWebgl:

      if (ExtensionEnabled(kWebGLDebugRendererInfoName)) {

        if (IdentifiabilityStudySettings::Get()->ShouldSampleType(

                blink::IdentifiableSurface::Type::kWebGLParameter)) {

          RecordIdentifiableGLParameterDigest(

              pname, IdentifiabilityBenignStringToken(

                         String(ContextGL()->GetString(GL_RENDERER))));

        }

        return WebGLAny(script_state,

                        String(ContextGL()->GetString(GL_RENDERER)));

      }

      SynthesizeGLError(

          GL_INVALID_ENUM, "getParameter",

          "invalid parameter name, WEBGL_debug_renderer_info not enabled");

      return ScriptValue::CreateNull(script_state->GetIsolate());

可以看出结构上是和修改厂商信息没有太大区别的,依然可以在启用拓展的情况下对其中的显卡信息返回值进行定制修改。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2338510.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

GitHub SSH连接终极解决方案

GitHub SSH连接终极解决方案&#xff1a;443端口修改多场景故障排查指南 一、问题现象速查 当开发者执行以下命令时出现连接异常&#xff1a; ssh -T gitgithub.com常见报错类型&#xff1a; 经典端口阻塞ssh: connect to host github.com port 22: Connection refused密钥验…

每日算法【双指针算法】(Day 1-移动零)

双指针算法 1.算法题目&#xff08;移动零&#xff09;2.讲解算法原理3.编写代码 1.算法题目&#xff08;移动零&#xff09; 2.讲解算法原理 数组划分&#xff0c;数组分块&#xff08;快排里面最核心的一步&#xff09;只需把0改为tmp 双指针算法&#xff1a;利用数组下标来…

B端管理系统:企业运营的智慧大脑,精准指挥

B端管理系统的定义与核心功能 B端管理系统&#xff08;Business Management System&#xff09;是专门设计用于支持企业内部运作和外部业务交互的一套软件工具。它集成了多种功能模块&#xff0c;包括但不限于客户关系管理(CRM)、供应链管理(SCM)、人力资源管理(HRM)以及财务管…

使用Java基于Geotools的SLD文件编程式创建与磁盘生成实战

前言 在地理信息系统&#xff08;GIS&#xff09;领域&#xff0c;地图的可视化呈现至关重要&#xff0c;而样式定义语言&#xff08;SLD&#xff09;文件为地图元素的样式配置提供了强大的支持。SLD 能够精确地定义地图图层中各类要素&#xff08;如点、线、面、文本等&#x…

Git 命令速查手册

听说用美图可以钓读者&#xff1f; 一、基础操作核心命令 1. 仓库初始化与克隆 命令作用示例git init创建新仓库git init my-projectgit clone克隆远程仓库git clone [https://github.com/user/repo.git](https://github.com/user/repo.git)git remote add关联远程仓库git re…

网络编程 - 4 ( TCP )

目录 TCP 流套接字编程 API 介绍 SeverSocket Socket 用 TCP 实现一个回显服务器 服务端 客户端 运行调试 第一个问题&#xff1a;PrintWriter 内置的缓冲区 - flush 刷新解决 第二个问题&#xff1a;上述代码中&#xff0c;需要进行 close 操作吗&#xff1f; 第三…

OSPF综合实验(HCIP)

1&#xff0c;R5为ISP&#xff0c;其上只能配置Ip地址&#xff1b;R4作为企业边界路由器&#xff0c; 出口公网地址需要通过ppp协议获取&#xff0c;并进行chap认证 2&#xff0c;整个OSPF环境IP基于172.16.0.0/16划分&#xff1b; 3&#xff0c;所有设备均可访问R5的环回&…

真实波幅策略思路

该策略是一种基于ATR&#xff08;Average True Range&#xff09;指标的交易策略&#xff0c;主要用于期货市场中的日内交易。策略的核心思想是利用ATR指标来识别市场的波动范围&#xff0c;并结合均线过滤来确定买入和卖出的时机。 交易逻辑思维 1. 数据准备与初始化 - 集合竞…

leetcode 674. Longest Continuous Increasing Subsequence

目录 题目描述 第一步&#xff0c;明确并理解dp数组及下标的含义 第二步&#xff0c;分析明确并理解递推公式 第三步&#xff0c;理解dp数组如何初始化 第四步&#xff0c;理解遍历顺序 代码 题目描述 这是动态规划解决子序列问题的例子。与第300题的唯一区别就是&#…

STM32 外部中断EXTI

目录 外部中断基础知识 STM32外部中断框架 STM32外部中断机制框架 复用功能 重映射 中断嵌套控制器NVIC 外部中断按键控制LED灯 外部中断基础知识 STM32外部中断框架 中断的概念&#xff1a;在主程序运行过程中&#xff0c;出现了特点的中断触发条件&#xff0c;使得…

Linux:基础IO---动静态库

文章目录 1. 动静态库前置知识1.1 动静态库知识回顾1.2 什么是动静态库 2. 动静态库2.1 站在库的制作者的角度2.2 站在库的使用者的角度2.3 动态库是怎么被加载的&#xff08;原理&#xff09; 序&#xff1a;上一篇文章我们从认识到理解&#xff0c;从理解到实现场景&#xff…

深度学习-torch,全连接神经网路

3. 数据集加载案例 通过一些数据集的加载案例&#xff0c;真正了解数据类及数据加载器。 3.1 加载csv数据集 代码参考如下 import torch from torch.utils.data import Dataset, DataLoader import pandas as pd ​ ​ class MyCsvDataset(Dataset):def __init__(self, fil…

Codex CLI - 自然语言命令行界面

本文翻译整理自&#xff1a;https://github.com/microsoft/Codex-CLI 文章目录 一、关于 Codex CLI相关链接资源 二、安装系统要求安装步骤 三、基本使用1、基础操作2、多轮模式 四、命令参考五、提示工程与上下文文件自定义上下文 六、故障排查七、FAQ如何查询可用OpenAI引擎&…

实现窗口函数

java 实现窗口函数 public class SlidingWin {public static void main(String[] args) {SlidingWin slidingWin new SlidingWin();double v slidingWin.SlidWin(2);System.out.println(v);}public double SlidWin(int k){int [] array new int[]{2,4,5,6,9,10,12,23,1,3,8…

清华《数据挖掘算法与应用》K-means聚类算法

使用k均值聚类算法对表4.1中的数据进行聚类。代码参考P281。 创建一个名为 testSet.txt 的文本文件&#xff0c;将以下内容复制粘贴进去保存即可&#xff1a; 0 0 1 2 3 1 8 8 9 10 10 7 表4.1 # -*- coding: utf-8 -*- """ Created on Thu Apr 17 16:59:58 …

MATLAB - 小车倒立摆的非线性模型预测控制(NMPC)

系列文章目录 目录 系列文章目录 前言 一、摆锤/小车组件 二、系统方程 三、控制目标 四、控制结构 五、创建非线性 MPC 控制器 六、指定非线性设备模型 七、定义成本和约束 八、验证非线性 MPC 控制器 九、状态估计 十、MATLAB 中的闭环仿真 十一、使用 MATLAB 中…

HAL库配置RS485+DMA+空闲中断收发数据

前言&#xff1a; &#xff08;1&#xff09;DMA是单片机集成在芯片内部的一个数据搬运工&#xff0c;它可以代替单片机对数据进行传输、存储&#xff0c;节约CPU资源。一般应用场景&#xff0c;ADC多通道采集&#xff0c;串口收发&#xff08;频繁进入接收中断&#xff09;&a…

【java实现+4种变体完整例子】排序算法中【计数排序】的详细解析,包含基础实现、常见变体的完整代码示例,以及各变体的对比表格

以下是计数排序的详细解析&#xff0c;包含基础实现、常见变体的完整代码示例&#xff0c;以及各变体的对比表格&#xff1a; 一、计数排序基础实现 原理 通过统计每个元素的出现次数&#xff0c;按顺序累加得到每个元素的最终位置&#xff0c;并填充到结果数组中。 代码示…

嵌入式单片机开发 - Keil MDK 编译与烧录程序

Keil MDK 编译程序 1、Keil MDK 编译按钮 Build 按钮&#xff1a;重新编译整个工程的所有源文件&#xff0c;无论它们是否被修改过 Rebuild 按钮&#xff1a;仅编译修改过的文件及其依赖项&#xff0c;未修改的文件直接使用之前的编译结果 2、Keil MDK 编译结果 linking... …

裂项法、分式分解法——复杂分式的拆解

目录 一、裂项法 1. 核心思想 2. 适用场景 3. 步骤 4. 例题 二、分式分解 1. 核心思想 2. 适用场景 3. 步骤 4.例题 一、裂项法 1. 核心思想 将一项拆解为多项之差&#xff0c;使得在求和时中间项相互抵消&#xff0c;最终仅剩首尾少数项。 2. 适用场景 级数求和…