AST反混淆实战|某里226混淆代码还原详解

关注它,不迷路。       

本文章中所有内容仅供学习交流,不可用于任何商业用途和非法用途,否则后果自负,如有侵权,请联系作者立即删除!

1. 需求分析

最近网络上对阿里226的分析文章突然多了起来,我也来蹭一波热点试试。我还原的是下面的这个js:

https://aeis.alicdn.com/AWSC/fireyejs/1.226.0/fireyejs.js

话不多说,直接开干。

2. 思路详解

1.拿到压缩的混淆代码,先用反混淆通用模板处理一下,将其格式化,这样我们才好分析从哪里下手。

2.格式化后,看到了大量的 void 语句:

void (3 == h ? r = U < F.length ? 7 : 6 : h < 3 ? 1 == h ? r = y < O.length ? 8 : 1 : h < 1 ? (y++, r = 16) : (U++, r = 48) : 5 == h ? r = D < T.length ? 9 : 11 : h < 5 ? r = void 0 : (D++, r = 80));

它的父节点竟然是 表达式语句,相当于这里的 void 操作符可有可无,写个插件,可以轻松还原:

const restoreUnaryExpression = 
{
  UnaryExpression(path)
  {
    let {node,parentPath} = path;
    if (!parentPath.isExpressionStatement({"expression":node}) || !types.isConditionalExpression(node.argument))
    {
      return;
    }
    
    path.replaceWith(node.argument);


  },
}

还原后的代码如下:

3 == h ? r = U < F.length ? 7 : 6 : h < 3 ? 1 == h ? r = y < O.length ? 8 : 1 : h < 1 ? (y++, r = 16) : (U++, r = 48) : 5 == h ? r = D < T.length ? 9 : 11 : h < 5 ? r = void 0 : (D++, r = 80);

3.接下来就是将上面的条件表达式语句转换为 if 语句,还原后的代码如下:

if (3 == h) {
    if (U < F.length) {
        r = 7;
    } else {
        r = 6;
    }
} else {
    if (h < 3) {
        if (1 == h) {
            if (y < O.length) {
                r = 8;
            } else {
                r = 1;
            }
        } else {
            if (h < 1) {
                y++,
                r = 16;
            } else {
                U++,
                r = 48;
            }
        }
    } else {
        if (5 == h) {
            if (D < T.length) {
                r = 9;
            } else {
                r = 11;
            }
        } else {
            if (h < 5) {
                r = void 0;
            } else {
                D++,
                r = 80;
            }
        }
    }
}

4.接下来就是将if语句转换为switch语句了,不过从上面的代码可以看到,变量 h 和数字 比较,有时候在左边,有时候又在右边,不方便处理,因此写个插件将其统一一下,变量全部放到左边去,处理后的代码如下:

if (h == 3) {
    if (U < F.length) {
        r = 7;
    } else {
        r = 6;
    }
} else {
    if (h < 3) {
        if (h == 1) {
            if (y < O.length) {
                r = 8;
            } else {
                r = 1;
            }
        } else {
            if (h < 1) {
                y++,
                r = 16;
            } else {
                U++,
                r = 48;
            }
        }
    } else {
        if (h == 5) {
            if (D < T.length) {
                r = 9;
            } else {
                r = 11;
            }
        } else {
            if (h < 5) {
                r = void 0;
            } else {
                D++,
                r = 80;
            }
        }
    }
}

5.这样处理后,可以将 if语句转换为 switch语句了,还原后的代码如下:

switch (h) {
    case 0:
        y++,
        r = 16;
        break;
    case 1:
        if (y < O.length) {
            r = 8;
        } else {
            r = 1;
        }
        break;
    case 2:
        U++,
        r = 48;
        break;
    case 3:
        if (U < F.length) {
            r = 7;
        } else {
            r = 6;
        }
        break;
    case 4:
        r = void 0;
        break;
    case 5:
        if (D < T.length) {
            r = 9;
        } else {
            r = 11;
        }
        break;
    case 6:
        D++,
        r = 80;
        break;
}

6.处理完毕后,发现switch嵌套了switch,是由三个变量控制的,因此可以写代码,将三重的switch语句转换为一重,方便后续继续还原:

0b5c444e5ffd34b1fa552d20a665a15f.png

7.switch节点没问题了,接下来就是还原 控制流了,但是在还原控制流之前,需要做一些预处理,比如还原逗号表达式,将多重嵌套的赋值语句提取出来:

x[d = d.split("").reverse().join("")]("");
......
var v = "b",l = x[p = (p += "oLtes").split("").reverse().join("")][v += "ind"](x),u = "c";

还原成:

d = d.split("").reverse().join("");
x[d]("");
......
var v = "b";
p += "oLtes";
p = p.split("").reverse().join("");
v += "ind";
var l = x[p][v](x);

总之,再去控制流之前,把一些能处理的节点,优先给他处理掉,主要是为了能使用星球里的九大节点合并算法。

8.接下来就是去除控制流的虚假分支了,大量充斥着这样的代码:

case 10561:
            go = 3;
            xe = 3 * go;
            Fo = xe > -74;
            i(38, ye, x, i, !0, V, !0);
            Si = Fo ? 22049 : 1573;
            break;

