補瀏覽器環境

一,導言

// 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.pswp.cn/diannao/39544.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/39544.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/39544.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

校園水質信息化監管系統——水質監管物聯網系統

隨著物聯網技術的發展越來越成熟&#xff0c;它不斷地與人們的日常生活和工作深入融合&#xff0c;推動著社會的進步。其中物聯網系統集成在高校實踐課程中可以應用到許多項目&#xff0c;如環境氣象檢測、花卉種植信息化監管、水質信息化監管、校園設施物聯網信息化改造、停車…

C++編程(八)多態

文章目錄 一、多態&#xff08;一&#xff09;概念1. 多態2. 函數重寫3. 虛函數 &#xff08;二&#xff09;實現多態的條件1. 繼承關系2. 父類中寫虛函數3. 在子類中重寫父類的虛函數4.父類的指針或引用指向子類的對象5. 使用示例 &#xff08;三&#xff09;虛析構函數&#…

springboot項目jar包修改數據庫配置運行時異常

一、背景 我將軟件成功打好jar包了&#xff0c;到部署的時候發現jar包中數據庫配置寫的有問題&#xff0c;不想再重新打包了&#xff0c;打算直接修改配置文件&#xff0c;結果修改配置后&#xff0c;再通過java -jar運行時就報錯了。 二、問題描述 本地項目是springBoot項目…

【計算機圖形學 | 基于MFC三維圖形開發】期末考試知識點匯總(上)

文章目錄 視頻教程第一章 計算機圖形學概述計算機圖形學的定義計算機圖形學的應用計算機圖形學 vs 圖像處理 vs模式識別圖形顯示器的發展及工作原理理解三維渲染管線 第二章 基本圖元的掃描轉換掃描轉換直線的掃描轉換DDA算法Bresenham算法中點畫線算法圓的掃描轉換中點畫圓算法…

Java中的持續集成與持續部署

Java中的持續集成與持續部署 大家好&#xff0c;我是免費搭建查券返利機器人省錢賺傭金就用微賺淘客系統3.0的小編&#xff0c;也是冬天不穿秋褲&#xff0c;天冷也要風度的程序猿&#xff01;今天我們將深入探討Java中的持續集成&#xff08;Continuous Integration&#xff…

熟練掌握Docker及linux常用命令排查線上問題。熟悉Git, Maven等項目管理及構建工具,熟悉微服務中基于Jenkins的CI/CD

掌握Docker、Linux命令、項目管理及構建工具&#xff0c;以及CI/CD流程是現代軟件開發和運維的關鍵技能。以下是對這些技能的概述和一些實踐建議&#xff1a; ### Docker - **概述**&#xff1a;Docker是一個開源的容器化平臺&#xff0c;允許開發者打包應用及其依賴到一個可移…

【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;平面上兩點之間的距離是 歐幾里德距離&#…

洗衣機水龍頭要買有止逆閥的,多花幾十元能省掉幾萬,值了

問大家一下&#xff0c;你家洗衣機水龍頭用的是什么樣的&#xff1f;      可能有業主會說我家買的是純銅的&#xff0c;質量挺好的。      如果你家選的洗衣機水龍頭僅僅是純銅的&#xff0c;并沒有其他的功能&#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…

學習java第一百一十八天

Component 和 Bean 的區別是什么&#xff1f;Component 注解作用于類&#xff0c;而Bean注解作用于方法。Component通常是通過類路徑掃描來自動偵測以及自動裝配到 Spring 容器中&#xff08;我們可以使用 ComponentScan 注解定義要掃描的路徑從中找出標識了需要裝配的類自動裝…

Nacos 配置中心:動態加載 Bean

前提&#xff1a; 已經集成好 springboot / cloud 與nacos的環境 1 nacos中配置文件參數 message:#sender: emailMessageSendersender: smsMessageSender 2 接口和兩個實現類 public interface MessageSender {String sendMessage(String message, String recipient); }impo…

模電-二極管及其應用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";…