JS逆向:AST 语法树反混淆策略处理控制流平坦化

时间:2021-7-4 作者:qvyue

1、控制流

  • 控制流(Control Flow),指的是
  • 控制流基本语法包括两种:
    第一种:if / else 条件语句判断
if(条件){  };
else{  };

第二种:while / switch / case 条件语句判断

while (option) {
    switch (args){
        case 1:console.log('case 1,xxx');
        case 2:console.log('case 2,xxx');
        case 3:console.log('case 3,xxx');
    }
}

2. 控制流平坦化

  • 控制流平坦化(Control Flow Flattening)是一种代码混淆方式,其基本思想是让所有的基本块都有共同的前驱块,而该前驱块进行基本块的分发,分发用switch语句,依赖于switch变量进行分发。
  • 具体是先为每个基本块进行值编号,每个基本块就是一个case块,如果基本块有后继块,就替换每个基本块的后继块,新的后继块更新switch变量为后继块的值,然后跳转到switch开始分发处,初始switch变量为入口entry块的值。
  • 现已有一些编译器实现了控制流平坦化,Obfuscator-LLVM(简称 OLLVM)是一种基于 LLVM 框架的实现,这是目前比较主流的控制流平坦化实现方法;
  • 例如,有下面的代码,正常形态下我们可以很容易看懂其逻辑:
// 正常形态
function test(a){
   var b = a;
   b += 1;
   b += 2;
   b += 3;
   b += 4;
   return a + b
  • 通过加密操作,得到下面的代码,这样看起来就会复杂得多,调试的时候如果此处下断点,跳来跳去也会让人觉得头晕:
// 乱序形态
function test() {
    for (var s = 1; void 0 !== s; ) {
        var r = 3 & s
          , c = s >> 2
          , b = 3 & c;
        switch (r) {
        case 0:
            !function() {
                switch (b) {
                case 0:
                    k += "do",
                    s = 8;
                    break;
                case 1:
                    k += "Nt",
                    s = 2;
                    break;
                case 2:
                    s = k ? 4 : 2;
                    break;
                case 3:
                    s = void 0
                }
            }();
            break;
        case 1:
            var k = "e";
            s = k ? 0 : 8;
            break;
        case 2:
            k += "nerap",
            k = k.split("").reverse().join("");
            var i = kr[k];
            s = i ? 3 : 12;
            break;
        case 3:
            a.push(175528201),
            a.push(24898129191),
            a.push(2),
            a.push(0),
            e(13, 2, -1);
            var o = a.pop();
            i[o](kr),
            s = 12
        }
    }
}
  • 上面这段代码以 switch-case 的方式实现使用了控制流平展混淆。相比于常规的控制流平展混淆的改进之处在于,它的 switch-case 结构不止一层,本例中嵌套了一层,理论上可以多层嵌套;
  • 针对不止一层switch-case结构的混淆变种,需要把原始方案作一个增强。我们采用树形结构来表示原始的控制流结构。一层switch-case可看做只有两层的树。多层switch-case相当于在对应节点上的继续延伸,从而形成三层、四层…的树形结构;

    JS逆向:AST 语法树反混淆策略处理控制流平坦化
    20200605121640582.png

3. AST 语法树处理控制流平坦化

  • 首先将上面的代码复制到 https://astexplorer.net/,得到下图:
    JS逆向:AST 语法树反混淆策略处理控制流平坦化
    image.png
  • 通过分析,我们得出这段代码包含两侧的 switch / case 嵌套,如下图:

    JS逆向:AST 语法树反混淆策略处理控制流平坦化
    image.png
  • 之后,我们查找 switch 条件,分析条件参数;

    JS逆向:AST 语法树反混淆策略处理控制流平坦化
    image.png
  • 结合条件参数和执行逻辑逻辑,即可推导出最初的代码;
声明:本文内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:qvyue@qq.com 进行举报,并提供相关证据,工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。