补浏览器环境

news2025/1/8 5:49:27

一,导言

// global是node中的关键字(全局变量),在node中调用其中的元素时,可以直接引用,不用加global前缀,和浏览器中的window类似;在浏览器中可能会使用window前缀:window.location.href,也可能省略window直接调用location.href,这两种情况通过将window赋予global一样的全局属性便都可以正常调用了

window = global; // 将window变成node中的全局变量
- 电脑上安装node.js后,就可以执行JavaScript(编译器,相当于python装CPython解释器)
- 安装node.js时,会自动安装npm(第三方包管理器,相当于python中的pip)

什么是纯净V8:

在这里插入图片描述

在纯净V8中,除了V8引擎本身之外,没有其他浏览器相关的组件和功能。因此,开发人员可以使用纯净V8来构建独立的JavaScript应用程序(例如Node.js),而无需依赖于任何浏览器的特定功能和API。

什么是BOM和DOM:BOM包含DOM

在这里插入图片描述

JavaScript内置对象,所有不在内置对象的都不是v8引擎自带的,比如Regexp/Object/Proxy是v8有的, global不属于v8属于node特有的,查询连接为:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects

在这里插入图片描述

二,什么是补浏览器环境?

**浏览器环境:**是指JS代码在浏览器中的运行时环境,包括V8自动构建的对象(即ECMAScript的内容,如Date、Array),浏览器内置传递给V8的操作DOM和BOM的对象(如document、navigator)。

**Node环境:**是基于V8引擎的Js运行时环境,它包括V8与其自己的内置API,如fs, http, path。

在这里插入图片描述

因此,补浏览器环境其实是补浏览器有而node没有的环境,即补BOM和DOM对象。此外,Node环境和浏览器还具有一些区别,比如window对象区别、this指向区别、Js引擎区别,以及一些DOM操作区别。

三,为什么要补环境?

一般情况下,将加密算法扣下来能够直接执行,但是如果检测了浏览器指纹(由于Node环境与浏览器环境之间存在差异,会导致部分JS代码在浏览器中运行的结果 与在node中运行得到的结果不一样),那就比较难了。

所以需要 “补浏览器环境”,使得扣出来的 “js加密算法代码”Node环境中运行得到的加密值,与其在 浏览器环境中运行得到的加密值一致。

环境对JS代码的影响跳不过这两种方式:

  1. 用来判断,改变逻辑
  2. 值参与加密运算

四,常被检测的环境

在常被检测的环境中,有window、location、document、navigator、canvas、native方法检测等,除了这些属性外,还有针对自动化痕迹的检查(比如对chromedriver属性检测)、Node环境的检测,以及浏览器指纹检测、TLS指纹校验、驱动检测、异常堆栈调用检测等。

window检测:

  • window是否为方法
  • window对象是否freeze
  • 各属性检测

location检测:

  • hostname
  • protocol
  • host
  • hash
  • origin

navigator检测:

  • AppName
  • AppVersion
  • cookieEnabled
  • language
  • userAgent
  • product
  • platform
  • plugins浏览器插件
  • javaEnabled() 方法
  • taintEnabled() 方法

document检测:

  • referrer
  • cookie
  • createElement() 方法

canvas指纹:

  • 不同类型图片的canvas指纹应当不一样,如 .jpg、.png
  • 不同质量quality的canvas指纹应该不一样
  • 不同属性的canvas指纹应该不一样
  • 同一个条件的canvas多次绘制时应该保持一致

浏览器指纹信息:

  • window.screen屏幕分辨率/宽高
  • navigator.useragent
  • location.href/host
  • navigator.platform平台、语言等信息
  • canvas 2D图像指纹
  • navigator.plugin 浏览器插件信息
  • webgl 3D图像指纹
  • 浏览器字体信息
  • 本地存储的cookie信息

五,确定需要补那些环境?

要想 “补浏览器环境”,首先我们得知道 “js加密算法代码” 到底使用了哪些浏览器环境API,然后再对应去补上这些环境;

