JS逆向实战:加强版的 OB 混淆 AST 处理方法
大家好,今天分享一个加强版的 OB 混淆的处理方法。
加强版 OB 混淆
本次样本来源为猿人学第十题,题目难度为非常困难,本次仅分享 OB 混淆的处理方案,解题方法不在本次分享范围内。
混淆的 JS 一共有两层,外层为大量的反调试,使用 eval
执行加密后的代码,代码一共分为五段,其中四段是 OB 混淆,里层主要是控制流混淆。
为什么说是加强版的 OB 混淆呢,因为正常的 OB 混淆只有一个解密函数,一般抠出来解密函数以后使用 AST 很简单就能解开。但是此次的 OB 混淆,有 N 多个解密函数,每个解密函数最终都会调用原始的解密函数,相当于将解密函数做了多层跳板。
查看上图会发现,_0x478e
是正常的解密函数,但是实际字符串加密后的函数通过类似 _0x1f7593
这样的函数进行了一层封装,对解密函数的参数进行了计算,最终才调用真正的解密函数,本次对这种情况进行处理。
举个例子:
1 | const _0x30d0c2 = _0x2a6f46(this, function () { |
部分混淆代码如上,封装后的解密函数有五个参数,但是实际上只有两个是有效的,封装后的解密后数对参数进行计算后才调用真正的解密函数。
AST 处理-合并函数定义
为了简化后续处理,先将变量定义为函数表达式合并为函数定义。
如上图所示,这块相对简单,并且不是文章重点,所以就跳过了。
AST 处理思路
接下来讲一下处理的思路,拿一个解密函数举个例子:
1 | function _0x478e(_0x740ada, _0x4798ed) { |
以上面的函数为例,来讲一下思路:
- 首先要遍历所有的被封装后的解密函数的实际调用,例如这里的:
_0x337c3b(1089, 691, "]v58", 527, 187)
。 - 取出它所有的参数值,并且保存起来,其中有四个整形和一个字符串,可以在这里来判断是否是需要处理的函数,特征就是整形参数和字符串参数的数量,像上面的函数,参数值是:
1089, 691, "]v58", 527, 187
。 - 获取这个函数的函数定义,因为函数定义中有针对真正解密函数的封装逻辑,主要是对参数的计算和具体哪个参数才是有效的。如下所示,获取到函数的定义,可以看到第一个参数参与了计算,并且实际有效的参数是第三个,剩余的参数都是没有用到的。
1 | function _0x337c3b(_0x3ab717, _0x323fb8, _0x5c1ff5, _0x4b78ea, _0x3fd75c) { |
- 根据函数定义获取到真正的解密函数,拿到解密函数使用到的参数,并且获取计算逻辑中用到的数字,使用的参数是
_0x3ab717
,计算逻辑是+915
,有效的参数是:_0x3ab717
和_0x5c1ff5
。 - 注意上面的
+915
是经过计算后得到的,实际上是减去负的915
,这里稍微有些复杂,因为要判断是正值还是负值,并且要兼容不同情况,减去正值还是减去负值。 - 使用
_0x3ab717
和_0x5c1ff5
在被封装的函数参数中获取有效参数的索引,索引就是0
和3
,根据索引获取实际参数值,实际参数值为:1089, 691, "]v58", 527, 187
,索引0
和3
就是1089
和"]v58"
。 - 根据上面的逻辑,如果替换成真正的解密函数调用的话,应该是
_0x478e(1089- -915, "]v58")
,使用以上内容构造一个新的函数调用,参数值为刚刚获取到的两个参数,到此处理逻辑结束。
以上逻辑仅为我个人的思路,可能写的不太好,大家可以手动操作替换一下应该就能理解了。
实现代码
具体代码请关注文末的公众号获取。
总结
以上就是针对 OB 混淆的加强版的处理方案了,建议大家具体实操一下,可以加深对 AST 的理解,如果能处理这种程度的混淆,那么其他的 OB 混淆应该也难不倒你了。期望大家的作业哈哈哈,分享自己的思路,如果能有小伙伴写的比我的更简洁就更好了。
本文章首发于个人博客 LLLibra146’s blog
本文作者:LLLibra146
更多文章请关注公众号 (LLLibra146):
版权声明:本博客所有文章除特别声明外,均采用 © BY-NC-ND 许可协议。非商用转载请注明出处!严禁商业转载!