补环境最终目的: 不修改JS 在某个环境中直接运行JS文件
第一节课
- BOM 浏览器实现的代码 历史记录 浏览器版本信息之类的
- DOM 根据ID取标签
- 网络请求 XHR jsonp(json_163434343{(a:1)})
- 跨窗口worker (https//developermozillaorg/zh-CN/docs/Web/JavaScript) 链接中的内置对象 就是v8引擎自带的功能。其余均没有
目的:
- 补运行环境
- 找到缺少的环境
- 实现环境代码的实现
使用框架
npm install vm2
vm2:纯净的v8环境。
目的: 既要在node中运行 又要脱离所属的node环境。
ps: 在纯净中 window = this;这也正是为什么有的人写this 而有的人写global的原因之一。
重点检测区: process(检测node)canvas 指纹(每个网站都不一样 不同浏览器和内核也都不一样 生成的图片)
第二节课
要使得vscode中。调整js 打开浏览器 无环境 需要安装一个插件
JavaScript Debugger (Nightly)
其次还需要安装node的一个包
npm install -g node-inspect
可能会失败 多试几次就好了。
然后任意浏览器就会出现这个绿色的小按钮,打开debugger就会跳到浏览器的环境了。
框架 封装的思想 功能单一 可扩展
- js调试框架 监控所有环境 在真是浏览器代理(无法代理某些对象) 在自己伪造的环境代理(任意代理,保证代理不会被检测) 利用开源谷歌浏览器 进行修改内核代码 C++ (学习难度比较高)
- 代码如何被检测? toString() 基于原型链的检测(navigation) Dom环境的检测(canvas)
- 代理是什么?
拦截 js 读取window.xx的操作
实现一个简单的proxy框架
// 后代理的检测不到先代理的。也就是我们这个代理 他是无法用代理检测的 function vmProxy(options) { return new Proxy(options, { set(target, property, value) { console.log("set", target, property, value); return Reflect.set(...arguments); }, get(target, property, receiver) { console.log("get", target, property, receiver) return target[property]; }, }) } Object.defineProperties(window, { [Symbol.toStringTag]: { value: "window", configurable: true, } }); window = vmProxy(window); navigator = vmProxy(class navigator { }) document = vmProxy(class document { }) location = vmProxy(class location { }) debugger;;
第三节课
- 认识框架
- 认识原型和实例
var a = {} // 实例 var b = class b{} // 实例 var c = new (function(){}) 实例 var d = Object() // 实例 var e = Object.create({}) // 实例 function xx(){} // 方法也是对象 方法即是实例也是对象 /* 实例调用 __proto__ 返回实例的原型 原型调用 __proto__ 返回父亲的原型/实例 原型 调用 prototype 返回原型自身 window.__proto__ === Window.prototype // true ({}).__proto__ */
只要有__proto__ 的就是实例
那有没有没有这个的呢?
函数实际上就是对象,每个函数都是Function类型的实例,由于函数是对象,因此函数名也是指向函数对象的一个指针,并不会和函数绑定.
举个例子
function WindowProperties(){} var window1 = function Window1(){} Object.defineProperties(Window1, { [Symbol.toStringTag]: { value: "Window1", configurable: true } }) window1 = new Window1(); var WindowProperties1 = function WindowProperties1(){} Object.defineProperties(WindowProperties1, { [Symbol.toStringTag]: { value: "WindowProperties1", configurable: true } }) // 如何取window1的原型? window1.__proto__ = WindowProperties;
要伪造window1和window一样
如何实现呢?
var window1 = function Window1(){} window1 = new Window1; Object.defineProperties(Window1.prototype, { [Symbol.toStringTag]: { value: "Window", configurable: true } }) var WindowProperties1 = function WindowProperties1(){}; Object.defineProperties(WindowProperties1.prototype, { [Symbol.toStringTag]: { value: "WindowProperties1", configurable: true } }) //window1.__proto__ == Window1.prototype true window1.__proto__.__proto__=WindowProperties1.prototype // 接着补EventTarget var EventTarget1 = function EventTarget1(){}; Object.defineProperties(EventTarget1.prototype, { [Symbol.toStringTag]: { value: "EventTarget1", configurable: true } }) WindowProperties1.prototype.__proto__ = EventTarget1.prototype
修改成这个样子就行了
还需要删除掉构造函数 这个constructor