最初原因是有防爬的需求,因此需要对于 web 应用进行安全防护,从最初的数据对称加密(aes) ,到字体混淆(fontmin) ,再到后面的非对称加密(rsa + sm4) ,以及 js 代码混淆(javascript-obfuscator) 。做的越多越是觉得前端所能做其实很有限,以上种种都避不开一个问题,js 最终是要在浏览器运行的并且界面也要响应用户的交互行为的,甚至爬虫不用关心你的底层逻辑,直接执行你的代码即可拿到最终数据, 这个结论无疑是令人沮丧的,但是转念一想不能因为锁能被撬开,就连门都不关了。防爬,准确来说攻防相关是一个循环往复的过程,只能不断提升攻击者的攻破的成本,拦截掉一大部分,非专业人士的爬取。那我们先抛开整个风控系统不谈,思考一下前端还能做些什么。
其实最开始的时候,下意识想的防爬其实是怎么不让用户调试代码,方案用的也都是大家日常见到的方案。
禁用 devtools
代码混淆
最基础的压缩。最常用的 UglifyJS,Terser,esbuild 等。只是压缩了代码体积,简单的字符串混淆。经过 devtool format
之后具有较强的可读性,调试起来十分方便。
基础的混淆,eval 混淆,aa & jj 混淆。此类都是比较有规律的,比如 eval 内部方法的字符串一般使用 base64。aa & jj 就是相似字符作变量名,降低可阅读性。
集大成者 javascript-obfuscator 或者类似的 OOLVM 混淆,主要包含了 控制流平坦化
、虚假控制流
、指令替换
,核心是控制流平坦化,简单介绍一下:
控制流平坦化
基本块的执行流程,通过控制流平坦化,基本块间的前后关系将被混淆,从而加大了程序逆向分析的难度。逆向的思路基本是使用符号执行
或者AST
还原混淆代码
WebAssembly, 使用C、C++、C# 、Rust 开发编译为wasm格式的低级类汇编语言,WebAssembly本质上是为提升性能使用等, 一些核心的逻辑可以使用这些语言比如说加解密逻辑。用户只能在浏览器看到二进制数据而无法查看加解密的逻辑,当然只是能提升逆向的难度而已,能编译就能反编译。
jsvmp 配合WebAssembly使用
jsvmp 全称 js虚拟化保护(Virtual Machine based code Protection for JavaScript)
,
简单来说就是将代码转换成自定义的字节码,浏览器加载的就是这些字节码,这些字节码只有虚拟解释器才能识别出来。这个方案特殊在虚拟解释器
使用WebAssembly
来实现,使用C语言做解释器,WebAssembly
方案可以隐藏关键的解释器执行逻辑。
从本质上来说,上跟上一篇文章的
吾爱破解
插入到NeatReader
源码内部的那段代码一致。那段免责声明就是一段无法识别的Unicode(指令编码),只有经过他写的某个函数(解释器),才能计算出这段文本是什么。jsmvp这种方案是将代码也全部指令化了。解释器放入到了wasm文件中。 js代码安全-反编译初试
JSVMP的保护流程图
基于 WebAssembly 的 JavaScript 代码虚拟化保护方法- 匡开园