用于对使用字符串连接的javascript进行去混淆的方法

时间:2016-10-08 06:18:26

标签: javascript obfuscation deobfuscation

我正试图解开一种去混淆看起来像这样的javascript的方法:

https://jsfiddle.net/douglasg14b/4951br9f/2/

var testString = 'Test | String'

var wf6 = {
 fq4: 'su',
 k8d: 'bs',
 l8z: 'tri',
 cy1: 'ng',
 t5j: 'te',
 ol: 'stS',
 x3q: 'tri',
 l9x: 'ng',
 gh: 'xO'
};


//Obfuscated
let test1 = testString[wf6.fq4 + wf6.k8d + wf6.l8z + wf6.cy1](4,11);

//Normal
let test2 = testString.substring(4,11);
let test3;

//More complex obfuscation
(function moreComplex(){
	let h = "i",
        w = "nde",
        T0 = "f",
        hj = '|',
        a = eval(wf6.t5j + wf6.ol + wf6.x3q + wf6.l9x).length;
    //Obfuscated
    test3 = testString[wf6.fq4 + wf6.k8d + wf6.l8z + wf6.cy1](testString[h + w + wf6.gh + T0](hj), a);
    
    //Normal
    let test4 = testString.substring(testString.indexOf('|'), testString.length);
        
})();

$('.span1').text(test1);
$('.span2').text(test3);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<span class="span1"></span><br>
<span class="span2"></span>

这是一个小例子,我正在使用的文件大约是60k行,并且这种混淆是完整的。在任何地方都可以使用字符串作为属性名称,使用这种混淆。

我能想到这样做的方法是评估所有字符串连接,以便将它们转换为可读的等价物。虽然,我不知道如何解决这个问题,并忽略所有连接之间存在的所有其他工作代码。

思想?

加分问题:这种混淆是否有一个常用的名称可能会使搜索更容易?

编辑:添加了一个更复杂的示例。

1 个答案:

答案 0 :(得分:4)

您的基本想法是正确的:您必须partially-evaluate该程序并预先计算所有常量计算。在您的情况下,主要兴趣的不断计算是不会改变的值的连接步骤。

要执行此操作,您需要program transformation system (PTS)。这是一个工具,它将读取/解析指定语言的源代码并构建一个抽象语法树,允许您指定AST上的转换和分析,并运行它们,然后再次将修改后的AST作为源代码吐出。

在你的情况下,你显然想要一个PTS连线知道开箱即用的JavaScript(罕见)或愿意接受JavaScript的描述然后阅读JavaScript(更典型),希望你可以构建或轻松获取JavaScript描述。 [我构建了一个可以使用JavaScript描述的PTS,请参阅我的生物]。

有了这个,你需要:

  • 对分析器进行编码,该分析器检查表达式中找到的每个变量,以查看该表达式是否为常量(例如,&#34; wf6&#34;)。要证明它是常量,您必须找到变量定义,并检查变量定义中使用的所有值本身是否为常量。如果存在多个变量定义,则可能必须检查所有定义是否生成相同的值。你需要检查变量的副作用(例如,没有函数调用&#34; foo(...,wf6,...)&#34;这将允许变量的值被修改)。你需要担心是否存在实现这种副作用的eval命令[这几乎是不可能做到的,所以你经常不得不忽略evals并假设他们不做这样的事情]。很多PTS都有办法让你建立这样的分析仪;有些比其他人容易。
  • 对于每个常量值变量,在代码
  • 中替换该变量的值
  • 对于这些替换后的每个常数值子表达式,&#34; fold&#34; (计算)该表达式的结果并将该值替换为该子表达式并重复直到不再可能折叠为止。显然你想要至少为所有&#34; +&#34;运营商。 [OP刚修改了他的例子;他希望为#e; eval&#34;当所有操作数都是常数时,运算符也是如此。
  • 您可能必须迭代此过程,因为折叠表达式可能会使变量显然具有常量值

上述过程被称为&#34;恒定传播&#34;在编译器文献中,是许多编译器的一个特性。

在您的情况下,您可以将常量折叠限制为仅字符串连接。但是,一旦你有足够的机器来进行恒定值传播,对常数做所有或大多数操作都不是那么难。您可能需要这样来撤消其他涉及常量的混淆 似乎是您正在使用的代码上使用的混淆样式。

您需要一个转换

的特殊规则
var['string'](args)

 var.string(args)

作为最后一步。

你有另一个复杂因素:那就是知道你拥有与生成常量值变量相关的所有JavaScript。单个网页可能包含许多JavaScript内容;你将需要所有这些来证明变量没有副作用。我假设在你的情况下,你确信你拥有这一切。

关于生成已知常量值,您可能会担心一个棘手的情况:一个从非常量操作数生成常量值的表达式。想象一下混淆的表达是:

   x=random(); // produce a value between 0 and 1
   one=x+(1-x); // not constant by constant propagation, but constant by algebraic relations
   teststring['st'[one]+'vu'[one+1]+'bz'[one]+...](4,11)

你可以看到它总是计算&#39; substring&#39;作为财产。您可以添加一个转换规则,该规则可以理解用于计算&#34;一个&#34;的技巧,例如,用于计算已知常数的每个代数技巧的规则。不幸的是,你可以用无穷多的代数定理来制造常数;在你的示例代码中真正使用了多少代码? [欢迎使用智能对手进行逆向工程问题]。

不,这个&#34;容易&#34;。据推测,这就是混淆方法的原因 选择使用。