随机指纹chromium编译-传参固定指纹(二)
目标:
目标1:启动chrome时,传入参数--fingerprints=123123123(正整数),则指纹固定不变。当正整数更换,则获得一个新指纹。目标2:启动chrome时,不传参数--fingerprints,则每个访问请求的指纹全部随机生成。
注意的点
之前的随机生成指纹的代码都需要删掉,全部替换新代码。由于我接受的是int类型,所以--fingerprints只能传整数,且最大值为2,147,483,647这里我默认大家都看过我之前的博客,对修改源码的流程已经非常熟悉。
一、固定字体指纹
之前发现字体指纹的检测方式特别多,这里搞了个偷懒方式,一招全部解决。。 这个偷懒的方式就是:随机将字体偷换成别的字体。。不过这样做可能会出现页面上的字体发生改变。各位集帅们按需更改。
打开:\third_party\blink\renderer\core\css\css_font_family_value.cc
#include "base/command_line.h"
1. 定义一个抽数函数:
std::vector
srand(seed); // 设置随机数生成器的种子
std::vector
for (const auto& item : arr) {
if (rand() % 2 == 0) { // 随机选择是否保留每个元素
result.push_back(item);
}
}
return result;
}
2.找到 CSSFontFamilyValue::Create 函数
CSSFontFamilyValue* CSSFontFamilyValue::Create(
const AtomicString& family_name) {
if (family_name.IsNull()) {
return MakeGarbageCollected
}
CSSValuePool::FontFamilyValueCache::AddResult entry =
CssValuePool().GetFontFamilyCacheEntry(family_name);
if (!entry.stored_value->value) {
entry.stored_value->value =
MakeGarbageCollected
}
return entry.stored_value->value.Get();
}
3.替换成下面的代码
CSSFontFamilyValue* CSSFontFamilyValue::Create(
const AtomicString& family_name) {
// 开始追加=======================================
base::CommandLine* base_command_line = base::CommandLine::ForCurrentProcess();
std::string ignores = base_command_line->GetSwitchValueASCII("ignores");
if(ignores.find("fonts") == std::string::npos){
std::vector
int seed;
if (base_command_line->HasSwitch("fingerprints")) {
std::istringstream(base_command_line->GetSwitchValueASCII("fingerprints")) >> seed;
}else{
auto now = std::chrono::system_clock::now();
std::time_t now_time_t = std::chrono::system_clock::to_time_t(now);
seed = static_cast
}
std::string now_font_str = "";
AtomicString tmp_family_name("");
for (const std::string& font : stringsAarry) {
tmp_family_name = AtomicString (String(font));
if (tmp_family_name==family_name){
now_font_str = font;
break;
}
}
AtomicString res_family("monospace");
auto modifiedArray = randomlyRemoveElements(stringsAarry, seed);
if (std::find(modifiedArray.begin(), modifiedArray.end(), now_font_str) != modifiedArray.end()) {
return MakeGarbageCollected
}
}
// 结束追加=======================================
// 以下是原函数内容
if (family_name.IsNull()) {
return MakeGarbageCollected
}
CSSValuePool::FontFamilyValueCache::AddResult entry =
CssValuePool().GetFontFamilyCacheEntry(family_name);
if (!entry.stored_value->value) {
entry.stored_value->value =
MakeGarbageCollected
}
return entry.stored_value->value.Get();
}
二、固定audio指纹:
找到 /third_party/blink/renderer/modules/webaudio/offline_audio_context.cc
#include
#include "base/command_line.h"
int getRandomIntForFoo6Modern() {
static std::mt19937 generator(static_cast
std::uniform_int_distribution
return distribution(generator);
}
OfflineAudioContext::OfflineAudioContext(LocalDOMWindow* window,
unsigned number_of_channels,
uint32_t number_of_frames,
float sample_rate,
ExceptionState& exception_state)
: BaseAudioContext(window, kOfflineContext),
total_render_frames_(number_of_frames) {
base::CommandLine* base_command_line = base::CommandLine::ForCurrentProcess();
int tmp;
if (base_command_line->HasSwitch("fingerprints")) {
std::istringstream(base_command_line->GetSwitchValueASCII("fingerprints")) >> tmp;
}else{
tmp=getRandomIntForFoo6Modern();
}
tmp = tmp%99;
destination_node_ = OfflineAudioDestinationNode::Create(
this, number_of_channels, number_of_frames , sample_rate+tmp);
Initialize();
}
三、webGL指纹
找到 \third_party\blink\renderer\core\html\canvas\html_canvas_element.cc
#include "base/command_line.h"
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
if (v8_value->IsNumber())
quality = v8_value.As
}
String data = ToDataURLInternal(mime_type, quality, kBackBuffer);
TRACE_EVENT_INSTANT(
TRACE_DISABLED_BY_DEFAULT("identifiability.high_entropy_api"),
"CanvasReadback", "data_url", data.Utf8());
//这里追加几行
base::CommandLine* base_command_line = base::CommandLine::ForCurrentProcess();
int tmp;
std::istringstream(base_command_line->GetSwitchValueASCII("fingerprints")) >> tmp;
int randomNum;
if (base_command_line->HasSwitch("fingerprints")) {
randomNum = tmp%999;
}else{
srand((int)time(NULL));
randomNum = rand()%999;
}
std::string spaces(randomNum, ' ');
data = data + String(spaces);
//LOG(ERROR) << "data:('" << data << "') data";
return data;
}
原理是修改toDataURL()函数,给结尾处随机加上多个空格。 这个函数许多网站生成canvas指纹最后步骤也会使用,我们就顺便把修改canvas指纹也加强了。
四、固定canvas指纹
打开\third_party\blink\renderer\modules\canvas\canvas2d\base_rendering_context_2d.cc
void BaseRenderingContext2D::setFillStyle(v8::Isolate* isolate,
v8::Local
ExceptionState& exception_state) {
V8CanvasStyle v8_style;
if (!ExtractV8CanvasStyle(isolate, value, v8_style, exception_state))
return;
ValidateStateStack();
UpdateIdentifiabilityStudyBeforeSettingStrokeOrFill(v8_style,
CanvasOps::kSetFillStyle);
CanvasRenderingContext2DState& state = GetState();
// 追加
base::CommandLine* base_command_line = base::CommandLine::ForCurrentProcess();
int tmp;
if (base_command_line->HasSwitch("fingerprints")) {
std::istringstream(base_command_line->GetSwitchValueASCII("fingerprints")) >> tmp;
}else{
auto now = std::chrono::system_clock::now();
std::time_t now_time_t = std::chrono::system_clock::to_time_t(now);
tmp = static_cast
}
state.SetStrokeColor(Color::FromRGBALegacy(tmp % 5, tmp % 6,tmp % 7, tmp % 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行
parsed_color = Color::FromRGBALegacy(parsed_color.Param1() + tmp % 5, parsed_color.Param1()+ tmp % 6, parsed_color.Param2() + tmp % 7, parsed_color.Alpha()*255);
state.SetFillColor(parsed_color);
break;
}
}
state.SetUnparsedFillColor(v8_style.string);
state.ClearResolvedFilter();
}
原理是随机微调canvas的RGB颜色。
ImageData* BaseRenderingContext2D::getImageDataInternal(
int sx,
int sy,
int sw,
int sh,
ImageDataSettings* image_data_settings,
ExceptionState& exception_state) {
// 这里追加一行
if (sh==1){return nullptr;}
这里追加一行是为了应对creepjs的反指纹检测。
五、固定ja4指纹
1.给utility进程追加参数
打开 \content\browser\utility_process_host.cc
cmd_line->AppendSwitchASCII(switches::kProcessType,
switches::kUtilityProcess);
替换为
cmd_line->AppendSwitchASCII(switches::kProcessType,
switches::kUtilityProcess);
const base::CommandLine* base_command_line = base::CommandLine::ForCurrentProcess();
if (base_command_line->HasSwitch("fingerprints")) {
const std::string tmp = base_command_line->GetSwitchValueASCII("fingerprints");
cmd_line->AppendSwitchASCII("fingerprints", tmp);
}
2. 改ja4指纹
打开 \net\socket\ssl_client_socket_impl.cc
定义:
std::vector
srand(seed); // 设置随机数生成器的种子
std::vector
for (const auto& item : arr) {
if (rand() % 2 == 0) { // 随机选择是否保留每个元素
result.push_back(item);
}
}
return result;
}
找到:
std::string command("ALL:!aPSK:!ECDSA+SHA1:!3DES");
替换成:
// std::string command("ALL:!aPSK:!ECDSA+SHA1:!3DES");
std::string command("ALL");
std::vector
base::CommandLine* base_command_line = base::CommandLine::ForCurrentProcess();
int seed;
if (base_command_line->HasSwitch("fingerprints")) {
std::istringstream(base_command_line->GetSwitchValueASCII("fingerprints")) >> seed;
}else{
auto now = std::chrono::system_clock::now();
std::time_t now_time_t = std::chrono::system_clock::to_time_t(now);
seed = static_cast
}
auto modifiedArray = randomlyRemoveElements(stringsAarry, seed);
for (const std::string& key : modifiedArray) {
command.append(key);
}
原理是随机抽取部分加密函数给去掉。
六、固定plugins指纹
修改 /third_party/blink/renderer/modules/plugins/dom_plugin.cc
方法在上一篇博客里有:插眼传送
七、关于更新
本来是打算停更了,但是收到热心小伙伴的红包,半夜坐起来再更一波。。 至于后续,看心情