前言
好久没发帖了,在我发布rhino js的dex还原教程之后,autojs官方推出了另一种编译类加密:快照加密,从刚开始我便已开始研究,最近已经有一些人发布了运用AST进行语义还原的视频,甚至快照也有初步的还原,所以也没有什么藏着掖着的必要了,在这做个总结吧。
简介
快照加密是一种编译类的加密,将js编译为仅有rhino能够识别的二进制字节码,所有的条件、循环逻辑都被编译为了goto跳转语句,且字节码类型比使用dex编译更为繁多,所以还原难度极大,且直接修改字节码可能导致跳转错位,整个js脚本无法正常运行,运行逻辑抗修改性也极强。迄今为止,我依旧不能还原所有的js。
所需工具
- rhino官方文档
- rhino源码一份(可于github获取)
- idea/eclipse
具体过程
鉴别文件类型
刚开始,我拿到快照加密的结果,并不知道是什么类型的文件,所以可以去百度它的文件头。
搜索结果
从文件头可知这是一个java的序列化对象文件,然后再去翻rhino的官方文档。
rhino文档
rhino文档2
由此可知使用ScriptableInputStream即可读取这种文件。
寻找逻辑代码
读取之后。通过获取这个对象的class可知其为InterpretedFunction,也就是经过解释的函数。
函数类
根据英文意义判断,数据都在InterpreterData里面。
数据类
根据我的经验,这几个变量对应的含义已经标注在图片里了。
解析逻辑代码
这些字节码我们也不知道它的含义,那就得从编译器下手了,编译器类为Interpreter类。打开之后往下翻发现一个特殊的方法。
dumpICode
本来想着不会是编译为字节码了吧,谁知道真特么给我来了个惊喜,这确实就是字节码,全是goto的那种。。。
rhino内置AST
既然要还原,那肯定是要映射到一个AST上的,自己写一个AST太费劲,其它的解析库又不一定支持rhino的某些语法,最后发现rhino自带了一个js全套AST。
AST
那么直接使用这套AST进行映射就行了。
确定还原方式
在各种查找调试之后,最终决定为模拟一个栈,自行解析所有字节码,栈的内容为AST节点,类比Interpreter将数据加载之后从栈里出栈读取拼凑之后再入栈,遇到结束字节码时插入AST作为节点。
遇到函数字节码时,先行解析对应函数的字节码为AST,再将生成的FunctionNode放入栈顶即可
最后从AST根部直接生成源代码即可成为一个完整可运行的js。
效果图
效果图
左边为源代码,右边为根据字节码还原出来的代码。
可以看到为了正常表达所在作用域,变量都被提前声明了,let被解析为了var,多了几个括号。但是整体逻辑都与源代码别无二致。
难点
- 从goto中抽取与运算&&和或运算||
- 从多层if嵌套中正确识别有无else
- 正确区分三元运算?:与if-else
- 正确识别循环中的break与continue语句
- 正确区分let与var
- 使用,分隔的多运算语句
结束语
至此,与rhino有关的dex与快照编译类加密都被窥得全貌,虽然不至于完美还原所有js(现在的程度也就还原v6到可运行),但是原理已经被许多人知悉。正所谓能运行那必能被破解,所以没有绝对安全的加密,只有破解成本远大于收益即是真正的安全。
好了,所有内容就这些,研究到后面也没什么意思了,我继续潜水摸鱼去了,下次我再次发帖或许是新加密出现的时候?(手动狗头)
不要私聊我接不接单!仅限学习交流,不提供任何代码,有需求请自行编写代码!
|