5.1 通过undefined报错去分析

通过运行程序后的undefined报错一点一点的去补一些环境,这种方式是非常掉头发的。

5.2 使用Proxy

Proxy是ES6提供的代理器(在浏览器和Node中均可使用),用于创建一个对象的代理,从而实现基本操作的拦截和自定义。 它可以代理任何类型的对象,包括原生数组,函数,甚至另一个代理;拥有递归套娃的能力!

也就是说 我们代理某个对象后,我们就成了它的中间商,任何JS代码对它的任何操作都可以被我们所拦截!

使用 Proxy 对全局遍历window、document、navigator等常见环境检测点进行代理,拦截代理对象的读取、函数调用等操作,并通过控制台输出,这样就能够实现检测环境自吐的功能,后续再针对吐出来的环境统一进行补环境,这样就会方便的多。

Proxy基础用法:

先定义一个 target 对象,即目标对象;同时定义 handler 对象,handler 声明了代理 target 的指定行为。

// 目标对象(被代理对象)
var target = {
    name: 'JACK',
    age: 18,
};

// 代理行为对象(对目标对象进行取值或赋值行为时,会进入此对象的方法)
var handler = {
    get: function(target, property, receiver) {
        console.log("get: ", target, property, target[property]);
        return target[property]; 
    },
    set: function(target, property, value) {
        console.log("set: ", target, property, value);
        return Reflect.set(...arguments);
    }
};

// 使用 Proxy 构造函数实例出新的target对象
var target = new Proxy(target, handler)

// 取值操作 会进入handler中的get方法 并打印
target.name     //  get:  {name: 'JACK', age: 18} name JACK
// 赋值操作 会进入handler中的set方法 并打印
target.age = 25 //  set:  {name: 'JACK', age: 18} age 25

下图为Proxy的使用方法,以及补环境代码框架,主体分为三大部分:

在这里插入图片描述

当底部的代码有用到某个在浏览器中的对象时,就会在控制台输出对应的内容(前提是该对象被挂上了代理,并且触发的是get或set方法)

运行结果如下:

在这里插入图片描述

缺少的环境一目了然。后面就是缺啥补啥,只要将上图中显示undefined的对象及其属性补充在第二部分代码后面即可。(location和navigator等要补充的值在Console中查看即可)

示例代码如下:

/* 1,框架代理功能放在顶部 */
var handlerProxy = function (object) {
    return new Proxy(object, {
        get: function(target, property, receiver){
            console.log("get", target, property, target[property]);
            return target[property];
        },
        set: function(target, property, value){
            console.log("set", target, property, value);
            return Reflect.set(...arguments);
        }
    })
};

/* 2,给常见的环境对象挂上代理(挂上代理后在不影响原功能的情况下,当对象被调用时可以在控制台输出结果) */
window = global;
navigator = class navigator{};
document = class document{};
location = class location{};
window = handlerProxy(window);
navigator = handlerProxy(navigator);
document = handlerProxy(document);
location = handlerProxy(location);

/* 3,原生待补环境的js放在底部,调试输出观察 */
location.href = "https://blog.csdn.net/weixin_43411585";
location.protocol = "https:";

六,补环境的方法

6.1 手补

以下举两个例子:

1:当JS代码会判断你当前环境的window对象是否有toString方法

if (window.toString)
{
  //do some thing; 修改全局变量啥的
}

这时,只需要将 window.toString 赋值为true即可:

window = {};
window.toString = true;

这样写没有问题,只是个逻辑,如果还判断了是否为函数:

if (typeof window.toString === 'function')
{
  //do some thing; 修改全局变量啥的
}

这时我们依葫芦画瓢将其定义为函数:

window.toString = function(){};

如果对返回值进行了判断或者参与了加密运算,则直接在浏览器的控制台上运行看看返回值是啥:

在这里插入图片描述

再依照它的结果补上去就可以了:

window.toString = function() {return "[object Window]"};

2:下面是某cdn的部分代码:

document["createElement"]("img")["src"] = "/R=1&e=" + Math["random"]();

