· parser,把 JavaScript 代码解析成抽象语法树
· code generator,通过抽象语法树生成代码
· scope analyzer,分析变量定义的工具
· tree walker,遍历树节点
· tree transformer,改变树节点
对比下我上面给出的混淆器设计的图,发现其实只需要修改语法树 这一步自己完成。
实例
说了这么多,可能很多人还是一头雾水,为了帮助各位理解,我准备了一个简单的例子,假设我们的混淆规则是想把 var a = 1; 中的数字1换成16进制,我们该如何设计混淆器呢。首先对源代码做词法分析和语法分析,uglify一个方法就搞定了,生成一颗语法树,我们需要做的就是找到语法树中的数字然后修改成16进制的结果,如下图所示:
实例代码:
var UglifyJS = require("uglify-js");
var code = "var a = 1;";
var toplevel = UglifyJS.parse(code); //toplevel就是语法树
var transformer = new UglifyJS.TreeTransformer(function (node) {
if (node instanceof UglifyJS.AST_Number) { //查找需要修改的叶子节点
node.value = '0x' + Number(node.value).toString(16);
return node; //返回一个新的叶子节点 替换原来的叶子节点
};
});
toplevel.transform(transformer); //遍历AST树
var ncode = toplevel.print_to_string(); //从AST还原成字符串
console.log(ncode); // var a = 0x1;
上面的代码很简单,首先通过parse方法构建语法树,然后通过TreeTransformer遍历语法树,当遇到节点属于UglifyJS.AST_Number类型(所有的AST类型见ast),这个token具有一个属性 value 保存着数字类型的具体值,我们将其改成16进制表示,然后 return node 就会用新的节点代替原来的节点。