补浏览器环境

一,导言

// 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 jsdomconst 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.URLreferrer: "https://example.com/",  // document.referrercontentType: "text/html",  // document.contentTypeuserAgent: "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",  // UAincludeNodeLocations: 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.mzph.cn/diannao/39544.shtml

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

相关文章

校园水质信息化监管系统——水质监管物联网系统

随着物联网技术的发展越来越成熟&#xff0c;它不断地与人们的日常生活和工作深入融合&#xff0c;推动着社会的进步。其中物联网系统集成在高校实践课程中可以应用到许多项目&#xff0c;如环境气象检测、花卉种植信息化监管、水质信息化监管、校园设施物联网信息化改造、停车…

springboot项目jar包修改数据库配置运行时异常

一、背景 我将软件成功打好jar包了&#xff0c;到部署的时候发现jar包中数据库配置写的有问题&#xff0c;不想再重新打包了&#xff0c;打算直接修改配置文件&#xff0c;结果修改配置后&#xff0c;再通过java -jar运行时就报错了。 二、问题描述 本地项目是springBoot项目…

【计算机图形学 | 基于MFC三维图形开发】期末考试知识点汇总(上)

文章目录 视频教程第一章 计算机图形学概述计算机图形学的定义计算机图形学的应用计算机图形学 vs 图像处理 vs模式识别图形显示器的发展及工作原理理解三维渲染管线 第二章 基本图元的扫描转换扫描转换直线的扫描转换DDA算法Bresenham算法中点画线算法圆的扫描转换中点画圆算法…

【Godot4.2】Godot中的贝塞尔曲线

概述 通过指定平面上的多个点&#xff0c;然后顺次连接&#xff0c;我们可以得到折线段&#xff0c;如果闭合图形&#xff0c;就可以获得多边形。通过向量旋转我们可以获得圆等特殊图形。 但是对于任意曲线&#xff0c;我们无法使用简单的方式来获取其顶点&#xff0c;好在计…

mac上使用finder时候,显示隐藏的文件或者文件夹

默认在finder中是不显示隐藏的文件和文件夹的&#xff0c;但是想创建.gitignore文件&#xff0c;并向里面写入内容&#xff0c;即便是打开xcode也是不显示这几个隐藏文件的&#xff0c;那有什么办法呢&#xff1f; 使用快捷键&#xff1a; 使用finder打开包含隐藏文件的文件夹…

Linux如何安装openjdk1.8

文章目录 Centosyum安装jdk和JRE配置全局环境变量验证ubuntu使用APT(适用于Ubuntu 16.04及以上版本)使用PPA(可选,适用于需要特定版本或旧版Ubuntu)Centos yum安装jdk和JRE yum install java-1.8.0-openjdk-devel.x86_64 安装后的目录 配置全局环境变量 vim /etc/pr…

ISP IC/FPGA设计-第一部分-SC130GS摄像头分析-IIC通信(1)

1.摄像头模组 SC130GS通过一个引脚&#xff08;SPI_I2C_MODE&#xff09;选择使用IIC或SPI配置接口&#xff0c;通过查看摄像头模组的原理图&#xff0c;可知是使用IIC接口&#xff1b; 通过手册可知IIC设备地址通过一个引脚控制&#xff0c;查看摄像头模组的原理图&#xff…

中日区块链“大比拼”!中国蚂蚁加大区块链押注资本!日本索尼进军加密货币市场!

科技巨头在区块链和加密货币领域的动作越来越频繁。近期&#xff0c;中国金融科技巨头蚂蚁集团进一步加大了在区块链业务上的投资&#xff0c;而日本电子科技巨头索尼集团则正式进军加密货币交易领域。这些举措反映了两国对于区块链和加密资产领域的不同态度和布局。 蚂蚁集团加…

disql使用

进入bin目录&#xff1a;cd /opt/dmdbms/bin 启动disql&#xff1a;./disql&#xff0c;然后输入用户名、密码 sh文件直接使用disql&#xff1a; 临时添加路径到PATH环境变量&#xff1a;在当前会话中临时使用disql命令而无需每次都写完整路径&#xff0c;可以在执行脚本之前…

