AST 技巧:如何让混淆后的 JS 变量名“好看些”

大家好,今天分享一种可以在反混淆时让 JS 代码更具有可读性的方法,其实就是让 JS 的变量名更好看些。

恶心的变量名

在前两天遇到了一个 jsvmp 的混淆代码,发现变量名都是一个下划线,两个下划线这样的变量名,可读性完全没有,甚至混合着 pycharm 的代码警告导致看不到变量名是啥。

image-20250420202554404

上图就是 jsvmp 的代码,一大堆的 == 逻辑也不知道是在和谁比较。

既然学了 AST,那就要思考一下如何使用 AST 来解决问题。现在遇到了变量名的问题,那么应该如何使用 AST 来解决呢?

AST 重命名

这就涉及到了一个新的 AST 知识点了:作用域(scope)。

变量的作用域应该不会多讲了吧,在 AST 中可以通过作用域获取到这个变量被多少个变量修改了,被多少个地方使用到了,也可以进行批量重命名。

批量重命名就和使用 pycharm 的变量重命名功能是类似的,它会自动将所有引用的地方都重命名,而不影响其他作用域外部的代码,即使它们的名字是相同的,但是作用域外部的同名变量不会受到影响。

AST 重命名思路

因为这次主要分享重命名的方法,所以作用域在这里就不多说了,想要了解更多信息的小伙伴可以自行学习 babelscope 用法。

首先,为了重命名,要先知道将那些乱七八糟的名称变成什么,这里我选择变成几个随机的字符,总比下划线要好,对吧?大家可以选择适合自己的变量名和函数名。

先写一段生成随机变量名的代码:

1
2
3
4
const generateRandomString = () =>
Array.from({length: 3}, () =>
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'[Math.floor(Math.random() * 52)]
).join('');

这段代码会随机生成一个由三个随机字符组成的字符串。

但是想了一下,如果只有三个字符,那随机的时候万一重复了怎么办?变量名重复会导致正常运行的代码报错。

为了解决变量名重复的问题,新增以下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
let list = [];
const generateRandomString = () =>
Array.from({length: 3}, () =>
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'[Math.floor(Math.random() * 52)]
).join('');

function getRandomName() {
let name = generateRandomString();
while (true) {
if (list.indexOf(name) === -1) {
list.push(name);
break;
} else {
name = generateRandomString();
}
}
return name;
}

使用一个数组将生成的变量保存起来,如果之前生成过了, 那么重新生成一个。

这里最好使用 map 哈,我图省事就用 list 吧哈哈。

生成随机变量名后,就可以开始重命名了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
let renameVarDeclarator = {
VariableDeclarator: {
exit(path) {
let {node, scope} = path;
let binding = scope.getBinding(node.id.name);
if (!binding) {
return;
}
for (const referencePath of binding.referencePaths) {
scope.rename(referencePath.node.name, getRandomName());
}
}
}
}
traverse(ast, renameVarDeclarator);

先遍历所有的变量定义,通过 scope 获取变量的 binding,然后获取这个变量所有被引用的位置,将其重命名即可。

image-20250420205510289

查看效果,虽然还是看不懂,但是最起码变量名看上去好了很多哈哈,这样目的就达到了。

其他用法

上述重命名的方法还能用在哪里呢?除了这种变量名是下划线的,不知道大家有没有遇到过那种变量名和函数名全都是 Unicode 字符的,完全不知道啥是啥。

image-20250420205851639

我之前就遇到过,类似这种的,而且代码利用了 Unicode 的双向算法特性,加上某个字符会导致原来的 abc 变成 cba,非常恶心。像这种代码也可以使用刚才的方式将其还原。

image-20250420210031572

更详细的信息可以参考上图询问 AI。此方法还可以用在一些评论区,就是那种会溢出的评论,还是挺有意思的。

总结

后面大家在遇到类似的代码,可以尝试自己还原一下,无论是在浏览器动态分析还是静态分析,都是很有帮助的。

本文章首发于个人博客 LLLibra146’s blog

本文作者:LLLibra146

更多文章请关注公众号 (LLLibra146):LLLibra146

版权声明:本博客所有文章除特别声明外,均采用 © BY-NC-ND 许可协议。非商用转载请注明出处!严禁商业转载!

本文链接
https://blog.d77.xyz/archives/9b4b63d2.html