提出问题
在早期的一键解ob混淆脚本里,有大佬曾经问我:在还原object时,为啥不用scope来查找引用再替换?类似代码:
for (const referPath of referencePaths)
{
.......
referPath.replaceWith(......);
......
}
因为之前也尝试过用binding来替换,但总是会报错:
分析问题
为什么会引起错误,这个暂时未知,但是怎么分析报错问题,我之前一直提到过,直接打印最后一个遍历的path,看看是遍历的什么导致报错。添加如下打印代码:
for (const referPath of referencePaths)
{
console.log(referPath.parentPath.toString());
console.log(referPath.parentPath.parentPath.toString());
.......
referPath.replaceWith(......);
......
}
此时,在我遍历的样本中,打印信息如下:
红框处打印的是最后一次遍历的path,就是因为遍历了这里,才导致报错。
现在来自行分析下,在这之前遍历的是这个path:
_0x122f03["OnLhw"](_0x122f03["ueUti"], _0x122f03["nHsqG"])
替换成了 :
_0x122f03["ueUti"] !== _0x122f03["nHsqG"]
也就是处理 _0x122f03["OnLhw"] 这个之后,再遍历 _0x122f03["ueUti"] 时,就报错了,为啥?
我猜想的主要原因是 之前的节点是这样的:
_0x122f03["OnLhw"](_0x122f03["ueUti"], _0x122f03["nHsqG"])
这是一个包含关系,而在替换完 _0x122f03["OnLhw"] 后,节点的位置变了,但是使用scope的引用时,在这个新的节点位置进行替换操作,而这个节点并没有真正在AST中的生成,所以报了 Container is falsy 的错误(只是猜想,解释错误勿喷!)。
解决问题
在分析问题之后,解决问题就很简单了。既然这个包含关系,先遍历外面的,再遍历里面的,那反着来就可以了,即先遍历:
_0x122f03["OnLhw"](_0x122f03["ueUti"], _0x122f03["nHsqG"])
这个路径里的 _0x122f03["ueUti"] 和 _0x122f03["nHsqG"],再遍历 _0x122f03["OnLhw"],这样就不存在包含关系了。
referencePaths是一个Array类型,通过打印可以看出,引用的路径是按照代码顺序来的,"OnLhw" 在 "ueUti" 和 "nHsqG" 前面,也就先遍历了。
因此,只需将代码修改如下:
for (const referPath of referencePaths.reverse())
{
.......
referPath.replaceWith(......);
......
}
即可。经多个样本测试,不再报错,完美解决。Bingo!
欢迎关注本人微信公众号,谢谢!