这种情况下,当前node环境如果没有 createElement 函数,肯定是会报错的。那该怎么去补呢,我们来分析:

document[“createElement”] 是一个函数,你可以这样定义:

document = {};
document.createElement = function(){};

它传递了一个实参 “img”,因此还需要参数,像这样:

document.createElement = function(img){};

这样肯定还不行,document"createElement" 代码后面加了个 [“src”],那说明

  1. 当实参为 "img"时,有返回值。

  2. 返回值是一个object类型。

document.createElement = function(img){
   if (img === "img")
   {
     return {};
   }
};

上面的代码就可以满足条件了,如果你想更完美,可以像下面这样:

document = {};
document.createElement = function(img)
{
 if (img === "img")
 {
   return {src:""};
 }
}

在确定需要补什么内容时,直接在在浏览器上输出相应的值即可。

6.2 借助jsdom

npm install node-gyp@latest sudo npm explore -g npm -- npm i node-gyp@latest // 更新npm
npm install jsdom -g

注意:上述安装成功后已可以模拟浏览器环境,由于今日头条中依赖canvas包,这里一并下载

npm install canvas -g

jsdom入门示例:

// npm install jsdom

const jsdom = require("jsdom");  // 引入 jsdom
const { JSDOM } = jsdom;  // 引出 JSDOM 类, 等同于 JSDOM = jsdom.JSDOM
const dom = new JSDOM(`<!DOCTYPE html><p>Hello world</p>`);  // 创建DOM对象
console.log(dom.window.document.querySelector("p").textContent); // Hello world

配置DOM:

const dom = new JSDOM(`<!DOCTYPE html><p>Hello world</p>`, {
    url: "https://example.org/",  // window.location,document.URL
    referrer: "https://example.com/",  // document.referrer
    contentType: "text/html",  // document.contentType
    userAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36 Edg/105.0.1343.42",  // UA
    includeNodeLocations: true  // 保留由HTML解析器生成的位置信息,允许使用nodeLocation()方法
});

执行JS:

const jsdom = require("jsdom"); 
const { JSDOM } = jsdom;  
const dom = new JSDOM(
    `<body>
              <script>
              document.body.appendChild(document.createElement("hr"));
              console.log("hello world");
              </script>
           </body>`, 
    { runScripts: "dangerously" }  // 需要配置runScripts 否则不运行 JS
    );
// hello world

设置cookie:

const cookieJar = new jsdom.CookieJar(store, options);
const dom = new JSDOM(``, { cookieJar });

补充环境变量实例:

const jsdom = require("jsdom");
const {JSDOM} = jsdom;

const resourceLoader = new jsdom.ResourceLoader({
    userAgent: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.55 Safari/537.36"
});

const html = `<!DOCTYPE html><p>Hello world</p>`;
const dom = new JSDOM(html, {
    url: "https://www.toutiao.com",
    referrer: "https://example.com/",
    contentType: "text/html",
    resources: resourceLoader,
});


console.log(dom.window.location)
console.log(dom.window.navigator.userAgent)
console.log(dom.window.document.referrer)

window = global; 

const params = {
    location: {
        hash: "",
        host: "www.toutiao.com",
        hostname: "www.toutiao.com",
        href: "https://www.toutiao.com",
        origin: "https://www.toutiao.com",
        pathname: "/",
        port: "",
        protocol: "https:",
        search: "",
    },
    test:{
        hahaha:"nothing at all!!!"
    }
    navigator: {
        appCodeName: "Mozilla",
        appName: "Netscape",
        appVersion: "5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36",
        cookieEnabled: true,
        deviceMemory: 8,
        doNotTrack: null,
        hardwareConcurrency: 4,
        language: "zh-CN",
        languages: ["zh-CN", "zh"],
        maxTouchPoints: 0,
        onLine: true,
        platform: "MacIntel",
        product: "Gecko",
        productSub: "20030107",
        userAgent: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36",
        vendor: "Google Inc.",
        vendorSub: "",
        webdriver: false
    }
};