这里的Fo恒为 true,因此,可以改写成这样:

case 10561:
            go = 3;
            xe = 3 * go;
            Fo = xe > -74;
            i(38, ye, x, i, !0, V, !0);
            Si = 22049;
            break;

其他的节点是否也是如此呢?请大家自行验证。

9.接下来就是真正的去除控制流了,使用九大节点合并算法,处理后,还剩 34 个case没有被还原:

4a2bc41d07ef7b03a0890693d1bdfc12.png

为啥没有被还原,分析了一下,原来是 一个循环里面的代码太多,合并算法不适用,因此,需要想个方法来让它适用。

case 4452:
            Si = eo >= 0 ? 26306 : 12289;
            break;
 ......
 
  case 14752:
            m = 0 === S;
            if (m) {
              m = 0 === j;
            }
            f = m;
            if (f) {
              f = 0 === A;
            }
            m = f;
            Si = m ? 22880 : 13858;
            break;
 
  case 22880:
            eo--;
            Si = 4452;
            break;

分析上面的代码,其实可以合并成这样:

不适用,因此,需要想个方法来让它适用。


  case 4452:
            Si = eo >= 0 ? 26306 : 12289;
            break;
 ......
 
  case 14752:
            m = 0 === S;
            if (m) {
              m = 0 === j;
            }
            f = m;
            if (f) {
              f = 0 === A;
            }
            m = f;
            if(m)
            {
              eo--;
              continue;
            }
            Si = 13858;
            break;
 
  case 22880:
            eo--;
            Si = 4452;
            break;

像这样的节点可以找规律写代码合并。这样处理后,再使用 九大节点合并算法在处理一次,就可以完全还原了。

c9b3c336d5d8d1282eb4a298bd625c4e.png

还剩 8个 case,这就无关紧要了。

10.接下来合并字符串了,代码中有大量类似下面的代码:

var T = "167,xspulrlrlsx";
    var L = "";
    var D = 0;
    while (D < T["length"]) {
      var _ = 66 ^ T["charCodeAt"](D);
      L += String["fromCharCode"](_);
      D++;
    }

可以说,非常的多,它其实可以被计算出来具体的值,并进行合并替换:

var L = 'stun:127.0.0.1:';

上面的代码就缩减成了一行,可以所非常的爽!

11.紧跟着,就是赋值语句的还原了,因为是反复被赋值,没法用binding来处理,可以试试星球里的脚本:

be = "<br>";
Se = be;

还原后:

be = "<br>";
Se = "<br>";

12.上面的代码处理后,还可以进一步处理,比如删除 be 这个语句变成:

Se = "<br>";

当然,这需要视情况而定。

还原后的代码如下:

b7c870b04223b31e9774bd61fe215684.png

拿到网上替换调试:

da9344d8164037fe91eb89ace77b6763.png

还原到这里基本就差不多了,还有一些小的混淆代码可以处理,不再本文中讲述。

  • 5
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
### 回答1: ast混淆JS还原工具是一种强大的工具,可以帮助程序员和安全研究人员解决混淆的JavaScript问题。该工具的原理是通过解析抽象语法树(AST)来还原混淆的JavaScript代码,从而让代码恢复其原有的结构和逻辑。 AST混淆JS还原工具的优点是可以解决常见的混淆技术,如变量名替换、函数名替换、控制流混淆等。同时,该工具还支持多种JavaScript框架和库,可以有效避免由于第三方库混淆而导致的代码不可读性问题。 但是,需要注意的是,AST混淆JS还原工具并不能完全解决所有的混淆问题。在某些情况下,可能需要手动修改代码或使用其他工具进行修复。此外,该工具也可能会导致一些性能问题,特别是在处理大型JavaScript代码时。 总的来说,AST混淆JS还原工具是一种非常有用的工具,可以帮助开发人员和安全研究人员节省大量时间和精力。但是,使用该工具还需要仔细考虑其适用性和局限性。 ### 回答2: AST混淆JS还原工具是一种专门用于还原JavaScript代码的工具。AST是抽象语法树的缩写,它是一种能够把代码转换成树形结构的工具。在JavaScript中,所有的代码都是由AST表示的。因此,混淆代码实际上是对AST进行混淆,而混淆工具就是通过分析混淆后的AST还原出原始代码AST混淆JS还原工具有很多种,它们主要使用了一些静态和动态分析技术。静态分析就是直接分析混淆代码,从中找到解密算法和加密密钥等关键信息,并使用这些信息来解密代码。动态分析则是通过模拟代码的运行环境来解密代码,在代码运行时注入一些代码片段,以便找到解密算法和密钥。 无论是静态分析还是动态分析,AST混淆JS还原工具都需要在很多方面投入时间和精力。首先,它们需要分析混淆代码的结构,找出其中的规律,并将其还原AST中。其次,它们需要处理各种类型的混淆,包括命名混淆、结构混淆代码混淆等。最后,它们需要使用一些优化技巧来提高还原的效率和准确性。 总之,AST混淆JS还原工具是一种强大的混淆技术,它可以用于提高代码的安全性和保护知识产权。但需要注意的是,还原工具不应该被用于不道德的行为,如盗版或攻击等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值