mirror of
https://github.com/Big1moster/catvm.git
synced 2025-04-05 00:18:50 +08:00
dsf
This commit is contained in:
parent
46834779cc
commit
d843fcb236
53
CatVm2/browser/Document.js
Normal file
53
CatVm2/browser/Document.js
Normal file
@ -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': ["<body link=\"#0000cc\" mpa-version=\"7.16.14\" mpa-extension-id=\"ibefaeehajgcpooopoegkifhgecigeeg\" style=\"\"></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);
|
||||
|
34
CatVm2/browser/EventTarget.js
Normal file
34
CatVm2/browser/EventTarget.js
Normal file
@ -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);
|
0
CatVm2/browser/HTMLDocument.js
Normal file
0
CatVm2/browser/HTMLDocument.js
Normal file
27
CatVm2/browser/HTMLElements/HTMLDivElement.js
Normal file
27
CatVm2/browser/HTMLElements/HTMLDivElement.js
Normal file
@ -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;
|
||||
}
|
||||
|
15
CatVm2/browser/HTMLElements/htmlelement.node.js
Normal file
15
CatVm2/browser/HTMLElements/htmlelement.node.js
Normal file
@ -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
|
||||
}
|
28
CatVm2/browser/History.js
Normal file
28
CatVm2/browser/History.js
Normal file
@ -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);
|
||||
|
24
CatVm2/browser/Location.js
Normal file
24
CatVm2/browser/Location.js
Normal file
@ -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);
|
||||
|
49
CatVm2/browser/MimeType.js
Normal file
49
CatVm2/browser/MimeType.js
Normal file
@ -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);
|
||||
|
94
CatVm2/browser/MimeTypeArray.js
Normal file
94
CatVm2/browser/MimeTypeArray.js
Normal file
@ -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<tmp_plugin.length;m_index++){
|
||||
let tmp_mimetype = tmp_plugin.item(m_index);
|
||||
// catvm.memory.MimeTypeArray.ls.push(tmp_mimetype);
|
||||
if(!(tmp_mimetype.type in catvm.memory.MimeTypeArray.mimetype_types)){
|
||||
catvm.memory.MimeTypeArray.mimetype_types[tmp_mimetype.type] = 1;
|
||||
catvm.memory.MimeTypeArray._[catvm.memory.MimeTypeArray.mimetype_count] = tmp_mimetype;
|
||||
catvm.memory.MimeTypeArray.mimetype_count += 1;
|
||||
// mimetype.type浏览器显示的是灰色名称,下面这种添加属性会是亮的,因此我们需要换一种添加方式
|
||||
Object.defineProperty(catvm.memory.MimeTypeArray._, tmp_mimetype.type, {
|
||||
value: tmp_mimetype,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
catvm.memory.MimeTypeArray._.length = catvm.memory.MimeTypeArray.mimetype_count;
|
||||
|
||||
catvm.memory.MimeTypeArray._.__proto__ = MimeTypeArray.prototype;
|
||||
// 依赖注入
|
||||
navigator.mimeTypes = catvm.memory.MimeTypeArray._;
|
||||
// 代理一般挂在实例上
|
||||
navigator.mimeTypes = catvm.proxy(navigator.mimeTypes)
|
67
CatVm2/browser/Navigator.js
Normal file
67
CatVm2/browser/Navigator.js
Normal file
@ -0,0 +1,67 @@
|
||||
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 <anonymous>:1:21";
|
||||
throw e;
|
||||
// throw new TypeError("Illegal constructor");
|
||||
});
|
||||
}
|
||||
}
|
||||
////////
|
||||
|
||||
|
||||
navigator = catvm.proxy(navigator);
|
||||
|
99
CatVm2/browser/Plugin.js
Normal file
99
CatVm2/browser/Plugin.js
Normal file
@ -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);
|
||||
|
176
CatVm2/browser/PluginArray.js
Normal file
176
CatVm2/browser/PluginArray.js
Normal file
@ -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._;
|
27
CatVm2/browser/Screen.js
Normal file
27
CatVm2/browser/Screen.js
Normal file
@ -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);
|
||||
|
59
CatVm2/browser/Storage.js
Normal file
59
CatVm2/browser/Storage.js
Normal file
@ -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);
|
||||
|
67
CatVm2/browser/Window.js
Normal file
67
CatVm2/browser/Window.js
Normal file
@ -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);
|
16
CatVm2/browser/WindowProperties.js
Normal file
16
CatVm2/browser/WindowProperties.js
Normal file
@ -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;
|
||||
|
||||
|
39
CatVm2/catvm2.node.js
Normal file
39
CatVm2/catvm2.node.js
Normal file
@ -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
|
||||
}
|
16
CatVm2/tools/tools.node.js
Normal file
16
CatVm2/tools/tools.node.js
Normal file
@ -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
|
||||
}
|
14
CatVm2/tools/vm_memory.js
Normal file
14
CatVm2/tools/vm_memory.js
Normal file
@ -0,0 +1,14 @@
|
||||
// 框架内存管理,用于解决变量名重复问题
|
||||
// 调试日志 window.catvm 把框架功能集中管理,
|
||||
|
||||
var catvm = {};
|
||||
// 框架运行内存
|
||||
catvm.memory = {
|
||||
config: {print: true, proxy: true}, // 框架配置:是否打印,是否使用proxy
|
||||
htmlelements:{}, // 所有的html节点元素存放位置
|
||||
listeners:{}, // 所有事件存放位置
|
||||
log:[], // 环境调用日志统一存放点
|
||||
storage:{} // localStorage 全局存放点
|
||||
}; // 默认关闭打印
|
||||
|
||||
|
16
CatVm2/tools/vm_print.js
Normal file
16
CatVm2/tools/vm_print.js
Normal file
@ -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);
|
||||
|
||||
}
|
||||
};
|
23
CatVm2/tools/vm_proxy.js
Normal file
23
CatVm2/tools/vm_proxy.js
Normal file
@ -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拦截,所以不会死循环
|
||||
}
|
||||
});
|
||||
}
|
31
CatVm2/tools/vm_safefunction.js
Normal file
31
CatVm2/tools/vm_safefunction.js
Normal file
@ -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);
|
14
README.md
Normal file
14
README.md
Normal file
@ -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)
|
113
__bak/step.js
Normal file
113
__bak/step.js
Normal file
@ -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/上查看
|
45
__bak/tools.js
Normal file
45
__bak/tools.js
Normal file
@ -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);
|
||||
然后我们再具体实现每个方法
|
||||
*/
|
72
__bak/window.js
Normal file
72
__bak/window.js
Normal file
@ -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;
|
69
__bak/window_bak.js
Normal file
69
__bak/window_bak.js
Normal file
@ -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;
|
13595
debugger_bak.js
Normal file
13595
debugger_bak.js
Normal file
File diff suppressed because one or more lines are too long
17
index.js
Normal file
17
index.js
Normal file
@ -0,0 +1,17 @@
|
||||
var fs = require('fs');
|
||||
var catvm2 = require('./CatVm2/catvm2.node.js');
|
||||
const {VM,VMScript} = require('vm2');
|
||||
var catvm2_code = catvm2.GetCode(); // 框架代码
|
||||
// debugger;
|
||||
// var web_js_code = fs.readFileSync(`${__dirname}/jy.js`) ; // 网站js代码
|
||||
var web_js_code = fs.readFileSync(`${__dirname}/rs.js`) ; // 网站js代码
|
||||
var log_code = "\r\ncatvm.print.getAll();\r\r"
|
||||
web_js_code = web_js_code+log_code
|
||||
var all_code = catvm2_code+web_js_code;
|
||||
fs.writeFileSync(`${__dirname}/debugger_bak.js`,all_code);
|
||||
const script = new VMScript(all_code,`${__dirname}/debugger.js`); //真实路径,浏览器打开的就是该缓存文件
|
||||
|
||||
const vm = new VM(); // new 一个纯净v8环境
|
||||
debugger
|
||||
vm.run(script);
|
||||
debugger
|
@ -1 +0,0 @@
|
||||
666
|
BIN
补环境框架项目结构.png
Normal file
BIN
补环境框架项目结构.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 46 KiB |
Loading…
Reference in New Issue
Block a user