探讨如何反制“反制CSense”
CSense 在 CCW(共创世界)进行了一些害人的行为,例如破坏云空间以破坏玩家体验、盗取作品。
社区中出现了很多“反制CSense”的方法,不妨来讨论一下这些方法的可行性。
这篇文章只是从技术上探讨这些方法的可行性,请不要进行捣乱!
操作DOM删去 CSense 的元素
这种方法是最常见的反制方法,原理是通过 JavaScript 操作 DOM,删去 CSense 的元素。
不过,这可能无效。例如说我们可以使用DOM API 拦截的方式阻止找到 CSense 的元素。
const RULES = [
s => s.toLowerCase().includes('csense'),
s => s.toLowerCase().includes('rgb(221'),
s => s.includes('脆弱性')
];
const QSDoc = Document.prototype.querySelector;
Document.prototype.querySelector = function(sel){
if (hit(sel, this)) return null;
return QSDoc.call(this, sel);
};
类似地,我们也可以重写getElementById、getElementsByClassName等方法。这样就可以阻止部分扩展通过 DOM API 检测并删去 CSense 的元素。
但是,有人就使用一些其他方法,例如使用JQuery来选择元素,这样就绕过了 DOM API 的拦截。不过类似地,我们也可以重写JQuery的选择器方法来阻止这种行为。
覆写 $('selector', ctx)、$.fn.find以及$.find的方式,相关事宜可以自行搜索。
查看 localStorage 以检测 CSense
CSense 会在localStorage中存储内容,例如__csense-storaged-script。如果你不使用 CSense 的脚本功能,你可以删去这些内容。
当然,你覆写localStorage的获取函数也可以,此处不再叙述。
“火速运行”会删除 vm.toJSON 防止盗作品
我去,你真是个天才!只不过这只能够防止“脚本小子”。
我直接劫持JSON.parse()不就行了?只要你作品加载了我就可以读取到你的作品的project.json,因为CCW会调用JSON.parse()来解析json。
而大多数 Scratch 社区都是这么做的,事实上,只需要下面这个例子就可以盗取大多数社区的作品。(别针社区修改了project.json,因此更有难度)
const _parse = JSON.parse;
JSON.parse = function(text, reviver){
// 只是一个示例,真实情况会更精准地查找
if (text.includes('target')) {
console.log(_parse.call(this, text, reviver));
}
return _parse.call(this, text, reviver);
};
扩展“混淆了”变量名,捣乱者无法查看变量到底是什么意思?
事实上你只需要覆写扩展,删去那些部分,并在扩展加载时拦截并替换就好了。
有很多方法拦截扩展,例如修改HTMLScriptElement.prototype,如果扩展通过XHR或是fetch加载,你当然也可以劫持他们并篡改请求。
或者,你可以像上文说的那样,覆写JSON.parse(),然后在project.json中修改扩展的加载地址,指向一个特定的“安全版”扩展。
如果扩展对其源代码混淆了怎么办?
一个简单的做法是,你自己开个作品,加载这个扩展,然后将其所有积木块拖动到代码区,并下载该作品。
之后,你可以解压该作品文件,找到project.json,然后在其中找到该扩展的积木块们对应的opcode,自己写一份“安全版”扩展。
对于“<是否检测到CSense?>”,恒返回false;对于“[冻结xxx变量]”,只需要储存是否冻结了变量然后什么都不做,需要返回的时候就返回储存下来的结果,这样作品无法检测到到底有没有冻结。
一个更加自动化的做法是,像v0.1.5版本的 CSense 一样,在SecureVM中加载扩展并生成相应的空扩展,然而这么做的缺点是可以被检测到。
例如,我先冻结变量a,然后检查是否冻结了变量a,如果返回true,那么解冻变量a,然后检查是否冻结了变量a,如果返回的不是false,那么该扩展很有可能被篡改了。
或者,如果冻结了变量a,那么检查变量a的值是否为true,如果不是,那么该扩展很有可能被篡改了。
我不了解扩展会怎么实现,但我也不关心他是如何实现的,我只需要写一份对应的具有类似行为的“安全版”扩展就行了,这对真正想要捣乱的捣乱这说来不是难事,即便他没有时间或精力或能力写扩展:他完全可以让AI代劳。
混淆其实没有什么用,扩展也难以阻止真正的捣乱者,在前端用这些简单的方法来阻止捣乱者是无效的,捣乱者的代码比你的先加载,你的代码能不能被运行都不一定呢。
那有什么方法可以防止捣乱者捣乱呢?
事实上,你不能够阻止捣乱者的所有捣乱行为,但是你能够防止捣乱者获取一些数据。
有趣的是,由于CCW开发者的疏忽、消极开发与修补漏洞,导致CCW存在及其危险的漏洞。试想这么一件事情:
今天,你发现你的所有金币都被投给了一个你压根就没玩过的作品(实际上,如果投给一个未发布的作品你可能都没有能力发现你的金币去了哪里),然而这背后的原因竟然是你在一年前玩了一个极具影响力的作品! 那个极具影响力的作品的作者,一个正直热心的人,为什么要盗取你的金币呢? 根据调查发现,其实他根本就没有加入相关的代码,而是别人添加的!原他在一年前无意间加载(注意没有运行或游玩)到了某个恶意作品,而恶意作品作者盗了他的号并在向他的作品中加入了恶意代码,而这个恶意代码作为扩展隐藏成
ceb2的模样,作者根本没有发现! 天哪,背后的原因令人寒心。
然而更有意思的是,从理论上来看,捣乱者还可以通过div遮罩的方式让你在浏览动态的时候就点进了恶意作品,并且恶意作品中的恶意代码可以感染你的作品并修改其内容和简介,来达到更大范围的传播。
这不是危言耸听,事实上,从技术上完全可行,并且也有了小范围的实践来证明其可行性。
因此,我认为目前在试图使用扩展反制 CSense 的开发者们,应当写几个脚本来防止被恶意盗号。
例如,劫持XHR查看响应体是否包含token等可以获取用户信息的内容,如果有就弹出弹窗提示并及时阻断。
又或者,禁止用户在作品页面中登录,因为在作品页中捣乱者完全可以获取到用户的密码和token。
结语
多学习。
另外,我不认为混淆代码是一个好的做法,用户难以得知里面是否混淆了恶意代码,这是不安全的。