Object.assign(window,params); // 为window补充环境变量


// 使用window调用或直接调用
console.log(window.location.href)
console.log(location.href)

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

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

相关文章

comfyui定制外包

&#x1f308; 最强AI绘画comfyui模型训练、定制服务公司出炉 —— 触站AI&#xff0c;引领设计智能新潮流 &#x1f680; &#x1f3a8; 触站AI&#xff0c;以AI绘画模型训练重塑设计边界 &#x1f3a8;在AI技术的浪潮中&#xff0c;触站AI以其前沿的AI绘画模型训练技术&…

cesium 添加 Echarts图层(人口迁徒图)

cesium 添加 Echarts 人口迁徒图(下面附有源码) 1、实现思路 1、在scene上面新增一个canvas画布 2、通坐标转换,将经纬度坐标转为屏幕坐标来实现 3、将ecarts 中每个series数组中元素都加 coordinateSystem: ‘cesiumEcharts’ 2、示例代码 <!DOCTYPE html> <ht…

java反射和注解

反射 获取class对象的三种方法 ①&#xff1a;Class.forName("全类名"); ②&#xff1a;类名.class ③&#xff1a;对象.getclass(); 代码样例 package com.ithema;public class Main {public static void main(String[] args) throws ClassNotFoundException {//第…

Centos7修改yum源

安装好系统后&#xff0c;网络能通信&#xff0c;源也没有配置&#xff0c;但是安装软件失败。 解决办法&#xff1a;配置阿里yum源 # curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo # yum clean all # yum make cache再次安装软…

阿里228x82y还原之递归数组解密

声明 本文章中所有内容仅供学习交流&#xff0c;抓包内容、敏感网址、数据接口均已做脱敏处理&#xff0c;严禁用于商业用途和非法用途&#xff0c;否则由此产生的一切后果均与作者无关&#xff0c;若有侵权&#xff0c;请联系我立即删除&#xff01; 目标网站 某里228 分析逆…

详解C语言分支与循环语句

分支语句 if elseswitch 循环语句 whilefordo while goto语句 文章目录 1.什么是语句2.分支语句&#xff08;选择结构&#xff09;2.1 if语句2.1.1 悬空else2.1.3 练习 2.2 switch语句2.2.1 在switch语句中的break2.2.2 default子句 3.循环语句3.1 while循环3.1.1 while语句中…

Studying-代码随想录训练营day26| 491.递增子序列、46.全排列、47.全排列 II、51.N皇后、37.解数独、回溯总结

第26天&#xff0c;回溯part04&#xff0c;昨天休息复习总结回溯内容&#xff0c;&#x1f4aa;(ง •_•)ง&#x1f4aa; 目录 491.递增子序列 46.全排列 47.全排列 II 51.N皇后 37.解数独 回溯总结 491.递增子序列 文档讲解&#xff1a;代码随想录递增子序列 视频讲…

3D Gaussian Splatting代码中的forward和backward两个文件代码解读

3dgs代码前向传播部分 先来讨论一下glm&#xff0c;因为定义变量的时候用到了这个。 glm的解释 glm 是指 OpenGL Mathematics&#xff0c;这是一个针对图形编程的数学库。它的全称是 OpenGL Mathematics (GLM)&#xff0c;主要用于 OpenGL 的开发。这个库是基于 C 的模板库&…

递归算法练习

