JavaScript 反混淆的一般套路和技巧: 转

把没用的多余的简写的代码处理完后, 代码就差不多有个基本的样子了, 不过现在还没到休息的时候. 由于函数错综复杂、变量名表达不出语义等原因, 我们的代码虽然可读性较之前已经得到了提高, 但想要完整理解代码的意图, 在当前的情况下仍然是一件麻烦的事.

为了理解代码, 通常我们要做两件事, 一件是“基于主函数的运行顺序整理”, 另一件是” 猜解变量名和函数名 ” , 之后, 代码在可读性上就能更加接近原始代码的级别了.

基于主函数的运行顺序整理

除非你在反混淆的代码是一个库或者模块, 否则每一段独立的程序, 都会有一个主体的部分, 反混淆到达这一步, 你需要找出整个代码的主函数.

主函数可能是整段代码中最长的那段代码, 也可能是整段代码最尾部的那一段代码, 或者, 整段代码就是被安排好了顺序执行的, 那么整段代码就是主函数.

找到主函数之后, 再继续寻找那些代码中只被调用过一次的函数, 如果存在这些函数, 直接把这些函数的代码抽出来, 合并进主函数里, 当然, 你还需要确定和管理好变量各自的作用域, 这并不是件易事, 但如果你这么做了, 代码可能会产生像从异步到同步那样在可读性方面的神奇转变.

再接下来, 你需要调整函数和变量声明的位置, 将它们分类, 比如把变量声明全部放在函数头部之类的, 而函数都应该被放在它所处层的最顶部, 如果能把代码像ES5定义的严格模式那样格式化好, 可读性也会得到上升, 起码这个时候, 你不需要借助IDE之类的工具把各种语法上的定义通过列表之类的控件特别抽离出来就能找到它们所应处的位置, 不过这也是非常难做的一件事.

事实上, 在ES6和ES7里, JavaScript被赋予了很多新的特性, 让这门本来就显得有些离经叛道的语言, 变得更加酷炫也更加难以琢磨, 不过我没反混淆过ES5以上的JavaScript代码, 所以关于ES6和之后的标准在反混淆时应当如何处理运行顺序, 我是不知道的, 如果有这个机会, 我会写一篇续篇补上关于ES6和ES7的部分.

猜解变量名和函数名

这可能是整个反混淆中最压抑的部分, 每一个程序员都怕用a, b, c…或者apple, banana, pear…作为变量名和函数名的程序员, 而大多数压缩工具, 都是这样的程序员.

在这里, 我们先从规模最小的函数开始入手, 像那些只有几行的函数, 是最容易搞明白具体意思的, 当你看懂它的意图之后, 请根据你所熟悉的命名规范来为其命名, 不过无论是哪种变量命名方式, 我都建议在变量名上标上它指向的数据的类型(如果一个变量指向过多种类型, 建议创建一个新的变量来表示这种新的类型). 如果变量名起了冲突或实在无法决定该如何命名时, 可以考虑在变量名或类型名后加上数字序号的命名方法, 因为即便这样命名, 也比用a, b, c来得好.

规模最小的函数搞定之后, 继续猜解调用这些函数的其他函数, 逐层向上, 最终就能猜解完大多数的代码.

另外, 如果函数内部出现了有关浏览器环境的内容, 比如XHR和Cookie之类的内容, 你完全有理由相信并大胆猜测这个函数与这些内容有关, 以此作为假设继续猜解其他内容, 将可能得到效率上的提升. 多利用编辑器的查找和替换功能, 也可以帮助减少疏漏.

至此, 代码的反混淆已经大致完成, 在下一章, 也是最后一章《JavaScript 反混淆的一般套路和技巧: 结》中, 将说明一些反混淆过程中的其他注意事项.