973. 最接近原点的 K 个点-k数组维护+二分查找

973. 最接近原点的 K 个点-k数组维护二分查找 给定一个数组 points &#xff0c;其中 points[i] [xi, yi] 表示 X-Y 平面上的一个点&#xff0c;并且是一个整数 k &#xff0c;返回离原点 (0,0) 最近的 k 个点。 这里&#xff0c;平面上两点之间的距离是 欧几里德距离&#…

初学嵌入式是弄linux还是单片机?

在开始前刚好我有一些资料&#xff0c;是我根据网友给的问题精心整理了一份「单片机的资料从专业入门到高级教程」&#xff0c; 点个关注在评论区回复“666”之后私信回复“666”&#xff0c;全部无偿共享给大家&#xff01;&#xff01;&#xff01;1、先入门了51先学了89c52…

leetcode每日一练:链表OJ题

链表经典算法OJ题 1.1 移除链表元素 题目要求&#xff1a; 给你一个链表的头节点 head 和一个整数 val &#xff0c;请你删除链表中所有满足 Node.val val 的节点&#xff0c;并返回 新的头节点 。 示例 1&#xff1a; 输入&#xff1a;head [1,2,6,3,4,5,6], val 6 输出&a…

模电-二极管及其应用51单片机LED点亮前置工作!

今日小记 2024-7-2&#xff0c;星期二&#xff0c;16:32&#xff0c;天气&#xff1a;晴&#xff0c;心情&#xff1a;晴。持续了两个星期的梅雨天终于暂时过去啦&#xff0c;迎来了久违的阳光&#xff0c;虽然没有雨天凉快&#xff0c;但是能看到太阳也是开心哒&#xff0c;心…

2021强网杯

一、环境 网上自己找 二、步骤 2.1抛出引题 在这个代码中我们反序列&#xff0c;再序列化 <?php$raw O:1:"A":1:{s:1:"a";s:1:"b";};echo serialize(unserialize($raw));//O:1:"A":1:{s:1:"a";s:1:"b";…

工业 web4.0UI 风格品质卓越

工业 web4.0UI 风格品质卓越

单向链表结构

链表结构简介 链表结构是一种用比较特殊的数据结构类型&#xff0c;它也是线性数据结构中的一种&#xff0c;但是与栈结构等线性数据结构不同&#xff0c;它的内部结构并不是一个简单的存储空间&#xff0c;而是一个带有指向性质的单元。要理解链表结构要弄清楚两个问题&#x…

不要再被骗了!电脑无法进入系统的原因可能是这个硬件坏了而已……

前言 前段时间小白在抖音上发了很多很多很多的视频&#xff0c;其中应该是有很多商家关注了小白。 然后就会出现很多很多很多的赚钱小门道…… 电脑开机没有显示&#xff1f;换显卡&#xff01; 电脑还是不开机&#xff1f;换CPU 电脑还是一样不开机…… 经过了一番大折腾…

10.8K star!史上最强Web应用防火墙雷池WAF

长亭雷池SafeLine是长亭科技耗时近 10 年倾情打造的WAF(Web Application Firewall)&#xff0c; 一款敢打出口号 “不让黑客越雷池一步” 的 WAF&#xff0c;愿称之为史上最强的一款Web应用防火墙&#xff0c;足够简单、足够好用、足够强的免费且开源的 WAF&#xff0c;基于业…

pads layout 脚本导出不能运行excle解决办法

在一台新的电脑上安装好PADS&#xff0c;打开PCB文件导出坐标文件时&#xff1a; 出现“ActiveX Automation: server could not be found.”的问题,导致无法成功导出文件,错误提示截图如下&#xff1a; 导致上述问题的原因是在我们配置导出带坐标的脚本时,默认使用的是微软…

Java 实现application/x-www-form-urlencoded编码格式的POST请求

一、实现方式 在Java中&#xff0c;实现application/x-www-form-urlencoded内容类型通常涉及到发送HTTP POST请求。你可以使用java.net.HttpURLConnection或者第三方库如Apache HttpClient来实现。 以下是使用HttpURLConnection发送application/x-www-form-urlencoded数据的代…