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

最近发现网上没有什么专门深入去讲解JavaScript反混淆的文章, 能找到的, 基本都是针对于某一种加密方式的简单解密方法, 虽然能够解决一时的问题, 但从学习和研究的角度去看, 并没有太多价值. 加之近日从他人手中接手了一个算是有些棘手的反混淆单子, 感觉有所收获, 遂将自己在反混淆方面的一些理解和方案, 做一下记录, 于是便有了此文.

这篇文章假设你是一位使用JavaScript的中级以上水平的前端工程师, 对于一些相对基础的内容, 将不做讨论和额外讲解. 原先打算只写一篇文章, 但考虑到内容较多, 没有一次性写完的精力, 请原谅我分成多篇文章来写.

在开始动手之前, 你需要知道…

作为一位熟练使用JavaScript的编程人员, 你应该已经非常明白, JavaScript作为一个以函数式为核心的多范式动态弱类型脚本语言, 它的灵活性太强大了, 这直接导致了源代码在经过一些压缩工具的蹂躏之后, 变得极难还原. 所以, 你几乎不可能把代码还原到跟原始代码一致, 这是事实, 你能还原出来的, 通常只是和原本的代码运行流程一致的另一份代码.

不过, 也确实存在可以直接还原的代码, 比如这个:

eval(function(p,a,c,k,e,r){e=String;if(!''.replace(/^/,String)){while(c--)r1=k1||c;k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k1)p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k1);return p}('0.1("2 3!")',4,4,'console|log|Hello|World'.split('|'),0,{}))  

我想告诉你的是, 这段代码的混淆太弱, 只做了单纯的加密, 所以并不能归类到需要认真去反混淆的代码范畴之中. 对于类似Jspacker这样的加密手段, 解密方法在网上一搜有一大把, 由于它过于简单和流行, 以至于不少代码格式化工具都自带了Jspacker的解密功能. 这种程度的加密, 基本只在表面上做了功夫, 防君子不防小人. 当然, 你也可以把加密后的代码再加密一次, JavaScript的强大灵活性允许你这么做, 但和加密一次相比, 效果也差不多, 因为加密太简单, 而原始代码的可读性又太强.

还有一类混淆器, 在降低代码可读性上确实下了不少功夫, 比如把变量名设置成i, 1, l, I,|或者O,o,0这样的相似字符, 把加密后的代码拆分后再次加密等等, 以前写过的《l1l=document.all 特征 JS 混淆器反混淆流程详解》就是这种混淆, 比较可惜的是, 那篇文章里的例子在执行后会将原始代码直接作为script挂在document上, 去进行反混淆的唯一作用就是看看解密过程中除了把script挂到document上之外, 还有没有做其他的事, 付出与回报的价值有很大可能性不符, 性价比太低了.

读到这里你大概也猜到了, 在进行反混淆时, 你需要了解和明确的是: 什么是有价值去反混淆的代码? 怎样最小化你因为反混淆在时间上的损失? 而这些, 就是我接下来要告诉你的.

什么是有价值去反混淆的代码?

为什么要反混淆这段代码? 在面对一大堆看都不想看一眼的数字字母符号组合出来的文本之前, 你必须问自己这个问题. 一般来说, 只有利益驱使这么一种原因, 这里的利益并不一定是金钱, 如果你在看到”利益”二字时只能想到金钱, 或许你该慎重考虑一下是否应该继续在这行干下去, 这里的利益可以是为了满足自己的好奇心一窥原理, 为了使用其中的某一段代码, 或是为了取证, 当然, 纯粹的金钱交易也是一种情况. 如果是最后一种情况, 那么你必须权衡好付出和回报, 也就是反混淆的性价比, 因为其他非金钱驱动的利益作为动机时, 多半情况下你是非干不可的, 而涉及到金钱时, 你是有权利不去干这种脏活的, 何况, 你也知道, 任何涉及到代码的事情, 预估需要耗费的时间, 是比较困难的. 作为程序员, 请尽量偷懒和拒绝去做你不感兴趣的事.

怎样最小化你因为反混淆在时间上的损失?

答案其实很简单, 只要充分的利用工具就行了. 工具永远是你最好的帮手, 如果有现成的工具, 请拿来用. 在存在现成的反混淆方案/工具的时候, 不拿来用而是尝试自己去人工进行反混淆, 在学习以外的目的上这么做绝对是自杀行为.

而在人工进行反混淆时, 你必然会用到的工具有2个: 一个符合你习惯的代码格式化工具和一个称手的代码编辑器.

在一般的反混淆流程中, 格式化代码总是最先要做的事, 代码格式化工具可以很快的帮你还原代码的格式, 这样你就可以比较轻松的看出代码的结构, 不过一般用完之后就没它什么事了, 剩下的就看你的技术和编辑器是否强力了.

代码编辑器则至少应该具有代码高亮和替换查找功能, 代码高亮应能正确的区分关键字和符号, 替换查找功能则必须能区分单词和大小写, 或是正则表达式.

除了格式化工具和编辑器, 你还可能用到类似js2coffee的代码转化工具以及类似CoffeeScript的JavaScript预编译器, 是否会用到这些工具, 取决于你的知识储备量和需要反混淆的代码的复杂程度.

至此, 你在反混淆上的准备应该完全了, 在下一篇文章《JavaScript 反混淆的一般套路和技巧: 承》中, 将讨论一些常见的混淆方式和反混淆的方法, 以及怎样组织各个流程的顺序.