指纹浏览器编译-修改canvas指纹(高级)
一、canvas指纹是什么
- 之前介绍过canvas指纹和常见网站绕过canvas指纹,插眼: https://blog.csdn.net/w1101662433/article/details/137959179
二、为啥有更高级的canvas指纹
- 众所周知,creepjs和browserscan这2个网站对指纹的检测比较严格,随机修改了指纹后,很容易无法通过网站的反指纹修改检测,被识别到指纹被篡改。
- 上一期的canvas指纹修改没有通过browserscan的canvas指纹检测,我们继续针对性加强。
三、修改源码
- 打开源码文件
\third_party\blink\renderer\modules\canvas\canvas2d\base_rendering_context_2d.cc
1.头部加上(随便加在一个#include
后面)
#include <string>
#include <iostream>
#include <cstdlib>
#include <ctime>
2.找到下面的代码
void BaseRenderingContext2D::setFillStyle(v8::Isolate* isolate,
v8::Local<v8::Value> value,
ExceptionState& exception_state) {
V8CanvasStyle v8_style;
if (!ExtractV8CanvasStyle(isolate, value, v8_style, exception_state))
return;
ValidateStateStack();
UpdateIdentifiabilityStudyBeforeSettingStrokeOrFill(v8_style,
CanvasOps::kSetFillStyle);
CanvasRenderingContext2DState& state = GetState();
switch (v8_style.type) {
case V8CanvasStyleType::kCSSColorValue:
state.SetFillColor(v8_style.css_color_value);
break;
case V8CanvasStyleType::kGradient:
state.SetFillGradient(v8_style.gradient);
break;
case V8CanvasStyleType::kPattern:
if (!origin_tainted_by_content_ && !v8_style.pattern->OriginClean())
SetOriginTaintedByContent();
state.SetFillPattern(v8_style.pattern);
break;
case V8CanvasStyleType::kString: {
if (v8_style.string == state.UnparsedFillColor()) {
return;
}
Color parsed_color = Color::kTransparent;
if (!ExtractColorFromV8ValueAndUpdateCache(v8_style, parsed_color)) {
return;
}
if (state.FillStyle().IsEquivalentColor(parsed_color)) {
state.SetUnparsedFillColor(v8_style.string);
return;
}
state.SetFillColor(parsed_color);
break;
}
}
state.SetUnparsedFillColor(v8_style.string);
state.ClearResolvedFilter();
}
注意:最新代码可能和当前代码有略微差异,但基本逻辑是一样。通过改变canvas颜色来改变指纹。
3.替换为
void BaseRenderingContext2D::setFillStyle(v8::Isolate* isolate,
v8::Local<v8::Value> value,
ExceptionState& exception_state) {
V8CanvasStyle v8_style;
if (!ExtractV8CanvasStyle(isolate, value, v8_style, exception_state))
return;
ValidateStateStack();
UpdateIdentifiabilityStudyBeforeSettingStrokeOrFill(v8_style,
CanvasOps::kSetFillStyle);
CanvasRenderingContext2DState& state = GetState();
// 这里追加2行,这里可以过creepjs
srand((int)time(NULL));
state.SetStrokeColor(Color::FromRGBALegacy(rand() % 5, rand() % 6,rand() % 7, rand() % 255));
switch (v8_style.type) {
case V8CanvasStyleType::kCSSColorValue:
state.SetFillColor(v8_style.css_color_value);
break;
case V8CanvasStyleType::kGradient:
state.SetFillGradient(v8_style.gradient);
break;
case V8CanvasStyleType::kPattern:
if (!origin_tainted_by_content_ && !v8_style.pattern->OriginClean())
SetOriginTaintedByContent();
state.SetFillPattern(v8_style.pattern);
break;
case V8CanvasStyleType::kString: {
if (v8_style.string == state.UnparsedFillColor()) {
return;
}
Color parsed_color = Color::kTransparent;
if (!ExtractColorFromV8ValueAndUpdateCache(v8_style, parsed_color)) {
return;
}
if (state.FillStyle().IsEquivalentColor(parsed_color)) {
state.SetUnparsedFillColor(v8_style.string);
return;
}
//这里追加1行,这里用来过browserscan
parsed_color = Color::FromRGBALegacy(parsed_color.Param1() + rand() % 5, parsed_color.Param1()+ rand() % 6, parsed_color.Param2() + rand() % 7, parsed_color.Alpha()*255);
state.SetFillColor(parsed_color);
break;
}
}
state.SetUnparsedFillColor(v8_style.string);
state.ClearResolvedFilter();
}
注意:由于browserscan会同一时间点生成2次canvas指纹,进行对比,纯随机的话会无法绕过反修改指纹检测。
所以这里巧妙的运用了rand(),同一时间点生成的随机数是相同的,完美绕过。
4.编译
ninja -C out/Default chrome
三、绕过creepjs的反修改指纹检测
- 编译后发现,creepjs检测到了我们修过指纹
为了绕过他的检测,继续修改源码:
1.找到
ImageData* BaseRenderingContext2D::getImageDataInternal(
int sx,
int sy,
int sw,
int sh,
ImageDataSettings* image_data_settings,
ExceptionState& exception_state) {
2.改成:
ImageData* BaseRenderingContext2D::getImageDataInternal(
int sx,
int sy,
int sw,
int sh,
ImageDataSettings* image_data_settings,
ExceptionState& exception_state) {
// 这里追加一行
if (sh==1){return nullptr;}
注意:就是追加了一行代码,让sh==1时,canvas的getImageDate会返回null,完美绕过creepjs的检测。
3.再编译
ninja -C out/Default chrome
四、在线指纹验证网站:
- https://abrahamjuliot.github.io/creepjs/
- https://www.browserscan.net/