用户:
Nomen查看:16 回复:11 评论:16 创建时间:2023-05-14T11:43:14
Box3-Tools有了一个初始界面:
box3-tools.rth1.me/
======
这里是没有开场白的Nomen,闲来无事,写了一个神奇的东西(至于整活作品中的bug,关我啥事)
本体内容:
class NomenSandbox {
constructor(config, _code) {
this.timeout = config.timeout || 10 * 1000;
this.permision = config.permission || {};
this.finish = false;
this._cancel = false;
this.pgm = `try {
return (async () => {
let __st = setTimeout(() => {
if (sandbox.__finish__) { clearTimeout(__st); return; }
sandbox.__complete(new Error('[NomenSandbox] Sandbox Execute Timeout'));
throw new Error('[NomenSandbox] Sandbox Execute Timeout');
}, ${this.timeout});
with (sandbox) {
(async () => { return await ${(typeof _code == "function") ? '(' + _code.toString() + ')()' : _code} })()
.then(v => __complete(v))
.catch(e => __complete('[NomenSandbox: Error When execute user script]'+e))
.finally(() => __finish__ = true)
};
})()
} catch (err) { __complete('[NomenSandbox: Error When Runing NomenSandbox]'+err) }`;
}
run() {
if (this.finish) return;
return (async () => {
let r = this;
Object.assign(this.permision, {
get __finish__() { return r.finish || r._cancel },
r,
setInterval,
clearInterval,
setTimeout,
clearTimeout,
Error,
Promise,
})
try {
let result = await new Promise(resolve => {
r.permision.__complete = (v) => resolve(v)
const sandbox = new Proxy(r.permision, {
has() { return true },
get(target, key) { return (key == Symbol.unscopables) ? undefined : target[key] }
});
const cd = new Function('sandbox', r.pgm);
cd(sandbox)
.then(v => {
this.finish = true;
}).catch(e => { })
});
return result
} catch (err) {
return err;
}
})()
}
}
附带示例:
const config = {
timeout: 5 * 1000, // 超时,单位毫秒(超时后会强行终止用户脚本
// 但是由于顶级函数的某些vm特性(@吉吉 看你干的好事),会在之后二次抛出其他错误,但是不致命,放心使用)
permission: { // 允许脚本使用的内容
Promise, // 向内提供Promise
str: 'NomenYYDS', //在内部环境可以直接读取的字符串
log: (t) => console.log(t) // 向内提供了一个方法
},
};
async function main() {
var code = async () => {
let result = await new Promise(resolve => { setTimeout(() => resolve(null), 3 * 1000); });
return 'awa';
}; // 一个用户脚本,可以是字符串或函数
// 并且可以是异步函数
let ns = new NomenSandbox(config, code);// 初始化沙盒
try {
let res = await ns.run(); // 启动沙盒
console.log(res); // 获取用户脚本返回的
} catch (err) {
console.log('Error When Main' + err); // 要try-catch不然会致命
}
}
main()
=====
这个工具会出现在Box3-Tools仓库中,希望大家多多支持
Nomen还没有沙发的话,我来讲讲怎么用吧:
首先,我们需要一段人畜无害的die码,可以是字符串或者函数:
const config = {
timeout: 5 * 1000, // 超时,单位毫秒(超时后会强行终止用户脚本
// 但是由于顶级函数的某些vm特性(@吉吉 看你干的好事),会在之后二次抛出其他错误,但是不致命,放心使用)
permission: { // 允许脚本使用的内容
Promise, // 向内提供Promise
str: 'NomenYYDS', //在内部环境可以直接读取的字符串
log: (t) => console.log(t) // 向内提供了一个方法
},
};
async function main() {
var code = async () => {
voxels.setVoxel(11,45,14,'NomenYYDS!')
}; // 此处可以是某些加密了的毁图boom
let ns = new NomenSandbox(config, code);// 初始化沙盒
try {
let res = await ns.run(); // 启动沙盒
console.log(res); // 获取用户脚本返回的
} catch (err) {
console.log('Error When Main' + err); // 要try-catch不然会致命
}
}
main()
然后就会返回voxels不存在的错误,因为你还没有为其授权voxels,它甚至连global都无法获取,包括property,proccess,world之类的东西(包括require,JSON之类的原生)
如果你要为他授权,只需要在config.permission里加上这个东西:
const config = {
timeout: 5 * 1000,
permission: {
str: 'NomenYYDS', //用户脚本在内部可以像引用局域变量一样引用这个字符串
log: (t) => console.log(t),
voxels, //然后用户脚本就可以读取voxels了
},
};点赞0
评论
没尾巴的鲸鱼_只要添加3个config项,添加一下这个对象代理替换代码就可以解决constructor的问题(
if (this.constructorVisit) {
for (el in this.permision) {
this.permision[el] = new Proxy(this.permision[el], {
get(target, key) {
if (target[key] == target.constructor) { return undefined };
if (r.bannedGet[el].includes(key)) { return undefined };
return target[key];
},
set(target, key, val) {
if (target[key] == target.constructor) { return undefined };
if (r.bannedSet[el].includes(key)) { return undefined };
target[key] = val;
}
})
}
}点赞0
评论
没尾巴的鲸鱼_弄门🚪,我给沙盒执行提供的接口对象装上了代理,自带防构造器攻击,可以做到隔离特定成员,但while喵循环执行超时咋解决啊,是object有方法监听循环入口事件吗?
class SwingSandbox {
constructor(config, _code) {
this.timeout = config.timeout || 10 * 1000;
this.permision = config.permission || {};
this.constructorVisit = config.constructorVisit || false;
this.bannedSet = config.bannedSet || {};
this.bannedGet = config.bannedGet || {};
this.finish = false;
this._cancel = false;
this.pgm = `try {
return (async () => {
let __st = setTimeout(() => {
if (sandbox.__finish__) { clearTimeout(__st); return; }
sandbox.__complete(new Error('[SwingSandbox] Sandbox Execute Timeout'));
throw new Error('[SwingSandbox] Sandbox Execute Timeout');
}, ${this.timeout});
with (sandbox) {
(async () => { return await ${(typeof _code == "function") ? '(' + _code.toString() + ')()' : _code} })()
.then(v => __complete(v))
.catch(e => __complete('[SwingSandbox: Error When execute user script]'+e))
.finally(() => __finish__ = true)
};
})()
} catch (err) { __complete('[SwingSandbox: Error When Runing SwingSandbox]'+err) }`;
}
__run__() {
if (this.finish) return;
return (async () => {
let r = this;
Object.assign(this.permision, {
get __finish__() { return r.finish || r._cancel },
r,
setInterval,
clearInterval,
setTimeout,
clearTimeout,
Error,
Promise,
})
if (this.constructorVisit) {
for (el in this.permision) {
this.permision[el] = new Proxy(this.permision[el], {
get(target, key) {
if (target[key] == target.constructor) { return undefined };
if (r.bannedGet[el].includes(key)) { return undefined };
return target[key];
},
set(target, key, val) {
if (target[key] == target.constructor) { return undefined };
if (r.bannedSet[el].includes(key)) { return undefined };
target[key] = val;
}
})
}
}
try {
let result = await new Promise(resolve => {
r.permision.__complete = (v) => resolve(v)
const sandbox = new Proxy(r.permision, {
has() { return true },
get(target, key) { return (key == Symbol.unscopables) ? undefined : target[key] }
});
const cd = new Function('sandbox', r.pgm);
cd(sandbox)
.then(v => {
this.finish = true;
}).catch(e => { })
});
return result
} catch (err) {
return err;
}
})()
}
}点赞0
评论