14.Chromium指纹浏览器开发教程之WebGL指纹定制
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渲染器信息。
- 启用了扩展:如果启用,代码进一步处理获取显卡供应商的信息,并记录这些信息用于标识能力研究。这个扩展提供了一种方式来获取通常不公开的详细WebGL渲染器信息。
- 未启用拓展:如果扩展没有被启用,代码则会生成一个错误。错误指出无法获取请求的参数,因为相关的调试扩展没有启用。随后,代码返回一个空值作为函数的结果,表明操作未能成功执行。
要修改此处的WebGL厂商信息,可以选择在启用拓展时候修改,如果未启用就正常返回空值。通过传递名为webgl_vendor的命令行参数,即可完成厂商信息的修改。代码如下:
//ruyiconst 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());
可以看出结构上是和修改厂商信息没有太大区别的,依然可以在启用拓展的情况下对其中的显卡信息返回值进行定制修改。
相关文章:
14.Chromium指纹浏览器开发教程之WebGL指纹定制
WebGL指纹概述 当在浏览器打开的网页上浏览内容时,看到的大多是平面的、静态的图像和文字。但是有时想要在网页上看到更加生动、立体的图像,如3D游戏、虚拟现实应用等。这时,就需要用到WebGL。 简单来说,WebGL(Web G…...
GitHub SSH连接终极解决方案
GitHub SSH连接终极解决方案:443端口修改多场景故障排查指南 一、问题现象速查 当开发者执行以下命令时出现连接异常: ssh -T gitgithub.com常见报错类型: 经典端口阻塞ssh: connect to host github.com port 22: Connection refused密钥验…...
Git 中修改某个特定的commit提交内容
在 Git 中修改某个特定的提交(commit)通常需要使用 交互式变基(Interactive Rebase) 或 修改提交(Commit Amend)。以下是不同场景下的具体操作步骤: 一、修改最近的提交(最新提交&am…...
每日算法【双指针算法】(Day 1-移动零)
双指针算法 1.算法题目(移动零)2.讲解算法原理3.编写代码 1.算法题目(移动零) 2.讲解算法原理 数组划分,数组分块(快排里面最核心的一步)只需把0改为tmp 双指针算法:利用数组下标来…...
B端管理系统:企业运营的智慧大脑,精准指挥
B端管理系统的定义与核心功能 B端管理系统(Business Management System)是专门设计用于支持企业内部运作和外部业务交互的一套软件工具。它集成了多种功能模块,包括但不限于客户关系管理(CRM)、供应链管理(SCM)、人力资源管理(HRM)以及财务管…...
使用Java基于Geotools的SLD文件编程式创建与磁盘生成实战
前言 在地理信息系统(GIS)领域,地图的可视化呈现至关重要,而样式定义语言(SLD)文件为地图元素的样式配置提供了强大的支持。SLD 能够精确地定义地图图层中各类要素(如点、线、面、文本等&#x…...
Git 命令速查手册
听说用美图可以钓读者? 一、基础操作核心命令 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…...
PKI 公钥基础设施
PKI 的全称是公钥基础设施(Public Key Infrastructure),是一个基于公钥加密技术,为网络环境中的各种应用提供安全服务的基础设施,由多个部分组成,各部分协同工作以实现数字证书的管理、密钥的生成与管理以及…...
android测试硬件工具 安卓硬件测试命令
Android开发常用ADB命令大全 在Android开发过程中,ADB(Android Debug Bridge)是一个非常重要的调试工具。掌握这些命令可以大大提高开发效率。如果你正在使用克魔开发助手(Keymob)这样的开发工具,你会发现它已经集成了很多ADB功能,让调试变得…...
网络编程 - 4 ( TCP )
目录 TCP 流套接字编程 API 介绍 SeverSocket Socket 用 TCP 实现一个回显服务器 服务端 客户端 运行调试 第一个问题:PrintWriter 内置的缓冲区 - flush 刷新解决 第二个问题:上述代码中,需要进行 close 操作吗? 第三…...
OSPF综合实验(HCIP)
1,R5为ISP,其上只能配置Ip地址;R4作为企业边界路由器, 出口公网地址需要通过ppp协议获取,并进行chap认证 2,整个OSPF环境IP基于172.16.0.0/16划分; 3,所有设备均可访问R5的环回&…...
真实波幅策略思路
该策略是一种基于ATR(Average True Range)指标的交易策略,主要用于期货市场中的日内交易。策略的核心思想是利用ATR指标来识别市场的波动范围,并结合均线过滤来确定买入和卖出的时机。 交易逻辑思维 1. 数据准备与初始化 - 集合竞…...
ESB —— 企业集成架构的基石:功能、架构与应用全解析
企业服务总线(Enterprise Service Bus,ESB)是一种重要的企业级集成架构,以下为你详细介绍: 一、概念与定义 ESB 是一种基于面向服务架构(SOA)的中间件技术,它充当了企业内部不同应…...
leetcode 674. Longest Continuous Increasing Subsequence
目录 题目描述 第一步,明确并理解dp数组及下标的含义 第二步,分析明确并理解递推公式 第三步,理解dp数组如何初始化 第四步,理解遍历顺序 代码 题目描述 这是动态规划解决子序列问题的例子。与第300题的唯一区别就是&#…...
STM32 外部中断EXTI
目录 外部中断基础知识 STM32外部中断框架 STM32外部中断机制框架 复用功能 重映射 中断嵌套控制器NVIC 外部中断按键控制LED灯 外部中断基础知识 STM32外部中断框架 中断的概念:在主程序运行过程中,出现了特点的中断触发条件,使得…...
Linux:基础IO---动静态库
文章目录 1. 动静态库前置知识1.1 动静态库知识回顾1.2 什么是动静态库 2. 动静态库2.1 站在库的制作者的角度2.2 站在库的使用者的角度2.3 动态库是怎么被加载的(原理) 序:上一篇文章我们从认识到理解,从理解到实现场景ÿ…...
深度学习-torch,全连接神经网路
3. 数据集加载案例 通过一些数据集的加载案例,真正了解数据类及数据加载器。 3.1 加载csv数据集 代码参考如下 import torch from torch.utils.data import Dataset, DataLoader import pandas as pd class MyCsvDataset(Dataset):def __init__(self, fil…...
SQL注入相关知识
一、布尔盲注 1、布尔盲简介 布尔盲注是一种SQL注入攻击技术,用于在无法直接获取数据库查询结果的情况下,通过页面的响应来判断注入语句的真假,从而获取数据库中的敏感信息 2、布尔盲注工作原理 布尔盲注的核心在于利用SQL语句的布尔逻辑…...
Codex CLI - 自然语言命令行界面
本文翻译整理自: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…...
pycharm中怎么解决系统cuda版本高于pytorch可以支持的版本的问题?
在PyCharm中安装与系统CUDA版本不一致的PyTorch是可行的。以下是解决方案的步骤: 1. 确认系统驱动兼容性 检查NVIDIA驱动支持的CUDA版本:运行 nvidia-smi,右上角显示的CUDA版本是驱动支持的最高版本。只要该版本不低于PyTorch所需的CUDA版本…...
Day57 | 79. 单词搜索、89. 格雷编码
79. 单词搜索 题目链接:79. 单词搜索 - 力扣(LeetCode) 题目难度:中等 代码: class Solution {public boolean exist(char[][] board, String word) {char[] wordsword.toCharArray();for(int i0;i<board.lengt…...
清华《数据挖掘算法与应用》K-means聚类算法
使用k均值聚类算法对表4.1中的数据进行聚类。代码参考P281。 创建一个名为 testSet.txt 的文本文件,将以下内容复制粘贴进去保存即可: 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 中…...
深入解析进程与线程:区别、联系及Java实现
引言 在现代操作系统中,进程和线程是并发编程的两大核心概念。理解它们的区别与联系对开发高性能、高可靠性的程序至关重要。本文将通过原理分析和Java代码示例,深入探讨这两个关键概念。 一、基本概念 1.1 进程(Process) 定义&…...
【Flutter深度解析】多线程编程
Flutter作为单线程模型的框架,在处理复杂计算时可能会遇到性能瓶颈。本文将全面剖析Flutter中的多线程编程方案,帮助你充分利用设备的多核性能,构建流畅的Dart应用。 一、Flutter线程模型基础 1. Dart的单线程事件循环 Flutter应用运行在单…...
HAL库配置RS485+DMA+空闲中断收发数据
前言: (1)DMA是单片机集成在芯片内部的一个数据搬运工,它可以代替单片机对数据进行传输、存储,节约CPU资源。一般应用场景,ADC多通道采集,串口收发(频繁进入接收中断)&a…...
【java实现+4种变体完整例子】排序算法中【计数排序】的详细解析,包含基础实现、常见变体的完整代码示例,以及各变体的对比表格
以下是计数排序的详细解析,包含基础实现、常见变体的完整代码示例,以及各变体的对比表格: 一、计数排序基础实现 原理 通过统计每个元素的出现次数,按顺序累加得到每个元素的最终位置,并填充到结果数组中。 代码示…...
嵌入式单片机开发 - Keil MDK 编译与烧录程序
Keil MDK 编译程序 1、Keil MDK 编译按钮 Build 按钮:重新编译整个工程的所有源文件,无论它们是否被修改过 Rebuild 按钮:仅编译修改过的文件及其依赖项,未修改的文件直接使用之前的编译结果 2、Keil MDK 编译结果 linking... …...
裂项法、分式分解法——复杂分式的拆解
目录 一、裂项法 1. 核心思想 2. 适用场景 3. 步骤 4. 例题 二、分式分解 1. 核心思想 2. 适用场景 3. 步骤 4.例题 一、裂项法 1. 核心思想 将一项拆解为多项之差,使得在求和时中间项相互抵消,最终仅剩首尾少数项。 2. 适用场景 级数求和…...