112. 路径总和 package Tree;import java.util.HashMap; import java.util.Map;class TreeNode {int val;TreeNode left;TreeNode right;public TreeNode(int val) {this.val val;} }/*** 求 树的路径和* <p>* 递归 递减* <p>* 询问是否存在从*当前节点 root 到叶…

现代工作场所中的睡岗检测算法应用

在现代职场环境中&#xff0c;员工的工作状态直接影响到公司的整体效益。睡岗现象&#xff0c;即员工在工作时间内打瞌睡或睡觉&#xff0c;不仅降低了生产力&#xff0c;还可能带来安全隐患。因此&#xff0c;如何有效地检测和预防睡岗行为成为了企业管理中的一个重要课题。随…

The Sandbox 通过创作者挑战推动社区参与

游戏开发者并不是每天都有机会让自己的作品赢得大奖。但在 The Sandbox&#xff0c;这已经成为一种趋势&#xff01;首届 "创作者挑战 "让顶尖创作者将 150 万 SAND 捧回家。现在&#xff0c;我们要带着另一个巨额奖池回来了&#xff01; 关于首届创作者挑战&#xf…

02.C1W1.Sentiment Analysis with Logistic Regression

目录 Supervised ML and Sentiment AnalysisSupervised ML (training)Sentiment analysis Vocabulary and Feature ExtractionVocabularyFeature extractionSparse representations and some of their issues Negative and Positive FrequenciesFeature extraction with freque…

Vue.js中的计算属性:如何让数据自动更新

引言 在Vue.js的世界里&#xff0c;computed属性就像是你的智能助手&#xff0c;它能自动追踪变化&#xff0c;帮你快速做出反应。想象一下&#xff0c;你在做一道菜&#xff0c;调料&#xff08;数据&#xff09;一变&#xff0c;味道&#xff08;界面&#xff09;立刻跟上。…

leetcode刷题:vector刷题

​ ​ &#x1f525;个人主页&#xff1a;guoguoqiang. &#x1f525;专栏&#xff1a;leetcode刷题 1.只出现一次的数字 这道题很简单&#xff0c;我们只需要遍历一次数组即可通过异或运算实现。(一个数与自身异或结果为0&#xff0c;任何数与0异或还是它本身) class Solut…

Linux 实现自定义系统调用,支持参数和结果返回

本文实现一个简单的系统调用实现&#xff0c;支持输入字符串参数&#xff0c;并返回一个结果字符串。 以下是验证步骤&#xff1a; 1. 添加系统调用编号 试验使用的是 x86_64 架构的 Linux 内核。 找到并编辑 arch/x86/entry/syscalls/syscall_64.tbl 文件&#xff0c;在文件…

农业气象站的工作原理

TH-NQ8农业气象站是一种专门用于监测和记录与农业生产密切相关的气象要素的设施。它通过安装各种气象传感器来收集数据&#xff0c;如温度、湿度、风速、风向、降雨量、太阳辐射等&#xff0c;并将这些数据通过传输系统发送到数据中心或用户端&#xff0c;以供农业生产者、研究…

数据库。

数据库安全性 论述题5’ 编程题10’ sql语言实现权限控制 一、概述 1、不安全因素 &#xff08;1&#xff09;⾮授权对数据库的恶意存取和破坏 &#xff08;2&#xff09;数据库中重要的数据泄露 &#xff08;3&#xff09;安全环境的脆弱性 2、⾃主存取控制⽅法 gr…

Java学习 (七) 面向对象--多态、object类

一、多态性 多态在java中的体现是 父类的引用指向子类的对象 格式&#xff1a; 父类类型 变量名 子类对象 1、代码案例 vi Person.java public class Person {public String name;public int age;//新增方法public void eat(){System.out.println("人吃饭");}…

掌握这些快捷键,提升你的编程效率!

文章目录 执行代码行操作移动光标查看源码编辑常用操作类操作方法操作文件操作快捷键组合结语 &#x1f389;欢迎来到Java学习路线专栏~探索Java中的静态变量与实例变量 ☆* o(≧▽≦)o *☆嗨~我是IT陈寒&#x1f379;✨博客主页&#xff1a;IT陈寒的博客&#x1f388;该系列文…

Chapter9 更复杂的光照——Shader入门精要学习笔记

Chapter9 更复杂的光照 一、Unity的渲染路径1.渲染路径的概念2.渲染路径的类型①前向渲染路径a. 前向渲染路径的原理b. Unity中的前向渲染c. 两种Pass ②延迟渲染路径a. 延迟渲染路径的原理b. Unity中的延迟渲染c. 两种Pass ③顶点照明渲染路径 二、Unity的光源类型1.光源类型①…