This commit is contained in:
Big1moster 2023-02-06 11:36:48 +08:00
parent 46834779cc
commit d843fcb236
31 changed files with 14899 additions and 1 deletions

View 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);

View 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);

View File

View 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;
}

View 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
View 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);

View 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);

View 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);

View 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)

View 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
View 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);

View 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
View 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
View 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
View 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);

View 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
View 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
}

View 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
View 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
View 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
View 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拦截所以不会死循环
}
});
}

View 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再次toStringlocation.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
View File

@ -0,0 +1,14 @@
# 补环境框架 - 志远课程完结版
## 志远补环境课程配套框架源码
## 此项目已经被开源安全社区OSCS收录并检测安全
[![OSCS Status](https://www.oscs1024.com/platform/badge/fanchangrui/catvm.svg?size=small)](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
View 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时
// 会将该方法定义(包括方法定义中的注释)都输出
// egloca.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
View 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
View 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再次toStringlocation.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
View 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

File diff suppressed because one or more lines are too long

17
index.js Normal file
View 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

View File

@ -1 +0,0 @@
666

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB