JS代码安全之路:用JS对JS代码混淆加密( 二 )


注:在本结尾,会有一个彩蛋内容,实例介绍NodeJS字节码生成及运行 。
图1,NodeJS字节码效果:

JS代码安全之路:用JS对JS代码混淆加密

文章插图
 
回到正题,JS代码如何转化为AST?
其实,没有想象中那么复杂 。得益于NodeJS成熟的生态,已经有多个已实现模块可以完成这一操作 。比较流行的如:esprima、babel,都可以实现对JS代码进行词法分析、语法分析、生成AST、AST操作、从AST再生成JS代码 。
用esprima进行JS代码混淆加密 。程序框架 。图2、esprima框架demo:
JS代码安全之路:用JS对JS代码混淆加密

文章插图
 
如图2所示,使用esprima进行JS代码保护的原始功能框架 。
代码介绍:
Esprima实现将JS代码转化为AST;
estraverse对AST节点进行遍历,混淆加密的逻辑操作都将在此环节实现;
escodegen则是将操作后的AST转为JS代码输出 。
此demo代码未对AST进行任何处理,所以图中右侧的执行结果中可以看到,输出的JS代码与最初代码完全一致 。
AST是这样子的 。前面已经对AST进行了说明,AST具体是什么样?
一个方便的办法,是使用astexplorer.net,可以对输入的代码的AST即时同步显示:
图3、const a=1的AST:
JS代码安全之路:用JS对JS代码混淆加密

文章插图
 
Demo中使用的一行JS语句:“const a=1”,其AST即如图中所显示 。
AST是一个JSON结构 。
Program表示程序,子节点body中,是变量定义kind是“const”,字面量是“a”,值是“1” 。
看似杂乱,但很规整,细看便不难理解 。
demo程序里,在节点操作处可以用console输出AST,与astexplorer输出一至,不过前者更方便些 。
图4、在程序中输出AST:
JS代码安全之路:用JS对JS代码混淆加密

文章插图
 
借助Esprima修改AST实例:改“==”为“===” 。图5:
JS代码安全之路:用JS对JS代码混淆加密

文章插图
 
代码如上图,这是一个很简单的示例 。
程序中,estraverse对示例代码结点进行处理,当匹配到“==”时,改为“===” 。
为了明确修改节点细节,再对前后代码进行分析 。由图6、图7看到,差异仅在节点中的operator 。
图6、代码中使用“==”:
JS代码安全之路:用JS对JS代码混淆加密

文章插图
 
图7、代码中使用“===”:
JS代码安全之路:用JS对JS代码混淆加密

文章插图
 
借助Esprima修改AST实例:把parseInt改为标准语法 。parseInt方法,有两个参数,参数一是要转化的值,参数二是可选择项,是要转化的进制类型 。
图8:
JS代码安全之路:用JS对JS代码混淆加密

文章插图
 
通过astexplorer,先了解parseInt的AST,未使用参数二时,AST如下:
图9:
JS代码安全之路:用JS对JS代码混淆加密

文章插图
 
如果有第二参数,则AST如下:
图10:
JS代码安全之路:用JS对JS代码混淆加密

文章插图
 
那么,要将parseInt转为标准形式即是要给只有一个参数的调用增加第二参数 。
代码及执行结果如下:
图11:
JS代码安全之路:用JS对JS代码混淆加密

文章插图
 
因为初入手的原因,以上描述较为细致,后续将简化 。
方法名转义和转码 。如:console.log转为console[log]形式 。
通过在aspexplorer中比较可知,造成语句形式差异的原因是CallExpression成员中computed属性值的不同 。
图12:
JS代码安全之路:用JS对JS代码混淆加密

文章插图
 
那么,只需修改节对应节点的computed属性值即可:
图13:
JS代码安全之路:用JS对JS代码混淆加密

文章插图
 
而修改的条件,则是判断AST节点是CallExpression 。上面的例子中,也是使用相似的条件判断方法,找出要修改内容相对应的AST节点 。
再进一步,将方法名转为十六进制字符,console[log]会成为:console['x6cx6fx67'],以此进一步降低代码可读性 。
图14、增加字符串转16进制操作:
JS代码安全之路:用JS对JS代码混淆加密


推荐阅读