起因:

在研究爬虫的时候发现很多网站都出现了同一种方式的js混淆,并且名字都是pde.js,怀疑是使用了同一款混淆工具,所以研究一下。

这款工具叫JS Packer,并不是专门的混淆工具,而是一款js压缩工具,其官网地址为: http://dean.edwards.name/packer/

支持两种压缩方式,一种是Shrink variables比较常规的压缩方式,就是去掉一些空白符注释之类的,另一种是Base62 encode,是一种比较适合用来压缩内容单词重复率高的压缩方式。

压缩示例

所有讨论基于Base62 encode压缩方式,输入:

alter("hello, world");

输出:

eval(function(p,a,c,k,e,r){e=String;if(!''.replace(/^/,String)){while(c--)r[c]=k[c]||c;k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('0("1, 2");',3,3,'alter|hello|world'.split('|'),0,{}))

格式化后:

eval(function (p, a, c, k, e, r) {
e = String;
if (!''.replace(/^/, String)) {
while (c--) r[c] = k[c] || c;
k = [function (e) {
return r[e]
}];
e = function () {
return '\\w+'
};
c = 1
}
;
while (c--) if (k[c]) p = p.replace(new RegExp('\\b' + e(c) + '\\b', 'g'), k[c]);
return p
}('0("1, 2");', 3, 3, 'alter|hello|world'.split('|'), 0, {}))

上面的代码看着很唬人,其实原理很简单,我们耐心分析下。

压缩原理:

简单来说就是将相同的单词进行压缩,具体为将所有单词抽取出来作为一个词典,然后将源代码中表示单词的地方改为引用词典的下标,这样的话当重复的单词很多的时候压缩效果就比较好,但是当重复的单词比较少的时候这种方法有点得不偿失。

带入具体数据来具体分析,比如下面的代码:

console.log("aaaaa");
console.log("aaaaa");
console.log("bbbb");

压缩之后格式化:

eval(function(p, a, c, k, e, r) {
e = String;
if (!''.replace(/^/, String)) {
while (c--) r[c] = k[c] || c;
k = [function(e) {
return r[e]
}];
e = function() {
return '\\w+'
};
c = 1
};
while (c--) if (k[c]) p = p.replace(new RegExp('\\b' + e(c) + '\\b', 'g'), k[c]);
return p
} ('0.1("2");0.1("2");0.1("3");', 4, 4, 'console|log|aaaaa|bbbb'.split('|'), 0, {}))

可以看到规律已经很明显了,第一个 参数 '0.1("2");0.1("2");0.1("3");'中的数字对应着 'console|log|aaaaa|bbbb'.split('|') 中的下标,解压的时候只需要再将数字下标还原为单词即可。

下面是对解压缩算法的一个简单解读:

// p 将原始内容中所有单词替换为字典下标后的压缩内容
// a 词典大小,暂时用不到
// c 词典大小,在解压时用来关联压缩内容和词典
// k 词典
// e 在解压时,当replace第二个参数支持function时,为\\w+,否则为与下标对应的字符串
// r 当加速解压时用来保存词典
eval(function(p, a, c, k, e, r) {
e = String; // 检测当前的浏览器是否支持replace(regex, function),如果支持的话就能够加快解压速度
// 如果不支持的话可以把这一块直接忽略掉
if (!''.replace(/^/, String)) { // 把被压缩的单词拷贝一份,因为k还有别的用处
while (c--) r[c] = k[c] || c; // k[0]后面用来对每个匹配到的下标寻找替换字符串
k = [function(e) {
return r[e]
}]; // 用来分割原始内容
e = function() {
return '\\w+'
}; // 加速解压的时候,相当于把while变成了if
c = 1
}; // 使用词典将压缩后的下标代码扩展,如果没有上面的加速的话,c等于词典单词数,要一个一个替换了
// 如果支持replace(string, function)的话,会将匹配到的每一个数字都传递给k[c]来得到其应该被替换为的字符串
while (c--) if (k[c]) p = p.replace(new RegExp('\\b' + e(c) + '\\b', 'g'), k[c]); // 完成解压
return p
} ('0.1("2");0.1("2");0.1("3");', 4, 4, 'console|log|aaaaa|bbbb'.split('|'), 0, {}))

解压缩小工具

我把这种 eval(blablabla…) 形式的统称为eval压缩,并针对此写了个一个简单的解压小工具。

思路:

1. 既然这种肯定是要在网页上执行的,那么只需要模拟执行就可以了。

2. 可能不只有一层eval,所以应该能够方便的多次连续eval。

html代码如下:

<html>
<head>
<meta charset="UTF-8">
<title>JavaScript eval</title>
</head>
<body> <textarea id="eval_code" cols="100" rows="30" placeholder="粘贴eval代码"></textarea>
<button onclick="executeEval()">EVAL</button> <script type="text/javascript">
function executeEval(){
let evalCodeElt = document.getElementById("eval_code");
let evalCode = evalCodeElt.value;
// 如果不把开头的eval去掉的话直接执行会被执行两遍
evalCode = evalCode.replace(/^eval/, "");
try{
evalCodeElt.value = eval(evalCode);
}catch (e) {
alert("执行报错了:" + e);
}
}
</script>
</body>
</html>

效果如下:

参考资料:

1. /packer/

2. JS混淆加密压缩 - 站长工具

3. JavaScript在线压缩打包/解压缩工具 - JavaScript Packer - 志文工作室

4. What does “if (!''.replace(/^/, String))” do?

5. JavaScript replace() 方法

jspacker压缩及解压缩研究(js eval)的更多相关文章

  1. Java 基础【12】 压缩与解压缩

    Java.util.zip 提供用于读写标准 ZIP 和 GZIP 文件格式的类. 还包括使用 DEFLATE 压缩算法(用于 ZIP 和 GZIP 文件格式)对数据进行压缩和解压缩的类. 依赖 Jd ...

  2. 菜鸟学Linux命令:tar命令 压缩与解压缩

    tar命令可以为linux的文件和目录创建档案.利用tar,可以为某一特定文件创建档案(备份文件),也可以在档案中改变文件,或者向档案中加入新的文件. tar最初被用来在磁带上创建档案,现在,用户可以 ...

  3. Linux系统之压缩、解压缩,vi编辑器,系统初始化服务和系统监控

    一.正文处理,压缩与解压缩 1.内容重定向>与>> >:覆盖,将>号左边的结果覆盖到>号右边的文件中,如果文件不存在,则先创建一个新的空文件并覆盖 >> ...

  4. gzip [选项] 压缩(解压缩)

    减少文件大小有两个明显的好处,一是可以减少存储空间,二是通过网络传输文件时,可以减少传输的时间.gzip是在Linux系统中经常使用的一个对文件进行压缩和解压缩的命令,既方便又好用. 语法:gzip ...

  5. 使用ICSharpCode.SharpZipLib.Zip实现压缩与解压缩

    使用开源类库ICSharpCode.SharpZipLib.Zip可以实现压缩与解压缩功能,源代码和DLL可以从http://www.icsharpcode.net/OpenSource/SharpZ ...

  6. PclZip:强大的PHP压缩与解压缩zip类

    PclZip简介PclZip是一个很强大的压缩与解压缩zip文件的PHP类,PclZip library能够压缩与解压缩Zip格式的压缩档(WinZip.PKZIP):且能对此类类档案进行处理,包括产 ...

  7. zip格式压缩、解压缩(C#)

    压缩方法 #region 压缩 /// <summary> /// 压缩 /// </summary> /// <param name="bytes" ...

  8. Tar打包、压缩与解压缩到指定目录的方法

    tar在linux上是常用的打包.压缩.加压缩工具,他的参数很多,折里仅仅列举常用的压缩与解压缩参数 参数: -c :create 建立压缩档案的参数: -x : 解压缩压缩档案的参数: -z : 是 ...

  9. Deflater与Inflater的压缩与解压缩

    原文:Deflater与Inflater的压缩与解压缩 package util; import java.util.Arrays; import java.util.zip.Deflater; im ...

随机推荐

  1. SpringMVC(七):@RequestMapping下使用POJO对象绑定请求参数值

    Spring MVC会按照请求参数名和POJO属性名进行自动匹配,自动为该对象填充属性值,支持级联属性. 如:address.city.dept.address.province等. 步骤一:定义Ac ...

  2. Hibernate(十五):QBC检索、本地SQL检索和HQL删除

    QBC检索 QBC查询就是通过使用Hibernate提供的Query By Criteria API来查询对象,这种API封装了SQL语句的动态拼装,对查询提供了更加面向对象的功能接口. 1)通过Cr ...

  3. Struts(十四):通用标签-form表单

    form标签是struts2标签中一个重要标签: 可以生成html标签,使用起来和html的form标签差不多: Strut2的form标签会生成一个table,进行自动布局: 可以对表单提交的值进行 ...

  4. Extensions in UWP Community Toolkit - ListViewExtensions

    概述 UWP Community Toolkit Extensions 中有一个为 ListView 提供的扩展 - ListViewExtensions,本篇我们结合代码详细讲解 ListView  ...

  5. 小工具:批量导入导出主机上的docker镜像

    工作需要,将主机上的部分镜像导出为tar文件,放便在其他主机上使用 用python实现了一个批量打包脚本: import re import os import subprocess if __nam ...

  6. position的static、relative、absolute、fixed、inherit

    网上有很多关于position的讲解,也有很多他们属性之间的比较,但是比较全面的讲解还是比较少,每次看完过段时间就忘了,所以今天参考了很多网上现有的资源,自己整理一下,写下这篇文章. position ...

  7. python学习记录2

    一.两个模块(sys和os) #!/usr/bin/env python # _*_ coding: UTF-8 _*_ # Author:taoke import sys print(sys.pat ...

  8. 计蒜客NOIP模拟赛(2) D1T1邻家男孩

    凡是一个具有领导力的孩子.现实生活中他特别喜欢玩一个叫做 UNO 的纸牌游戏,他也总是带着其他小朋友一起玩,然后战胜他们.慢慢地,他厌倦了胜利,于是准备发明一种新的双人纸牌游戏. 初始时,每个人手中都 ...

  9. 洛谷P2319 [HNOI2006]超级英雄

    一开始是用二分图匹配(网络流)+二分做的,后来发现直接用匈牙利更简单 #include<cstdio> #include<cstdlib> #include<algori ...

  10. 【NOIP 2017】宝藏

    Description 参与考古挖掘的小明得到了一份藏宝图,藏宝图上标出了 n 个深埋在地下的宝藏屋, 也给出了这 n 个宝藏屋之间可供开发的 m 条道路和它们的长度. 小明决心亲自前往挖掘所有宝藏屋 ...