diff --git a/CatVm2/browser/Document.js b/CatVm2/browser/Document.js
new file mode 100644
index 0000000..4f9502f
--- /dev/null
+++ b/CatVm2/browser/Document.js
@@ -0,0 +1,53 @@
+// 从浏览器中知道Document是全局的,new Document会返回一个对象
+var Document = function Document() { // 构造函数
+};
+catvm.safefunction(Document);
+// 浏览器
+Object.defineProperties(Document.prototype, {
+ [Symbol.toStringTag]: {
+ value: "Document",
+ configurable: true
+ }
+});
+document = {};
+document.__proto__ = Document.prototype;
+
+////////// 浏览器代码自动生成部分
+document.cookie = '';
+document.referrer = location.href || '';
+document.getElementById = function getElementById(id) {
+ debugger;
+ // 用id匹配当前环境内存中已有的Element,没找到则返回null
+ return null;
+};
+catvm.safefunction(document.getElementById);
+
+document.getElementsByTagName = function getElementsByTagName(tag_name) {
+ var map_tag = {'body': ["
"]};
+ debugger;
+ return map_tag[tag_name]
+};
+catvm.safefunction(document.getElementsByTagName);
+
+
+document.addEventListener = function addEventListener(type, listener, options, useCapture) {
+ debugger;
+};
+catvm.safefunction(document.addEventListener);
+
+
+document.createElement = function createElement(tagName) {
+ tagName = tagName.toLowerCase();
+ if (catvm.memory.htmlelements[tagName] == undefined) {
+ debugger;
+ } else {
+ var tagElement = catvm.memory.htmlelements[tagName]();
+ return catvm.proxy(tagElement);
+ }
+};
+catvm.safefunction(document.createElement);
+////////
+// 浏览器中document是全局的,因此我们也需要定义一个document
+
+document = catvm.proxy(document);
+
diff --git a/CatVm2/browser/EventTarget.js b/CatVm2/browser/EventTarget.js
new file mode 100644
index 0000000..35e686c
--- /dev/null
+++ b/CatVm2/browser/EventTarget.js
@@ -0,0 +1,34 @@
+var EventTarget = function EventTarget() { // 构造函数
+
+};
+catvm.safefunction(EventTarget);
+
+// 因为EventTarget是构造函数,而我们要的是原型,因此需要先hook EventTarget.prototype,设置下原型的名字,否则它会使用父亲的名字
+Object.defineProperties(EventTarget.prototype, {
+ [Symbol.toStringTag]: {
+ value: "EventTarget",
+ configurable: true
+ }
+})
+
+EventTarget.prototype.addEventListener = function addEventListener(type,callback) {
+ debugger; //debugger的意义在于检测到是否检测了该方法
+ if(!(type in catvm.memory.listeners)){
+ catvm.memory.listeners[type] = [];
+ }
+ catvm.memory.listeners[type].push(callback);
+};
+catvm.safefunction(EventTarget.prototype.addEventListener);
+
+EventTarget.prototype.dispatchEvent = function dispatchEvent() {
+ debugger;
+};
+catvm.safefunction(EventTarget.prototype.dispatchEvent);
+
+EventTarget.prototype.removeEventListener = function removeEventListener() {
+ debugger;
+};
+catvm.safefunction(EventTarget.prototype.removeEventListener);
+
+// EventTarget = catvm.proxy(EventTarget);
+// EventTarget.prototype = catvm.proxy(EventTarget.prototype);
\ No newline at end of file
diff --git a/CatVm2/browser/HTMLDocument.js b/CatVm2/browser/HTMLDocument.js
new file mode 100644
index 0000000..e69de29
diff --git a/CatVm2/browser/HTMLElements/HTMLDivElement.js b/CatVm2/browser/HTMLElements/HTMLDivElement.js
new file mode 100644
index 0000000..c4b77e7
--- /dev/null
+++ b/CatVm2/browser/HTMLElements/HTMLDivElement.js
@@ -0,0 +1,27 @@
+var HTMLDivElement = function HTMLDivElement() { // 构造函数
+ throw new TypeError("Illegal constructor");
+};
+catvm.safefunction(HTMLDivElement);
+
+Object.defineProperties(HTMLDivElement.prototype, {
+ [Symbol.toStringTag]: {
+ value: "HTMLDivElement",
+ configurable: true
+ }
+});
+////////// 浏览器代码自动生成部分
+
+////////
+
+
+
+// 用户创建div
+catvm.memory.htmlelements["div"] = function () {
+ var div = new (function () {});
+ //////////////////////////////////////////
+ div.align = "";
+ /////////////////////////
+ div.__proto__ = HTMLDivElement.prototype;
+ return div;
+}
+
diff --git a/CatVm2/browser/HTMLElements/htmlelement.node.js b/CatVm2/browser/HTMLElements/htmlelement.node.js
new file mode 100644
index 0000000..251cdd4
--- /dev/null
+++ b/CatVm2/browser/HTMLElements/htmlelement.node.js
@@ -0,0 +1,15 @@
+// .node.js文件的用途就是拼接多个文件的js代码
+var fs = require('fs');
+
+function GetCode() {
+ var code = ""
+ code += fs.readFileSync(`${__dirname}/HTMLDivElement.js`) + '\r\n';
+ // code += fs.readFileSync(`${__dirname}/vm_safefunction.js`) + '\r\n';
+ // code += fs.readFileSync(`${__dirname}/vm_print.js`) + '\r\n';
+ // code += fs.readFileSync(`${__dirname}/vm_proxy.js`) + '\r\n';
+ return code;
+
+}
+module.exports = {
+ GetCode
+}
\ No newline at end of file
diff --git a/CatVm2/browser/History.js b/CatVm2/browser/History.js
new file mode 100644
index 0000000..d786f24
--- /dev/null
+++ b/CatVm2/browser/History.js
@@ -0,0 +1,28 @@
+// 从浏览器中知道History是全局的,且原型链只是一层,因此比较好伪造(window有多层所以要伪造多层)
+// 浏览器中new会报错,因此我们此处也需要报错
+var History = function History() { // 构造函数
+ throw new TypeError("Illegal constructor");
+};
+catvm.safefunction(History);
+// 浏览器
+Object.defineProperties(History.prototype, {
+ [Symbol.toStringTag]: {
+ value: "History",
+ configurable: true
+ }
+});
+
+history = {
+ length: 1,
+};
+history.__proto__ = History.prototype;
+////////// 浏览器代码自动生成部分
+History.prototype.back = function back() {
+ debugger;
+};
+catvm.proxy(History.prototype.back);
+////////
+// 浏览器中history是全局的,因此我们也需要定义一个history
+
+history = catvm.proxy(history);
+
diff --git a/CatVm2/browser/Location.js b/CatVm2/browser/Location.js
new file mode 100644
index 0000000..25e0d05
--- /dev/null
+++ b/CatVm2/browser/Location.js
@@ -0,0 +1,24 @@
+var Location = function Location() { // 构造函数
+ throw new TypeError("Illegal constructor");
+};
+catvm.safefunction(Location);
+
+Object.defineProperties(Location.prototype, {
+ [Symbol.toStringTag]: {
+ value: "Location",
+ configurable: true
+ }
+});
+location = {};
+location.__proto__ = Location.prototype;
+
+////////// 浏览器代码自动生成部分
+location.href = "https://www.baidu.com";
+location.port = "";
+location.protocol = 'https:';
+location.host = 'www.baidu.com';
+////////
+
+
+location = catvm.proxy(location);
+
diff --git a/CatVm2/browser/MimeType.js b/CatVm2/browser/MimeType.js
new file mode 100644
index 0000000..acf8090
--- /dev/null
+++ b/CatVm2/browser/MimeType.js
@@ -0,0 +1,49 @@
+// 存储一些值,避免污染全局变量空间
+catvm.memory.mimetype = {};
+
+var MimeType = function MimeType() { // 构造函数
+ throw new TypeError("Illegal constructor");
+};
+catvm.safefunction(MimeType);
+
+
+
+Object.defineProperties(MimeType.prototype, {
+ [Symbol.toStringTag]: {
+ value: "MimeType",
+ configurable: true
+ },
+});
+
+////////// 浏览器代码自动生成部分
+MimeType.prototype.description = "";
+MimeType.prototype.enabledPlugin = null;
+MimeType.prototype.suffixes = "";
+MimeType.prototype.type = "";
+
+for (var _prototype in MimeType.prototype) {
+ if (typeof (MimeType.prototype[_prototype]) != "function") {
+ // 相当于Object.defineProperty的get方法,Proxy的get方法,hook原型上的所有方法属性
+ MimeType.prototype.__defineGetter__(_prototype, function () {
+ throw new TypeError("Illegal constructor");
+ });
+ }
+}
+
+////////
+catvm.memory.mimetype.new = function (data,initPlugin) {
+ var mimetype = {};
+ if (data != undefined) {
+ mimetype.description = data.description;
+ mimetype.enabledPlugin = initPlugin; // plugin实例
+ mimetype.suffixes = data.suffixes;
+ mimetype.type = data.type;
+ }
+ // 先赋完值,在指向原型
+ mimetype.__proto__ = MimeType.prototype;
+ return mimetype;
+};
+
+// 代理一般挂在实例上
+navigator.plugins = catvm.proxy(navigator.plugins);
+
diff --git a/CatVm2/browser/MimeTypeArray.js b/CatVm2/browser/MimeTypeArray.js
new file mode 100644
index 0000000..187e649
--- /dev/null
+++ b/CatVm2/browser/MimeTypeArray.js
@@ -0,0 +1,94 @@
+// 存储一些值,避免污染全局变量空间
+catvm.memory.MimeTypeArray = {};
+// MimeTypeArray实例,MimeTypeArray这个虽然跟MimeType很像,但是无需被new,浏览器一开始就有该实例 navigator.mimeTypes
+catvm.memory.MimeTypeArray._ = {};
+
+
+var MimeTypeArray = function MimeTypeArray() { // 构造函数
+ throw new TypeError("Illegal constructor");
+};
+catvm.safefunction(MimeTypeArray);
+
+
+catvm.memory.MimeTypeArray.iterator = function values() {
+ debugger;
+ return {
+ next:function () {
+ if(this.index_ == undefined){
+ this.index_ = 0;
+ }
+ var tmp = this.self_[this.index_];
+ this.index_ += 1;
+ return {value:tmp,done:tmp==undefined};
+ },
+ self_:this
+ }
+};
+catvm.safefunction(catvm.memory.MimeTypeArray.iterator);
+
+Object.defineProperties(MimeTypeArray.prototype, {
+ [Symbol.toStringTag]: {
+ value: "MimeTypeArray",
+ configurable: true
+ },
+ // 原型上多了个这个,里面是个方法
+ [Symbol.iterator]: {
+ value: catvm.memory.MimeTypeArray.iterator,
+ configurable: true
+ }
+});
+
+////////// ///////////////////浏览器代码自动生成部分
+MimeTypeArray.prototype.length = 0;
+MimeTypeArray.prototype.item = function item(index) {
+ // debugger;
+ return this[index];
+};
+catvm.safefunction(MimeTypeArray.prototype.item);
+MimeTypeArray.prototype.namedItem = function namedItem(key) {
+ // debugger;
+ return this[key];
+};
+catvm.safefunction(MimeTypeArray.prototype.namedItem);
+
+
+// 适用于 调用原型的属性会抛出异常的对象
+for (var _prototype in MimeTypeArray.prototype) {
+ if (typeof (MimeTypeArray.prototype[_prototype]) != "function") {
+ // 相当于Object.defineProperty的get方法,Proxy的get方法,hook原型上的所有方法属性
+ MimeTypeArray.prototype.__defineGetter__(_prototype, function () {
+ // this是实例
+ throw new TypeError("Illegal constructor");
+ // return this[pr];
+ });
+ }
+}
+///////////////////////
+// catvm.memory.MimeTypeArray.ls = [] // 所有MimeType存放点
+// 遍历 PluginArray实例里面的所有Plugin实例
+catvm.memory.MimeTypeArray.mimetype_count = 0;
+catvm.memory.MimeTypeArray.mimetype_types = {}; // 所有MimeType.type存放点
+for (let index = 0; index < catvm.memory.PluginArray._.length; index++) {
+ let tmp_plugin = catvm.memory.PluginArray._[index];
+ // 遍历 Plugin实例里面的所有MimeType实例,增加到 MimeTypeArray中
+ for(let m_index=0;m_index:1:21";
+ throw e;
+ // throw new TypeError("Illegal constructor");
+ });
+ }
+}
+////////
+
+
+navigator = catvm.proxy(navigator);
+
diff --git a/CatVm2/browser/Plugin.js b/CatVm2/browser/Plugin.js
new file mode 100644
index 0000000..f28ce09
--- /dev/null
+++ b/CatVm2/browser/Plugin.js
@@ -0,0 +1,99 @@
+// 存储一些值,避免污染全局变量空间
+catvm.memory.plugin = {};
+
+var Plugin = function Plugin() { // 构造函数
+ throw new TypeError("Illegal constructor");
+};
+catvm.safefunction(Plugin);
+
+
+catvm.memory.plugin.iterator = function values() {
+ // debugger;
+ return {
+ next:function () {
+ if(this.index_ == undefined){
+ this.index_ = 0;
+ }
+ var tmp = this.self_[this.index_];
+ this.index_ += 1;
+ return {value:tmp,done:tmp==undefined};
+ },
+ self_:this
+ }
+};
+catvm.safefunction(catvm.memory.plugin.iterator);
+
+Object.defineProperties(Plugin.prototype, {
+ [Symbol.toStringTag]: {
+ value: "Plugin",
+ configurable: true
+ },
+ // 原型上多了个这个,里面是个方法
+ [Symbol.iterator]: {
+ value: catvm.memory.plugin.iterator,
+ configurable: true
+ }
+});
+
+////////// 浏览器代码自动生成部分
+Plugin.prototype.name = "";
+Plugin.prototype.filename = "";
+Plugin.prototype.description = "";
+Plugin.prototype.length = 0;
+Plugin.prototype.item = function item(index) {
+ // debugger;
+ return this[index];
+};
+catvm.safefunction(Plugin.prototype.item);
+Plugin.prototype.namedItem = function namedItem(key) {
+ // debugger;
+ return this[key];
+};
+catvm.safefunction(Plugin.prototype.namedItem);
+
+
+for (var _prototype in Plugin.prototype) {
+ if (typeof (Plugin.prototype[_prototype]) != "function") {
+ // 相当于Object.defineProperty的get方法,Proxy的get方法,hook原型上的所有方法属性
+ Plugin.prototype.__defineGetter__(_prototype, function () {
+ // this是实例
+ throw new TypeError("Illegal constructor");
+ // return this[pr];
+ });
+ }
+}
+/*
+{ name: 'Chrome PDF Viewer', filename: 'internal-pdf-viewer', description: 'Portable Document Format',MimeTypes:[{"description": "Portable Document Format","suffixes": "pdf","type": "application/pdf"},{"description": "xxxxx","suffixes": "xxxxpdf","type": "xxxxapplication/pdf"}]}
+ */
+////////
+catvm.memory.plugin.new = function (data) {
+ var plugin = {};
+ if (data != undefined) {
+ plugin.description = data.description;
+ plugin.filename = data.filename;
+ plugin.name = data.name;
+ // MimeType
+ if (data.MimeTypes != undefined) {
+ for (let index = 0; index < data.MimeTypes.length; index++) {
+ var mimetypedata = data.MimeTypes[index];
+ var mimetype = catvm.memory.mimetype.new(mimetypedata, plugin);
+ plugin[index] = mimetype;
+ // mimetype.type浏览器显示的是灰色名称,下面这种添加属性会是亮的,因此我们需要换一种添加方式
+ // plugin[mimetype.type] = mimetype;
+ Object.defineProperty(plugin, mimetype.type, {
+ value: mimetype,
+ writable: true // 是否可以改变
+ });
+ }
+
+ plugin.length = data.MimeTypes.length;
+ }
+ }
+ // 先赋完值,在指向原型
+ plugin.__proto__ = Plugin.prototype;
+ return plugin;
+};
+
+// 代理一般挂在实例上
+navigator.plugins = catvm.proxy(navigator.plugins);
+
diff --git a/CatVm2/browser/PluginArray.js b/CatVm2/browser/PluginArray.js
new file mode 100644
index 0000000..24a846a
--- /dev/null
+++ b/CatVm2/browser/PluginArray.js
@@ -0,0 +1,176 @@
+// 存储一些值,避免污染全局变量空间
+catvm.memory.PluginArray = {};
+
+var PluginArray = function PluginArray() { // 构造函数
+ throw new TypeError("Illegal constructor");
+};
+catvm.safefunction(PluginArray);
+
+
+catvm.memory.PluginArray.iterator = function values() {
+ // debugger;
+ return {
+ next:function () {
+ if(this.index_ == undefined){
+ this.index_ = 0;
+ }
+ var tmp = this.self_[this.index_];
+ this.index_ += 1;
+ return {value:tmp,done:tmp==undefined};
+ },
+ self_:this
+ }
+};
+catvm.safefunction(catvm.memory.plugin.iterator);
+
+Object.defineProperties(PluginArray.prototype, {
+ [Symbol.toStringTag]: {
+ value: "PluginArray",
+ configurable: true
+ },
+ // 原型上多了个这个,里面是个方法
+ [Symbol.iterator]: {
+ value: catvm.memory.PluginArray.iterator,
+ configurable: true
+ }
+});
+// PluginArray实例, PluginArray这个虽然跟Plugin很像,但是无需被new,浏览器一开始就有该实例 navigator.plugins
+catvm.memory.PluginArray._ = {};
+
+////////// ///////////////////浏览器代码自动生成部分
+PluginArray.prototype.length = 0;
+PluginArray.prototype.item = function item(index) {
+ // debugger;
+ return this[index];
+};
+catvm.safefunction(PluginArray.prototype.item);
+PluginArray.prototype.namedItem = function namedItem(key) {
+ // debugger;
+ return this[key];
+};
+catvm.safefunction(PluginArray.prototype.namedItem);
+
+PluginArray.prototype.refresh = function refresh() {
+ debugger;
+};
+catvm.safefunction(PluginArray.prototype.refresh);
+
+// 适用于 调用原型的属性会抛出异常的对象
+for (var _prototype in PluginArray.prototype) {
+ if (typeof (PluginArray.prototype[_prototype]) != "function") {
+ // 相当于Object.defineProperty的get方法,Proxy的get方法,hook原型上的所有方法属性
+ PluginArray.prototype.__defineGetter__(_prototype, function () {
+ // this是实例
+ throw new TypeError("Illegal constructor");
+ // return this[pr];
+ });
+ }
+}
+/*
+{ name: 'Chrome PDF Viewer', filename: 'internal-pdf-viewer', description: 'Portable Document Format',MimeTypes:[{"description": "Portable Document Format","suffixes": "pdf","type": "application/pdf"},{"description": "xxxxx","suffixes": "xxxxpdf","type": "xxxxapplication/pdf"}]}
+ */
+///////////////////////
+catvm.memory.PluginArray.ls = [
+ {
+ "name": "PDF Viewer",
+ "filename": "internal-pdf-viewer",
+ "description": "Portable Document Format",
+ "MimeTypes": [
+ {
+ "description": "Portable Document Format",
+ "suffixes": "pdf",
+ "type": "application/pdf"
+ },
+ {
+ "description": "Portable Document Format",
+ "suffixes": "pdf",
+ "type": "text/pdf"
+ }
+ ]
+ },
+ {
+ "name": "Chrome PDF Viewer",
+ "filename": "internal-pdf-viewer",
+ "description": "Portable Document Format",
+ "MimeTypes": [
+ {
+ "description": "Portable Document Format",
+ "suffixes": "pdf",
+ "type": "application/pdf"
+ },
+ {
+ "description": "Portable Document Format",
+ "suffixes": "pdf",
+ "type": "text/pdf"
+ }
+ ]
+ },
+ {
+ "name": "Chromium PDF Viewer",
+ "filename": "internal-pdf-viewer",
+ "description": "Portable Document Format",
+ "MimeTypes": [
+ {
+ "description": "Portable Document Format",
+ "suffixes": "pdf",
+ "type": "application/pdf"
+ },
+ {
+ "description": "Portable Document Format",
+ "suffixes": "pdf",
+ "type": "text/pdf"
+ }
+ ]
+ },
+ {
+ "name": "Microsoft Edge PDF Viewer",
+ "filename": "internal-pdf-viewer",
+ "description": "Portable Document Format",
+ "MimeTypes": [
+ {
+ "description": "Portable Document Format",
+ "suffixes": "pdf",
+ "type": "application/pdf"
+ },
+ {
+ "description": "Portable Document Format",
+ "suffixes": "pdf",
+ "type": "text/pdf"
+ }
+ ]
+ },
+ {
+ "name": "WebKit built-in PDF",
+ "filename": "internal-pdf-viewer",
+ "description": "Portable Document Format",
+ "MimeTypes": [
+ {
+ "description": "Portable Document Format",
+ "suffixes": "pdf",
+ "type": "application/pdf"
+ },
+ {
+ "description": "Portable Document Format",
+ "suffixes": "pdf",
+ "type": "text/pdf"
+ }
+ ]
+ }
+ ]
+
+
+for (let index = 0; index < catvm.memory.PluginArray.ls.length; index++) {
+ let tmp_plugin = catvm.memory.plugin.new(catvm.memory.PluginArray.ls[index]);
+ catvm.memory.PluginArray._[index] = tmp_plugin;
+ // mimetype.type浏览器显示的是灰色名称,下面这种添加属性会是亮的,因此我们需要换一种添加方式
+ Object.defineProperty(catvm.memory.PluginArray._, tmp_plugin.name, {
+ value: tmp_plugin,
+ });
+}
+catvm.memory.PluginArray._.length = catvm.memory.PluginArray.ls.length;
+
+catvm.memory.PluginArray._.__proto__ = PluginArray.prototype;
+// 代理一般挂在实例上
+catvm.memory.PluginArray._ = catvm.proxy(catvm.memory.PluginArray._);
+// 依赖注入
+navigator.plugins = catvm.memory.PluginArray._;
diff --git a/CatVm2/browser/Screen.js b/CatVm2/browser/Screen.js
new file mode 100644
index 0000000..9985ca5
--- /dev/null
+++ b/CatVm2/browser/Screen.js
@@ -0,0 +1,27 @@
+// 从浏览器中知道Screen是全局的,且原型链只是一层,因此比较好伪造(window有多层所以要伪造多层)
+// 浏览器中new会报错,因此我们此处也需要报错
+var Screen = function Screen() { // 构造函数
+ throw new TypeError("Illegal constructor");
+};
+catvm.safefunction(Screen);
+// 浏览器
+Object.defineProperties(Screen.prototype, {
+ [Symbol.toStringTag]: {
+ value: "Screen",
+ configurable: true
+ }
+});
+screen = {};
+screen.__proto__ = Screen.prototype;
+////////// 浏览器代码自动生成部分
+Screen.prototype.width = 1494;
+Screen.prototype.height = 934;
+Screen.prototype.availWidth = 1494;
+Screen.prototype.availHeight = 934;
+Screen.prototype.colorDepth = 24;
+Screen.prototype.pixelDepth = 24;
+////////
+// 浏览器中screen是全局的,因此我们也需要定义一个screen
+
+screen = catvm.proxy(screen);
+
diff --git a/CatVm2/browser/Storage.js b/CatVm2/browser/Storage.js
new file mode 100644
index 0000000..88e03bb
--- /dev/null
+++ b/CatVm2/browser/Storage.js
@@ -0,0 +1,59 @@
+// 从浏览器中知道Storage是全局的,且原型链只是一层,因此比较好伪造(window有多层所以要伪造多层)
+// 浏览器中new会报错,因此我们此处也需要报错
+var Storage = function Storage() { // 构造函数
+ throw new TypeError("Illegal constructor");
+};
+catvm.safefunction(Storage);
+// 浏览器
+Object.defineProperties(Storage.prototype, {
+ [Symbol.toStringTag]: {
+ value: "Storage",
+ configurable: true
+ }
+});
+var localStorage = {};
+localStorage.__proto__ = Storage.prototype;
+
+////////// 浏览器代码自动生成部分
+
+function get_length() {
+ return Object.keys(catvm.memory.storage).length;
+}
+
+Storage.prototype.length = get_length();
+Storage.prototype.key = function key(index) {
+ return Object.keys(catvm.memory.storage)[index];
+};
+catvm.safefunction(Storage.prototype.key);
+Storage.prototype.getItem = function getItem(keyName) {
+ var result = catvm.memory.storage[keyName];
+ if (result) {
+ return result;
+ } else {
+ return null;
+ }
+};
+catvm.safefunction(Storage.prototype.getItem);
+
+Storage.prototype.setItem = function setItem(keyName, keyValue) {
+ catvm.memory.storage[keyName] = keyValue;
+};
+catvm.safefunction(Storage.prototype.setItem);
+
+Storage.prototype.removeItem = function removeItem(keyName) {
+ delete catvm.memory.storage[keyName];
+};
+catvm.safefunction(Storage.prototype.removeItem);
+
+Storage.prototype.clear = function clear() {
+ catvm.memory.storage = {};
+};
+catvm.safefunction(Storage.prototype.clear);
+
+
+////////
+
+// 代理一般挂在实例上
+localStorage = catvm.proxy(localStorage);
+Storage = catvm.proxy(Storage);
+
diff --git a/CatVm2/browser/Window.js b/CatVm2/browser/Window.js
new file mode 100644
index 0000000..623a766
--- /dev/null
+++ b/CatVm2/browser/Window.js
@@ -0,0 +1,67 @@
+window = this;
+// debugger;
+var Window = function Window() { // 构造函数
+ // 容易被检测到的 js可以查看堆栈
+ throw new TypeError("Illegal constructor");
+};
+catvm.safefunction(Window);
+
+Object.defineProperties(Window.prototype, {
+ [Symbol.toStringTag]: {
+ value: "Window",
+ configurable: true
+ }
+})
+Window.prototype.__proto__ = WindowProperties.prototype;
+window.__proto__ = Window.prototype;
+
+///////////////////////////// 浏览器代码自动生成部分
+Window.prototype.PERSISTENT = 1;
+Window.prototype.TEMPORARY = 0;
+
+
+// v8没有setTimeout,浏览器有,但是浏览器把这个方法放到this下面,伪造v8有这个东西,因此我们需要伪造一下
+window.setTimeout = function (x, y) {
+ // x可能是方法也可能是文本
+ typeof (x) == "function" ? x() : undefined;
+ typeof (x) == "string" ? eval(x) : undefined;
+ // 正确应该 生成UUID,并且保存到内存
+ return 123;
+};
+catvm.safefunction(window.setTimeout);
+// 原型下面可以取这个属性\方法,就直接放原型即可
+// 只要是方法就需要catvm.safefunction 进行toSting保护
+window.open = function open() {
+ debugger;
+};
+catvm.safefunction(window.open);
+// 赋值空对象最好使用这种class chrome{} 形式,而不是 {},因为这样我们可以看名字,并且最好挂上代理
+window.chrome = catvm.proxy(class chrome {
+});
+// 打个debugger,因为我们还不知道js有没有调用该方法,也许只是获取了一下,看有没有该方法呢
+// 等它真正调用的时候,我们再补全其参数及返回
+window.DeviceOrientationEvent = function DeviceOrientationEvent() {
+ debugger;
+};
+catvm.safefunction(window.DeviceOrientationEvent);
+window.DeviceMotionEvent = function DeviceMotionEvent() {
+ debugger;
+};
+catvm.safefunction(window.DeviceMotionEvent);
+
+// window.localStorage = class localStorage {
+// };
+// window.localStorage.getItem = function getItem() {
+// debugger;
+// };
+// catvm.safefunction(window.localStorage.getItem);
+// window.localStorage.setItem = function setItem() {
+// debugger;
+// };
+// catvm.safefunction(window.localStorage.setItem);
+// window.localStorage = catvm.proxy(window.localStorage)
+//////////////////////
+
+// debugger;
+window = catvm.proxy(window);
+Window = catvm.proxy(Window);
diff --git a/CatVm2/browser/WindowProperties.js b/CatVm2/browser/WindowProperties.js
new file mode 100644
index 0000000..6c6066e
--- /dev/null
+++ b/CatVm2/browser/WindowProperties.js
@@ -0,0 +1,16 @@
+var WindowProperties = function WindowProperties() { // 构造函数
+
+};
+catvm.safefunction(WindowProperties);
+
+Object.defineProperties(WindowProperties.prototype, {
+ [Symbol.toStringTag]: {
+ value: "WindowProperties",
+ configurable: true
+ }
+})
+
+// 设置原型的父对象
+WindowProperties.prototype.__proto__ = EventTarget.prototype;
+
+
diff --git a/CatVm2/catvm2.node.js b/CatVm2/catvm2.node.js
new file mode 100644
index 0000000..74eede2
--- /dev/null
+++ b/CatVm2/catvm2.node.js
@@ -0,0 +1,39 @@
+var fs = require('fs');
+// 框架工具模块
+var vmtools = require('./tools/tools.node.js');
+var vmhtml = require('./browser/HTMLElements/htmlelement.node.js');
+function GetCode() {
+ // 引入框架工具代码
+ var code = "";
+ code += vmtools.GetCode() + '\r\n';
+ // 引入用户框架配置 // 暂时这么写
+ // code += "catvm.memory.config.proxy = true;\r\n"
+ // 引入浏览器相关代码
+ code += fs.readFileSync(`${__dirname}/browser/EventTarget.js`) + '\r\n';
+ code += fs.readFileSync(`${__dirname}/browser/WindowProperties.js`) + '\r\n';
+ // 加载BOM环境(优于DOM加载)
+ code += fs.readFileSync(`${__dirname}/browser/Window.js`) + '\r\n';
+ code += fs.readFileSync(`${__dirname}/browser/Location.js`) + '\r\n';
+ code += fs.readFileSync(`${__dirname}/browser/Navigator.js`) + '\r\n';
+ code += fs.readFileSync(`${__dirname}/browser/History.js`) + '\r\n';
+ code += fs.readFileSync(`${__dirname}/browser/Screen.js`) + '\r\n';
+ code += fs.readFileSync(`${__dirname}/browser/Storage.js`) + '\r\n';
+
+ code += fs.readFileSync(`${__dirname}/browser/MimeType.js`) + '\r\n';
+ code += fs.readFileSync(`${__dirname}/browser/Plugin.js`) + '\r\n';
+ code += fs.readFileSync(`${__dirname}/browser/PluginArray.js`) + '\r\n';
+ code += fs.readFileSync(`${__dirname}/browser/MimeTypeArray.js`) + '\r\n';
+
+ // 加载HTML节点
+ code += vmhtml.GetCode() + '\r\n';
+ // 加载DOM环境
+ code += fs.readFileSync(`${__dirname}/browser/Document.js`) + '\r\n';
+ // 引入用户自定义环境
+ code += "debugger;\r\n";
+ return code;
+
+}
+
+module.exports = {
+ GetCode
+}
\ No newline at end of file
diff --git a/CatVm2/tools/tools.node.js b/CatVm2/tools/tools.node.js
new file mode 100644
index 0000000..68c9a90
--- /dev/null
+++ b/CatVm2/tools/tools.node.js
@@ -0,0 +1,16 @@
+// .node.js文件的用途就是拼接多个文件的js代码
+var fs = require('fs');
+
+function GetCode() {
+ var code = "";
+ code += fs.readFileSync(`${__dirname}/vm_memory.js`) + '\r\n';
+ code += fs.readFileSync(`${__dirname}/vm_safefunction.js`) + '\r\n';
+ code += fs.readFileSync(`${__dirname}/vm_print.js`) + '\r\n';
+ code += fs.readFileSync(`${__dirname}/vm_proxy.js`) + '\r\n';
+ return code;
+
+}
+
+module.exports = {
+ GetCode
+}
\ No newline at end of file
diff --git a/CatVm2/tools/vm_memory.js b/CatVm2/tools/vm_memory.js
new file mode 100644
index 0000000..83b95d9
--- /dev/null
+++ b/CatVm2/tools/vm_memory.js
@@ -0,0 +1,14 @@
+// 框架内存管理,用于解决变量名重复问题
+// 调试日志 window.catvm 把框架功能集中管理,
+
+var catvm = {};
+// 框架运行内存
+catvm.memory = {
+ config: {print: true, proxy: true}, // 框架配置:是否打印,是否使用proxy
+ htmlelements:{}, // 所有的html节点元素存放位置
+ listeners:{}, // 所有事件存放位置
+ log:[], // 环境调用日志统一存放点
+ storage:{} // localStorage 全局存放点
+}; // 默认关闭打印
+
+
diff --git a/CatVm2/tools/vm_print.js b/CatVm2/tools/vm_print.js
new file mode 100644
index 0000000..a585c10
--- /dev/null
+++ b/CatVm2/tools/vm_print.js
@@ -0,0 +1,16 @@
+// 日志调试功能
+catvm.print = {};
+catvm.memory.print = []; // 缓存
+catvm.print.log = function () {
+ if (catvm.memory.config.print) {
+ console.table(catvm.memory.log);
+
+ }
+};
+
+catvm.print.getAll = function () { // 列出所有日志
+ if (catvm.memory.config.print) {
+ console.table(catvm.memory.log);
+
+ }
+};
\ No newline at end of file
diff --git a/CatVm2/tools/vm_proxy.js b/CatVm2/tools/vm_proxy.js
new file mode 100644
index 0000000..508e34d
--- /dev/null
+++ b/CatVm2/tools/vm_proxy.js
@@ -0,0 +1,23 @@
+// 框架代理功能
+
+catvm.proxy = function (obj) {
+ // Proxy 可以多层代理,即 a = new proxy(a); a = new proxy(a);第二次代理
+ // 后代理的检测不到先代理的
+ if (catvm.memory.config.proxy == false) {
+ return obj
+ }
+ return new Proxy(obj, {
+ set(target, property, value) {
+ console.table([{"类型":"set-->","调用者":target,"调用属性":property,"设置值":value}]);
+ catvm.memory.log.push({"类型":"set-->","调用者":target,"调用属性":property,"设置值":value});
+ // console.log("set", target, property, value);
+ return Reflect.set(...arguments); //这是一种反射语句,这种不会产生死循环问题
+ },
+ get(target, property, receiver) {
+ console.table([{"类型":"get<--","调用者":target,"调用属性":property,"获取值":target[property]}]);
+ catvm.memory.log.push({"类型":"get<--","调用者":target,"调用属性":property,"获取值":target[property]});
+ // console.log("get", target, property, target[property]);
+ return target[property]; // target中访问属性不会再被proxy拦截,所以不会死循环
+ }
+ });
+}
\ No newline at end of file
diff --git a/CatVm2/tools/vm_safefunction.js b/CatVm2/tools/vm_safefunction.js
new file mode 100644
index 0000000..f7ac35b
--- /dev/null
+++ b/CatVm2/tools/vm_safefunction.js
@@ -0,0 +1,31 @@
+// 主要用来保护伪造的函数,使其更难被识别
+
+// 主要用来保护伪造的函数,让其更难识破
+;
+(() => {
+ 'use strict';
+ // 取原型链上的toString
+ const $toString = Function.toString;
+ // 取方法名 reload
+ const myFunction_toString_symbol = Symbol('('.concat('', ')_', (Math.random() + '').toString(36)));
+ const myToString = function () {
+ return typeof this == 'function' && this[myFunction_toString_symbol] || $toString.call(this);
+ };
+
+ function set_native(func, key, value) {
+ Object.defineProperty(func, key, {
+ "enumerable": false, // 不可枚举
+ "configurable": true, // 可配置
+ "writable": true, // 可写
+ "value": value
+ })
+ }
+
+ delete Function.prototype['toString'];// 删除原型链上的toString
+ set_native(Function.prototype, "toString", myToString); // 自定义一个getter方法,其实就是一个hook
+ //套个娃,保护一下我们定义的toString,避免js对toString再次toString,如:location.reload.toString.toString() 否则就暴露了
+ set_native(Function.prototype.toString, myFunction_toString_symbol, "function toString() { [native code] }");
+ this.catvm.safefunction = (func) => {
+ set_native(func, myFunction_toString_symbol, `function ${myFunction_toString_symbol,func.name || ''}() { [native code] }`);
+ }; //导出函数到globalThis,更改原型上的toSting为自己的toString。这个方法相当于过掉func的toString检测点
+}).call(this);
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..24759ae
--- /dev/null
+++ b/README.md
@@ -0,0 +1,14 @@
+# 补环境框架 - 志远课程完结版
+## 志远补环境课程配套框架源码
+## 此项目已经被开源安全社区OSCS收录并检测安全
+[](https://www.oscs1024.com/project/fanchangrui/catvm?ref=badge_small)
+
+## 来源
+该项目是我跟着 志远大佬开源课程 一步步敲出来的;
+该项目内容与最后课程实现的效果完全一样,相当于课程配套源码。
+
+
+### 具体 使用步骤及实现原理,可以参考我的博客文章
+[JS逆向之浏览器补环境详解](https://blog.csdn.net/qq_36291294/article/details/127699273)
+### 另外,我使用另一种更完美\更细粒度的思路实现了一个补环境框架,目前可以直接黑盒过瑞数:
+[JS逆向之补环境过瑞数详解](https://blog.csdn.net/qq_36291294/article/details/128600583)
\ No newline at end of file
diff --git a/__bak/step.js b/__bak/step.js
new file mode 100644
index 0000000..5b33413
--- /dev/null
+++ b/__bak/step.js
@@ -0,0 +1,113 @@
+function Person(option) {
+ //一般传入字面量对象做参数
+ //new之后自动创建一个空对象,把这个对象的地址给this,即var this = new Object();
+ //this给空对象绑定属性和行为
+ this._init(option);
+ this.name = option.name;
+ this.eat = function(food) {
+ console.log("吃" + food)
+ }
+ ;
+ //自动默认return this;如果有存在 return 对象,则不返回this,若return 非对象,则依然return this
+}
+Person.prototype = {
+ //所有此对象共享的属性和方法
+ _init: function(option) {
+ this.earth = option.earth;
+ },
+ run: function(where) {
+ console.log(this.name + "在" + where + "泡");
+ }
+};
+var per = new Person({
+ name: "dsf"
+});
+//向构造函数传入字面量对象
+per.eat("牛排");
+//调用对象方法
+
+
+
+
+一般补环境的几个步骤:
+比如补Navigator:
+1、先在浏览器环境观察该对象:Navigator
+能否进行new Navigator,不能的话则在其构造函数定义中抛出异常,能的话不抛;
+查看其原型Navigator.prototype 的属性、方法、原型链,
+发现Navigator原型属性、方法不能通过原型调用,即
+Navigator.appVersion 会抛出异常。
+发现 其原型链只有一层,即Navigator.prototype.__proto__ === Object.prototype
+2、在浏览器环境观察其实例对象:navigator
+查看其属性、方法与 原型上的差异,发现差不多,基本都是继承原型的,
+
+3、补环境:
+定义Navigator 构造函数,并保护其toString,
+ 定义navigator对象,将其原型指向Navigator,即navigator.__proto__ = Navigator.prototype;
+如果是多层原型的话,需要多次指向。
+补全原型上的属性、方法:
+Navigator.prototype.plugins = [];
+Navigator.prototype.languages = ["zh-CN", "zh"];
+补全实例上的属性、方法(不要与继承自原型的属性、方法冲突)
+
+
+
+4、代理该对象 navigator
+
+
+
+
+
+补一个方法如location.reload()时,
+需要看其是在原型上还是实例上,这会决定我们是在原型上补还是在实例上补(唯一区别),
+通过浏览器环境观察,发现reload是在location实例上定义的,
+因此我们直接在location实例上补该方法:
+location = class location{};
+//此处必须给个方法名,因为toString会默认调用该方法,可能会检测该方法名,location.reload.toString时,
+// 会将该方法定义(包括方法定义中的注释)都输出
+// eg:loca.reload.toString()
+// 'function reload(){ //此处必须给个方法名,因为toString会默认调用该方法,可能会检测该方法名\n\n}'
+location.reload = function reload(){
+
+};
+定义完方法之后,需要对方法进行保护
+func_set_native(location.reload);
+
+
+
+
+
+
+
+一般补环境的几个步骤:
+比如补Navigator:
+1、先在浏览器环境观察该对象:Navigator
+先查看其原型链,发现只有一层即 Navigator.prototype.__proto__ 为Object原型
+能否进行new Navigator,不能的话则在其构造函数定义中抛出异常,能的话不抛;
+var Navigator = function Navigator() { // 构造函数
+ throw new TypeError("Illegal constructor");
+};
+然后保护该方法:
+catvm.safefunction(Navigator);
+然后给其原型一个名字:
+Object.defineProperties(Navigator.prototype, {
+ [Symbol.toStringTag]: {
+ value: "Navigator",
+ configurable: true
+ }
+}
+});
+在浏览器查看其实例navigator是否存在,存在的话我们也要定义一个:
+navigator = {};
+然后指定其原型:
+navigator.__proto__ = Navigator.prototype;
+此时对比浏览器原型链,确定我们原型已经补完,接下来就是填充navigator的原型方法、属性、实例方法、属性
+对比浏览器上navigator的原型与实例上方法、属性的差异,将原型上的补到我们原型上,实例上的补到实例上,两者都有的优先补到原型上。
+Navigator.prototype.plugins = [];
+Navigator.prototype.languages = ["zh-CN", "zh"];
+...
+然后在最末尾加上代理:
+navigator = catvm.proxy(navigator);
+最终在调试网站js环境代码时,根据log一个个补,浏览器上输出啥,我们就补成啥,如果log输出本来就跟浏览器上的
+一致,则不用动,继续去看下一个log
+
+遇到不清楚的属性、方法,去 https://developer.mozilla.org/上查看
\ No newline at end of file
diff --git a/__bak/tools.js b/__bak/tools.js
new file mode 100644
index 0000000..a6df27d
--- /dev/null
+++ b/__bak/tools.js
@@ -0,0 +1,45 @@
+// 传进来的对象是一个实例还是一个原型
+// 思路:遍历原型里面所有的值,拿出来进行封装
+
+//判断对象的类型
+function judge_type(pr,property,_name) {
+ var code = "";
+ // Screen.prototype.width = 1494;
+ var temp = _name+".prototype."+property;
+ switch (typeof (pr[property])) {
+ case "function":
+ code = temp + "= function " +property+"(){debugger;};catvm.safefunction("+temp+");";
+ break;
+ case "object":
+ code = temp + "= catvm.proxy(class " +property+"{});";
+ break;
+ default:
+ // "string"\"boolean"\"undefined"\"number"
+ code += _name+".prototype."+property + "=" +pr[property];
+ break;
+ }
+ return code;
+}
+
+function getcode(pr,_name) {
+ var code = "";
+ for (var property in pr.__proto__) {
+ console.log(property,typeof property);
+ // 原型、字段名、别名
+ code += judge_type(pr,property,_name) + "\r\n";
+ }
+ return code;
+}
+
+/*
+浏览器运行我们的脚本:
+getcode(localStorage,"Storage")
+生成:
+Storage.prototype.length=0
+Storage.prototype.clear= function clear(){debugger;};catvm.safefunction(Storage.prototype.clear);
+Storage.prototype.getItem= function getItem(){debugger;};catvm.safefunction(Storage.prototype.getItem);
+Storage.prototype.key= function key(){debugger;};catvm.safefunction(Storage.prototype.key);
+Storage.prototype.removeItem= function removeItem(){debugger;};catvm.safefunction(Storage.prototype.removeItem);
+Storage.prototype.setItem= function setItem(){debugger;};catvm.safefunction(Storage.prototype.setItem);
+然后我们再具体实现每个方法
+ */
\ No newline at end of file
diff --git a/__bak/window.js b/__bak/window.js
new file mode 100644
index 0000000..5b0b669
--- /dev/null
+++ b/__bak/window.js
@@ -0,0 +1,72 @@
+// 环境框架内容(环境头)
+
+window = this;
+
+navigator = {
+ userAgent:"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.107 Safari/537.36"
+}
+function vmProxy(obj){
+ // Proxy 可以多层代理,即 a = new proxy(a); a = new proxy(a);第二次代理
+ // 后代理的检测不到先代理的
+ return new Proxy(obj, {
+ set(target, property, value){
+ console.log(target, property, value);
+ return Reflect.set(...arguments); //这是一种反射语句,这种不会产生死循环问题
+ },
+ get(target,property,receiver){
+ console.log(target, property, receiver);
+ return target[property]; // target中访问属性不会被proxy拦截,所以不会死循环
+ }
+ });
+}
+// 主要用来保护伪造的函数,让其更难识破
+(() => {
+ 'use strict';
+ // 取原型链上的toString
+ const $toString = Function.toString;
+ // 取方法名 reload
+ const myFunction_toString_symbol = Symbol('('.concat('',')_',(Math.random()+'').toString(36)));
+ const myToString = function(){
+ return typeof this == 'function' && this[myFunction_toString_symbol] || $toString.call(this);
+ };
+ function set_native(func,key,value){
+ Object.defineProperty(func,key,{
+ "enumerable":false, // 不可枚举
+ "configurable":true, // 可配置
+ "writable":true, // 可写
+ "value":value
+ })
+ }
+ delete Function.prototype['toString'];// 删除原型链上的toString
+ set_native(Function.prototype,"toString",myToString); // 自定义一个getter方法,其实就是一个hook
+ //套个娃,保护一下我们定义的toString,避免js对toString再次toString,如:location.reload.toString.toString() 否则就暴露了
+ set_native(Function.prototype.toString,myFunction_toString_symbol,"function toString() { [native code] }");
+ this.func_set_native = (func) => {
+ set_native(func,myFunction_toString_symbol,`function ${myFunction_toString_symbol,func.name || ''}() { [native code] }`);
+ }; //导出函数到globalThis,更改原型上的toSting为自己的toString。这个方法相当于过掉func的toString检测点
+}).call(this);
+
+
+Object.defineProperties(window,{
+ [Symbol.toStringTag]:{
+ value:"window",
+ configurable:true
+ }
+})
+
+window = vmProxy(window);
+/*
+创建对象的几种方式: {} 、 Object.create({})、class xxx{} 、function xxx(){};+new xxx;
+代理这些常见的浏览器对象,以便进行环境调试。
+*/
+navigator = vmProxy(class navigator{});
+document = vmProxy(class document{});
+
+location = class location{};
+location.reload = function reload(){ //此处必须给个方法名,因为toString会默认调用该方法,可能会检测该方法名
+
+};func_set_native(location.reload);
+
+location = vmProxy(location);
+screen = vmProxy(class location{});
+debugger;
\ No newline at end of file
diff --git a/__bak/window_bak.js b/__bak/window_bak.js
new file mode 100644
index 0000000..1fb535c
--- /dev/null
+++ b/__bak/window_bak.js
@@ -0,0 +1,69 @@
+// 环境框架内容(环境头)
+
+window = this;
+
+navigator = {
+ userAgent:"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.107 Safari/537.36"
+}
+function vmProxy(obj){
+ // Proxy 可以多层代理,即 a = new proxy(a); a = new proxy(a);第二次代理
+ // 后代理的检测不到先代理的
+ return new Proxy(obj, {
+ set(target, property, value){
+ console.log(target, property, value);
+ return Reflect.set(...arguments); //这是一种反射语句,这种不会产生死循环问题
+ },
+ get(target,property,receiver){
+ console.log(target, property, receiver);
+ return target[property]; // target中访问属性不会被proxy拦截,所以不会死循环
+ }
+ });
+}
+// 主要用来保护伪造的函数,让其更难识破
+(() => {
+ 'use strict';
+ const $toString = Function.toString;
+ const myFunction_toString_symbol = Symbol('('.concat('',')_',(Math.random()+'').toString(36)));
+ const myToString = function(){
+ return typeof this == 'function' && this[myFunction_toString_symbol] || $toString.call(this);
+ };
+ function set_native(func,key,value){
+ Object.defineProperty(func,key,{
+ "enumerable":false,
+ "configurable":true,
+ "writable":true,
+ "value":value
+ })
+ };
+ delete Function.prototype['toString'];// 删除原型链上的toString
+ set_native(Function.prototype,"toString",myToString); // 自定义个getter方法
+ set_native(Function.prototype.toString,myFunction_toString_symbol,"function toString() { [native code] }"); //套个娃,保护一下我们定义的toString 否则就暴露了
+ this.func_set_native = (func) => {
+ set_native(func,myFunction_toString_symbol,`function ${myFunction_toString_symbol,func.name || ''}() { [native code] }`);
+ }; //导出函数到globalThis,这个方法相当于过掉func的toString检测点
+}).call(this);
+
+
+Object.defineProperties(window,{
+ [Symbol.toStringTag]:{
+ value:"window",
+ configurable:true
+ }
+})
+
+window = vmProxy(window);
+/*
+创建对象的几种方式: {} 、 Object.create({})、class xxx{} 、function xxx(){};+new xxx;
+代理这些常见的浏览器对象,以便进行环境调试。
+*/
+navigator = vmProxy(class navigator{});
+document = vmProxy(class document{});
+
+location = class location{};
+location.reload = function reload(){ //此处必须给个方法名,因为toString会默认调用该方法,可能会检测该方法名
+
+};func_set_native(location.reload);
+
+location = vmProxy(location);
+screen = vmProxy(class location{});
+debugger;
\ No newline at end of file
diff --git a/debugger_bak.js b/debugger_bak.js
new file mode 100644
index 0000000..94b47ba
--- /dev/null
+++ b/debugger_bak.js
@@ -0,0 +1,13595 @@
+// 框架内存管理,用于解决变量名重复问题
+// 调试日志 window.catvm 把框架功能集中管理,
+
+var catvm = {};
+// 框架运行内存
+catvm.memory = {
+ config: {print: true, proxy: true}, // 框架配置:是否打印,是否使用proxy
+ htmlelements:{}, // 所有的html节点元素存放位置
+ listeners:{}, // 所有事件存放位置
+ log:[], // 环境调用日志统一存放点
+ storage:{} // localStorage 全局存放点
+}; // 默认关闭打印
+
+
+
+// 主要用来保护伪造的函数,使其更难被识别
+
+// 主要用来保护伪造的函数,让其更难识破
+;
+(() => {
+ 'use strict';
+ // 取原型链上的toString
+ const $toString = Function.toString;
+ // 取方法名 reload
+ const myFunction_toString_symbol = Symbol('('.concat('', ')_', (Math.random() + '').toString(36)));
+ const myToString = function () {
+ return typeof this == 'function' && this[myFunction_toString_symbol] || $toString.call(this);
+ };
+
+ function set_native(func, key, value) {
+ Object.defineProperty(func, key, {
+ "enumerable": false, // 不可枚举
+ "configurable": true, // 可配置
+ "writable": true, // 可写
+ "value": value
+ })
+ }
+
+ delete Function.prototype['toString'];// 删除原型链上的toString
+ set_native(Function.prototype, "toString", myToString); // 自定义一个getter方法,其实就是一个hook
+ //套个娃,保护一下我们定义的toString,避免js对toString再次toString,如:location.reload.toString.toString() 否则就暴露了
+ set_native(Function.prototype.toString, myFunction_toString_symbol, "function toString() { [native code] }");
+ this.catvm.safefunction = (func) => {
+ set_native(func, myFunction_toString_symbol, `function ${myFunction_toString_symbol,func.name || ''}() { [native code] }`);
+ }; //导出函数到globalThis,更改原型上的toSting为自己的toString。这个方法相当于过掉func的toString检测点
+}).call(this);
+
+// 日志调试功能
+catvm.print = {};
+catvm.memory.print = []; // 缓存
+catvm.print.log = function () {
+ if (catvm.memory.config.print) {
+ console.table(catvm.memory.log);
+
+ }
+};
+
+catvm.print.getAll = function () { // 列出所有日志
+ if (catvm.memory.config.print) {
+ console.table(catvm.memory.log);
+
+ }
+};
+// 框架代理功能
+
+catvm.proxy = function (obj) {
+ // Proxy 可以多层代理,即 a = new proxy(a); a = new proxy(a);第二次代理
+ // 后代理的检测不到先代理的
+ if (catvm.memory.config.proxy == false) {
+ return obj
+ }
+ return new Proxy(obj, {
+ set(target, property, value) {
+ console.table([{"类型":"set-->","调用者":target,"调用属性":property,"设置值":value}]);
+ catvm.memory.log.push({"类型":"set-->","调用者":target,"调用属性":property,"设置值":value});
+ // console.log("set", target, property, value);
+ return Reflect.set(...arguments); //这是一种反射语句,这种不会产生死循环问题
+ },
+ get(target, property, receiver) {
+ console.table([{"类型":"get<--","调用者":target,"调用属性":property,"获取值":target[property]}]);
+ catvm.memory.log.push({"类型":"get<--","调用者":target,"调用属性":property,"获取值":target[property]});
+ // console.log("get", target, property, target[property]);
+ return target[property]; // target中访问属性不会再被proxy拦截,所以不会死循环
+ }
+ });
+}
+
+var EventTarget = function EventTarget() { // 构造函数
+
+};
+catvm.safefunction(EventTarget);
+
+// 因为EventTarget是构造函数,而我们要的是原型,因此需要先hook EventTarget.prototype,设置下原型的名字,否则它会使用父亲的名字
+Object.defineProperties(EventTarget.prototype, {
+ [Symbol.toStringTag]: {
+ value: "EventTarget",
+ configurable: true
+ }
+})
+
+EventTarget.prototype.addEventListener = function addEventListener(type,callback) {
+ debugger; //debugger的意义在于检测到是否检测了该方法
+ if(!(type in catvm.memory.listeners)){
+ catvm.memory.listeners[type] = [];
+ }
+ catvm.memory.listeners[type].push(callback);
+};
+catvm.safefunction(EventTarget.prototype.addEventListener);
+
+EventTarget.prototype.dispatchEvent = function dispatchEvent() {
+ debugger;
+};
+catvm.safefunction(EventTarget.prototype.dispatchEvent);
+
+EventTarget.prototype.removeEventListener = function removeEventListener() {
+ debugger;
+};
+catvm.safefunction(EventTarget.prototype.removeEventListener);
+
+// EventTarget = catvm.proxy(EventTarget);
+// EventTarget.prototype = catvm.proxy(EventTarget.prototype);
+var WindowProperties = function WindowProperties() { // 构造函数
+
+};
+catvm.safefunction(WindowProperties);
+
+Object.defineProperties(WindowProperties.prototype, {
+ [Symbol.toStringTag]: {
+ value: "WindowProperties",
+ configurable: true
+ }
+})
+
+// 设置原型的父对象
+WindowProperties.prototype.__proto__ = EventTarget.prototype;
+
+
+
+window = this;
+// debugger;
+var Window = function Window() { // 构造函数
+ // 容易被检测到的 js可以查看堆栈
+ throw new TypeError("Illegal constructor");
+};
+catvm.safefunction(Window);
+
+Object.defineProperties(Window.prototype, {
+ [Symbol.toStringTag]: {
+ value: "Window",
+ configurable: true
+ }
+})
+Window.prototype.__proto__ = WindowProperties.prototype;
+window.__proto__ = Window.prototype;
+
+///////////////////////////// 浏览器代码自动生成部分
+Window.prototype.PERSISTENT = 1;
+Window.prototype.TEMPORARY = 0;
+
+
+// v8没有setTimeout,浏览器有,但是浏览器把这个方法放到this下面,伪造v8有这个东西,因此我们需要伪造一下
+window.setTimeout = function (x, y) {
+ // x可能是方法也可能是文本
+ typeof (x) == "function" ? x() : undefined;
+ typeof (x) == "string" ? eval(x) : undefined;
+ // 正确应该 生成UUID,并且保存到内存
+ return 123;
+};
+catvm.safefunction(window.setTimeout);
+// 原型下面可以取这个属性\方法,就直接放原型即可
+// 只要是方法就需要catvm.safefunction 进行toSting保护
+window.open = function open() {
+ debugger;
+};
+catvm.safefunction(window.open);
+// 赋值空对象最好使用这种class chrome{} 形式,而不是 {},因为这样我们可以看名字,并且最好挂上代理
+window.chrome = catvm.proxy(class chrome {
+});
+// 打个debugger,因为我们还不知道js有没有调用该方法,也许只是获取了一下,看有没有该方法呢
+// 等它真正调用的时候,我们再补全其参数及返回
+window.DeviceOrientationEvent = function DeviceOrientationEvent() {
+ debugger;
+};
+catvm.safefunction(window.DeviceOrientationEvent);
+window.DeviceMotionEvent = function DeviceMotionEvent() {
+ debugger;
+};
+catvm.safefunction(window.DeviceMotionEvent);
+
+// window.localStorage = class localStorage {
+// };
+// window.localStorage.getItem = function getItem() {
+// debugger;
+// };
+// catvm.safefunction(window.localStorage.getItem);
+// window.localStorage.setItem = function setItem() {
+// debugger;
+// };
+// catvm.safefunction(window.localStorage.setItem);
+// window.localStorage = catvm.proxy(window.localStorage)
+//////////////////////
+
+// debugger;
+window = catvm.proxy(window);
+Window = catvm.proxy(Window);
+
+var Location = function Location() { // 构造函数
+ throw new TypeError("Illegal constructor");
+};
+catvm.safefunction(Location);
+
+Object.defineProperties(Location.prototype, {
+ [Symbol.toStringTag]: {
+ value: "Location",
+ configurable: true
+ }
+});
+location = {};
+location.__proto__ = Location.prototype;
+
+////////// 浏览器代码自动生成部分
+location.href = "https://www.baidu.com";
+location.port = "";
+location.protocol = 'https:';
+location.host = 'www.baidu.com';
+////////
+
+
+location = catvm.proxy(location);
+
+
+var Navigator = function Navigator() { // 构造函数
+ throw new TypeError("Illegal constructor");
+};
+catvm.safefunction(Navigator);
+
+Object.defineProperties(Navigator.prototype, {
+ [Symbol.toStringTag]: {
+ value: "Navigator",
+ configurable: true
+ }
+});
+navigator = {
+ // platform: 'Win32',
+ // userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36',
+ // maxTouchPoints: 0,
+ // onLine: true,
+ // mimeTypes: [{
+ // suffixes: "pdf",
+ // type: "application/pdf"
+ // }],
+ //
+ // plugins: [{
+ // "0": {},
+ // "1": {}
+ // }]
+
+};
+navigator.__proto__ = Navigator.prototype;
+////////// 浏览器代码自动生成部分
+
+Navigator.prototype.plugins = [];
+Navigator.prototype.languages = ["zh-CN", "zh"];
+Navigator.prototype.userAgent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36';
+Navigator.prototype.platform = 'Win32';
+Navigator.prototype.maxTouchPoints = 0;
+Navigator.prototype.onLine = true;
+Navigator.prototype.mimeTypes = [{
+ suffixes: "pdf",
+ type: "application/pdf"
+}];
+Navigator.prototype.plugins = [{
+ "0": {},
+ "1": {}
+}];
+//上面是定义原型的属性
+// navigator比较特殊,它会把属性继续定义到 静态属性中,所以我们也做一下
+for (var _prototype in Navigator.prototype) {
+ navigator[_prototype] = Navigator.prototype[_prototype]; // 将原型上的方法复制一遍给实例
+ if (typeof (Navigator.prototype[_prototype]) != "function") {
+ // 相当于Object.defineProperty的get方法,Proxy的get方法,hook原型上的所有方法属性
+ Navigator.prototype.__defineGetter__(_prototype, function () {
+ debugger;
+ var e = new Error();
+ e.name = "TypeError";
+ e.message = "Illegal constructor";
+ e.stack = "VM988:1 Uncaught TypeError: Illegal invocation \r\n " +
+ "at :1:21";
+ throw e;
+ // throw new TypeError("Illegal constructor");
+ });
+ }
+}
+////////
+
+
+navigator = catvm.proxy(navigator);
+
+
+// 从浏览器中知道History是全局的,且原型链只是一层,因此比较好伪造(window有多层所以要伪造多层)
+// 浏览器中new会报错,因此我们此处也需要报错
+var History = function History() { // 构造函数
+ throw new TypeError("Illegal constructor");
+};
+catvm.safefunction(History);
+// 浏览器
+Object.defineProperties(History.prototype, {
+ [Symbol.toStringTag]: {
+ value: "History",
+ configurable: true
+ }
+});
+
+history = {
+ length: 1,
+};
+history.__proto__ = History.prototype;
+////////// 浏览器代码自动生成部分
+History.prototype.back = function back() {
+ debugger;
+};
+catvm.proxy(History.prototype.back);
+////////
+// 浏览器中history是全局的,因此我们也需要定义一个history
+
+history = catvm.proxy(history);
+
+
+// 从浏览器中知道Screen是全局的,且原型链只是一层,因此比较好伪造(window有多层所以要伪造多层)
+// 浏览器中new会报错,因此我们此处也需要报错
+var Screen = function Screen() { // 构造函数
+ throw new TypeError("Illegal constructor");
+};
+catvm.safefunction(Screen);
+// 浏览器
+Object.defineProperties(Screen.prototype, {
+ [Symbol.toStringTag]: {
+ value: "Screen",
+ configurable: true
+ }
+});
+screen = {};
+screen.__proto__ = Screen.prototype;
+////////// 浏览器代码自动生成部分
+Screen.prototype.width = 1494;
+Screen.prototype.height = 934;
+Screen.prototype.availWidth = 1494;
+Screen.prototype.availHeight = 934;
+Screen.prototype.colorDepth = 24;
+Screen.prototype.pixelDepth = 24;
+////////
+// 浏览器中screen是全局的,因此我们也需要定义一个screen
+
+screen = catvm.proxy(screen);
+
+
+// 从浏览器中知道Storage是全局的,且原型链只是一层,因此比较好伪造(window有多层所以要伪造多层)
+// 浏览器中new会报错,因此我们此处也需要报错
+var Storage = function Storage() { // 构造函数
+ throw new TypeError("Illegal constructor");
+};
+catvm.safefunction(Storage);
+// 浏览器
+Object.defineProperties(Storage.prototype, {
+ [Symbol.toStringTag]: {
+ value: "Storage",
+ configurable: true
+ }
+});
+var localStorage = {};
+localStorage.__proto__ = Storage.prototype;
+
+////////// 浏览器代码自动生成部分
+
+function get_length() {
+ return Object.keys(catvm.memory.storage).length;
+}
+
+Storage.prototype.length = get_length();
+Storage.prototype.key = function key(index) {
+ return Object.keys(catvm.memory.storage)[index];
+};
+catvm.safefunction(Storage.prototype.key);
+Storage.prototype.getItem = function getItem(keyName) {
+ var result = catvm.memory.storage[keyName];
+ if (result) {
+ return result;
+ } else {
+ return null;
+ }
+};
+catvm.safefunction(Storage.prototype.getItem);
+
+Storage.prototype.setItem = function setItem(keyName, keyValue) {
+ catvm.memory.storage[keyName] = keyValue;
+};
+catvm.safefunction(Storage.prototype.setItem);
+
+Storage.prototype.removeItem = function removeItem(keyName) {
+ delete catvm.memory.storage[keyName];
+};
+catvm.safefunction(Storage.prototype.removeItem);
+
+Storage.prototype.clear = function clear() {
+ catvm.memory.storage = {};
+};
+catvm.safefunction(Storage.prototype.clear);
+
+
+////////
+
+// 代理一般挂在实例上
+localStorage = catvm.proxy(localStorage);
+Storage = catvm.proxy(Storage);
+
+
+// 存储一些值,避免污染全局变量空间
+catvm.memory.mimetype = {};
+
+var MimeType = function MimeType() { // 构造函数
+ throw new TypeError("Illegal constructor");
+};
+catvm.safefunction(MimeType);
+
+
+
+Object.defineProperties(MimeType.prototype, {
+ [Symbol.toStringTag]: {
+ value: "MimeType",
+ configurable: true
+ },
+});
+
+////////// 浏览器代码自动生成部分
+MimeType.prototype.description = "";
+MimeType.prototype.enabledPlugin = null;
+MimeType.prototype.suffixes = "";
+MimeType.prototype.type = "";
+
+for (var _prototype in MimeType.prototype) {
+ if (typeof (MimeType.prototype[_prototype]) != "function") {
+ // 相当于Object.defineProperty的get方法,Proxy的get方法,hook原型上的所有方法属性
+ MimeType.prototype.__defineGetter__(_prototype, function () {
+ throw new TypeError("Illegal constructor");
+ });
+ }
+}
+
+////////
+catvm.memory.mimetype.new = function (data,initPlugin) {
+ var mimetype = {};
+ if (data != undefined) {
+ mimetype.description = data.description;
+ mimetype.enabledPlugin = initPlugin; // plugin实例
+ mimetype.suffixes = data.suffixes;
+ mimetype.type = data.type;
+ }
+ // 先赋完值,在指向原型
+ mimetype.__proto__ = MimeType.prototype;
+ return mimetype;
+};
+
+// 代理一般挂在实例上
+navigator.plugins = catvm.proxy(navigator.plugins);
+
+
+// 存储一些值,避免污染全局变量空间
+catvm.memory.plugin = {};
+
+var Plugin = function Plugin() { // 构造函数
+ throw new TypeError("Illegal constructor");
+};
+catvm.safefunction(Plugin);
+
+
+catvm.memory.plugin.iterator = function values() {
+ // debugger;
+ return {
+ next:function () {
+ if(this.index_ == undefined){
+ this.index_ = 0;
+ }
+ var tmp = this.self_[this.index_];
+ this.index_ += 1;
+ return {value:tmp,done:tmp==undefined};
+ },
+ self_:this
+ }
+};
+catvm.safefunction(catvm.memory.plugin.iterator);
+
+Object.defineProperties(Plugin.prototype, {
+ [Symbol.toStringTag]: {
+ value: "Plugin",
+ configurable: true
+ },
+ // 原型上多了个这个,里面是个方法
+ [Symbol.iterator]: {
+ value: catvm.memory.plugin.iterator,
+ configurable: true
+ }
+});
+
+////////// 浏览器代码自动生成部分
+Plugin.prototype.name = "";
+Plugin.prototype.filename = "";
+Plugin.prototype.description = "";
+Plugin.prototype.length = 0;
+Plugin.prototype.item = function item(index) {
+ // debugger;
+ return this[index];
+};
+catvm.safefunction(Plugin.prototype.item);
+Plugin.prototype.namedItem = function namedItem(key) {
+ // debugger;
+ return this[key];
+};
+catvm.safefunction(Plugin.prototype.namedItem);
+
+
+for (var _prototype in Plugin.prototype) {
+ if (typeof (Plugin.prototype[_prototype]) != "function") {
+ // 相当于Object.defineProperty的get方法,Proxy的get方法,hook原型上的所有方法属性
+ Plugin.prototype.__defineGetter__(_prototype, function () {
+ // this是实例
+ throw new TypeError("Illegal constructor");
+ // return this[pr];
+ });
+ }
+}
+/*
+{ name: 'Chrome PDF Viewer', filename: 'internal-pdf-viewer', description: 'Portable Document Format',MimeTypes:[{"description": "Portable Document Format","suffixes": "pdf","type": "application/pdf"},{"description": "xxxxx","suffixes": "xxxxpdf","type": "xxxxapplication/pdf"}]}
+ */
+////////
+catvm.memory.plugin.new = function (data) {
+ var plugin = {};
+ if (data != undefined) {
+ plugin.description = data.description;
+ plugin.filename = data.filename;
+ plugin.name = data.name;
+ // MimeType
+ if (data.MimeTypes != undefined) {
+ for (let index = 0; index < data.MimeTypes.length; index++) {
+ var mimetypedata = data.MimeTypes[index];
+ var mimetype = catvm.memory.mimetype.new(mimetypedata, plugin);
+ plugin[index] = mimetype;
+ // mimetype.type浏览器显示的是灰色名称,下面这种添加属性会是亮的,因此我们需要换一种添加方式
+ // plugin[mimetype.type] = mimetype;
+ Object.defineProperty(plugin, mimetype.type, {
+ value: mimetype,
+ writable: true // 是否可以改变
+ });
+ }
+
+ plugin.length = data.MimeTypes.length;
+ }
+ }
+ // 先赋完值,在指向原型
+ plugin.__proto__ = Plugin.prototype;
+ return plugin;
+};
+
+// 代理一般挂在实例上
+navigator.plugins = catvm.proxy(navigator.plugins);
+
+
+// 存储一些值,避免污染全局变量空间
+catvm.memory.PluginArray = {};
+
+var PluginArray = function PluginArray() { // 构造函数
+ throw new TypeError("Illegal constructor");
+};
+catvm.safefunction(PluginArray);
+
+
+catvm.memory.PluginArray.iterator = function values() {
+ // debugger;
+ return {
+ next:function () {
+ if(this.index_ == undefined){
+ this.index_ = 0;
+ }
+ var tmp = this.self_[this.index_];
+ this.index_ += 1;
+ return {value:tmp,done:tmp==undefined};
+ },
+ self_:this
+ }
+};
+catvm.safefunction(catvm.memory.plugin.iterator);
+
+Object.defineProperties(PluginArray.prototype, {
+ [Symbol.toStringTag]: {
+ value: "PluginArray",
+ configurable: true
+ },
+ // 原型上多了个这个,里面是个方法
+ [Symbol.iterator]: {
+ value: catvm.memory.PluginArray.iterator,
+ configurable: true
+ }
+});
+// PluginArray实例, PluginArray这个虽然跟Plugin很像,但是无需被new,浏览器一开始就有该实例 navigator.plugins
+catvm.memory.PluginArray._ = {};
+
+////////// ///////////////////浏览器代码自动生成部分
+PluginArray.prototype.length = 0;
+PluginArray.prototype.item = function item(index) {
+ // debugger;
+ return this[index];
+};
+catvm.safefunction(PluginArray.prototype.item);
+PluginArray.prototype.namedItem = function namedItem(key) {
+ // debugger;
+ return this[key];
+};
+catvm.safefunction(PluginArray.prototype.namedItem);
+
+PluginArray.prototype.refresh = function refresh() {
+ debugger;
+};
+catvm.safefunction(PluginArray.prototype.refresh);
+
+// 适用于 调用原型的属性会抛出异常的对象
+for (var _prototype in PluginArray.prototype) {
+ if (typeof (PluginArray.prototype[_prototype]) != "function") {
+ // 相当于Object.defineProperty的get方法,Proxy的get方法,hook原型上的所有方法属性
+ PluginArray.prototype.__defineGetter__(_prototype, function () {
+ // this是实例
+ throw new TypeError("Illegal constructor");
+ // return this[pr];
+ });
+ }
+}
+/*
+{ name: 'Chrome PDF Viewer', filename: 'internal-pdf-viewer', description: 'Portable Document Format',MimeTypes:[{"description": "Portable Document Format","suffixes": "pdf","type": "application/pdf"},{"description": "xxxxx","suffixes": "xxxxpdf","type": "xxxxapplication/pdf"}]}
+ */
+///////////////////////
+catvm.memory.PluginArray.ls = [
+ {
+ "name": "PDF Viewer",
+ "filename": "internal-pdf-viewer",
+ "description": "Portable Document Format",
+ "MimeTypes": [
+ {
+ "description": "Portable Document Format",
+ "suffixes": "pdf",
+ "type": "application/pdf"
+ },
+ {
+ "description": "Portable Document Format",
+ "suffixes": "pdf",
+ "type": "text/pdf"
+ }
+ ]
+ },
+ {
+ "name": "Chrome PDF Viewer",
+ "filename": "internal-pdf-viewer",
+ "description": "Portable Document Format",
+ "MimeTypes": [
+ {
+ "description": "Portable Document Format",
+ "suffixes": "pdf",
+ "type": "application/pdf"
+ },
+ {
+ "description": "Portable Document Format",
+ "suffixes": "pdf",
+ "type": "text/pdf"
+ }
+ ]
+ },
+ {
+ "name": "Chromium PDF Viewer",
+ "filename": "internal-pdf-viewer",
+ "description": "Portable Document Format",
+ "MimeTypes": [
+ {
+ "description": "Portable Document Format",
+ "suffixes": "pdf",
+ "type": "application/pdf"
+ },
+ {
+ "description": "Portable Document Format",
+ "suffixes": "pdf",
+ "type": "text/pdf"
+ }
+ ]
+ },
+ {
+ "name": "Microsoft Edge PDF Viewer",
+ "filename": "internal-pdf-viewer",
+ "description": "Portable Document Format",
+ "MimeTypes": [
+ {
+ "description": "Portable Document Format",
+ "suffixes": "pdf",
+ "type": "application/pdf"
+ },
+ {
+ "description": "Portable Document Format",
+ "suffixes": "pdf",
+ "type": "text/pdf"
+ }
+ ]
+ },
+ {
+ "name": "WebKit built-in PDF",
+ "filename": "internal-pdf-viewer",
+ "description": "Portable Document Format",
+ "MimeTypes": [
+ {
+ "description": "Portable Document Format",
+ "suffixes": "pdf",
+ "type": "application/pdf"
+ },
+ {
+ "description": "Portable Document Format",
+ "suffixes": "pdf",
+ "type": "text/pdf"
+ }
+ ]
+ }
+ ]
+
+
+for (let index = 0; index < catvm.memory.PluginArray.ls.length; index++) {
+ let tmp_plugin = catvm.memory.plugin.new(catvm.memory.PluginArray.ls[index]);
+ catvm.memory.PluginArray._[index] = tmp_plugin;
+ // mimetype.type浏览器显示的是灰色名称,下面这种添加属性会是亮的,因此我们需要换一种添加方式
+ Object.defineProperty(catvm.memory.PluginArray._, tmp_plugin.name, {
+ value: tmp_plugin,
+ });
+}
+catvm.memory.PluginArray._.length = catvm.memory.PluginArray.ls.length;
+
+catvm.memory.PluginArray._.__proto__ = PluginArray.prototype;
+// 代理一般挂在实例上
+catvm.memory.PluginArray._ = catvm.proxy(catvm.memory.PluginArray._);
+// 依赖注入
+navigator.plugins = catvm.memory.PluginArray._;
+
+// 存储一些值,避免污染全局变量空间
+catvm.memory.MimeTypeArray = {};
+// MimeTypeArray实例,MimeTypeArray这个虽然跟MimeType很像,但是无需被new,浏览器一开始就有该实例 navigator.mimeTypes
+catvm.memory.MimeTypeArray._ = {};
+
+
+var MimeTypeArray = function MimeTypeArray() { // 构造函数
+ throw new TypeError("Illegal constructor");
+};
+catvm.safefunction(MimeTypeArray);
+
+
+catvm.memory.MimeTypeArray.iterator = function values() {
+ debugger;
+ return {
+ next:function () {
+ if(this.index_ == undefined){
+ this.index_ = 0;
+ }
+ var tmp = this.self_[this.index_];
+ this.index_ += 1;
+ return {value:tmp,done:tmp==undefined};
+ },
+ self_:this
+ }
+};
+catvm.safefunction(catvm.memory.MimeTypeArray.iterator);
+
+Object.defineProperties(MimeTypeArray.prototype, {
+ [Symbol.toStringTag]: {
+ value: "MimeTypeArray",
+ configurable: true
+ },
+ // 原型上多了个这个,里面是个方法
+ [Symbol.iterator]: {
+ value: catvm.memory.MimeTypeArray.iterator,
+ configurable: true
+ }
+});
+
+////////// ///////////////////浏览器代码自动生成部分
+MimeTypeArray.prototype.length = 0;
+MimeTypeArray.prototype.item = function item(index) {
+ // debugger;
+ return this[index];
+};
+catvm.safefunction(MimeTypeArray.prototype.item);
+MimeTypeArray.prototype.namedItem = function namedItem(key) {
+ // debugger;
+ return this[key];
+};
+catvm.safefunction(MimeTypeArray.prototype.namedItem);
+
+
+// 适用于 调用原型的属性会抛出异常的对象
+for (var _prototype in MimeTypeArray.prototype) {
+ if (typeof (MimeTypeArray.prototype[_prototype]) != "function") {
+ // 相当于Object.defineProperty的get方法,Proxy的get方法,hook原型上的所有方法属性
+ MimeTypeArray.prototype.__defineGetter__(_prototype, function () {
+ // this是实例
+ throw new TypeError("Illegal constructor");
+ // return this[pr];
+ });
+ }
+}
+///////////////////////
+// catvm.memory.MimeTypeArray.ls = [] // 所有MimeType存放点
+// 遍历 PluginArray实例里面的所有Plugin实例
+catvm.memory.MimeTypeArray.mimetype_count = 0;
+catvm.memory.MimeTypeArray.mimetype_types = {}; // 所有MimeType.type存放点
+for (let index = 0; index < catvm.memory.PluginArray._.length; index++) {
+ let tmp_plugin = catvm.memory.PluginArray._[index];
+ // 遍历 Plugin实例里面的所有MimeType实例,增加到 MimeTypeArray中
+ for(let m_index=0;m_index