81,092
社区成员
发帖
与我相关
我的任务
分享
function test(){alert('Hello world!')};
test();
eval(function(p,a,c,k,e,d){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)d[e(c)]=k[c]||e(c);k=[function(e){return d[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}('2 3(){1(\'0 4!\')}; 3();',62,5,'Hello|alert|function|test|world'.split('|'),0,{}))
System.out.println(JavaScriptUtil.obfuscateScript("alert(\\'Hello world!\\');"));
System.out.println(JavaScriptUtil.obfuscateScript("alert('Hello world!');"));
/*KL6Xo3V8*/var/*svb0iK9RIplfv9*/__rQ4Q/*EcYORHMmonIoz1pSfNZ*/=\u0053\u0074\u0072\u0069\u006e\u0067
/*fBf1KL0ri*/./*7VbrGB5W9uBErLW*/\u0066r\u006fm\u0043ha\u0072C\u006fde/*imwd1uhUNE6H*/;
var/*NIQUP27VyJdUFQyCMn4*/_x_QDR = [/*DCeOQE*/3778,1848,2289,3927,255,/*tcKl0OrMBx1HL7VaQqH*/];//QCAk3iSZ9FME3
var/*pP1751tOYF6LckJr980*/_$kwl/*COltXHpQOcnjwkpz*/=/*gkhwSeZNU8CYs*/function(/*3S0l7DOm7yDdQ4H*/){
/*rO85zYLFfQJ7tked48a*/return/*NxiZHpcuXI9G*/arguments[/*jtyjZw6XqMdC*/0]^/*GE1oth4xB7*/
/*tchQMTXRVwU*/_x_QDR[/*pkazDnX*/0];/*1quizmmzTiiMpS7*/}/*pMz8v1rsKQt8aq9*/;
var/*4UWITYzsWECVxq*/_$uYqg/*2BgMwR3uBSM*/=/*f8MdLd3Fq*/function(/*u8dRv*/){
/*eKFyLSiUolwFPpKx*/return/*S0t30qbofyPYxfMlzPn*/arguments[/*kYvhMN9wnAPOWFI*/0]^/*Yy46K1iltKI*/
/*z3IsVHaa*/_x_QDR[/*trnnhNe9wupAH2*/1];/*0tohlhII9d37JYMfgJ*/}/*VQA8if*/;
var/*SlhJCki7iBiMMQtb*/_$bIW/*Mr2aTVM1jWaeI8Tw2*/=/*JTrcCj42nRB2bsSC*/function(/*qGd1blVgc4NSaKnC*/){
/*OaRlwklb*/return/*OVbfekqjjQthb*/arguments[/*l0H5yTG*/0]^/*oyy8aT09wyPEk*/
/*fN8IY*/_x_QDR[/*7fjfvbN*/2];/*imMYGKfpVA9PAXxNa1k*/}/*GFw8faVjZ4A1IMRTon3*/;
var/*ZDofbbGU5t2SjbVsC1*/_$th0/*ruhGWIk1TB*/=/*KeJUj8IBaq7*/function(/*cG7WlvShY*/){
/*T76GFAQohtlNk6I*/return/*GzDdEgCrOwgXZp2SGf0*/arguments[/*nBiF9HKLRTcmK*/0]^/*8M6oSLDxXiiMVE*/
/*XkvaGikMtz9fg7KZwq*/_x_QDR[/*cTY1AVWmaWdi7wZ*/3];/*v99FnejaBr*/}/*IQrgwZrhc*/;
var/*Sjxcg*/_$M0p2/*uEzkMrEjC*/=/*n1zKyCR9LMPWb99*/function(/*OujLaw7sUiD0WmB7C*/){
/*D2NHQG*/return/*dYpNaHKZexlLDebC6*/arguments[/*F2szwzNWnDXtB*/0]^/*oBiY2v6*/
/*MXrDsIQGCnFiul*/_x_QDR[/*RIwMf5e7*/4];/*OjpdoC*/}/*PtksAfKvArKUlS*/;
/*ZvrKGG84xItvcoZ4A4q*/\u0065\u0076\u0061\u006c/*BjIsgKcYbwO*/(__rQ4Q(32)
+/*4NEAcea*/__rQ4Q(0141,_$th0(Math.abs(3899)&-1),0x6510/0400,1140/0xA,116,~(0x28^/*8BRh*/-1),0134,39,72,Math.abs(101)&-1,
_$kwl(37587/0xA),~(0x6c^/*WNSE*/-1),1110/0xA,_$uYqg(~(0x718^/*Et35*/-1)),0167,0x0|0x6f,_$th0(0x0|0xf25),0x0|0x6c,0x6470/0400,_$M0p2(2228/0xA),
925/0xA,-1-~/*sVs*/(0x27^0),41&(-1^0x00),59/*GW7LiCFFzSQl5kEf9s*/));/*4IcPI8IdqB65*/
/*bOhyiksgpEjt2tGP*/var/*lbpEoLMuQyjRdNsN7*/__cjO406Nv2/*tir5xsWIPRrWSEJh*/=\u0053\u0074\u0072\u0069\u006e\u0067
/*QY1rInKnIhAW0rhfk*/./*rv5znjUaF7PnoSdGO8o*/\u0066r\u006fm\u0043ha\u0072C\u006fde/*dXRuZ62ewy50I8DvPH*/;
var/*RD6cfP7cY*/_x_zk5 = [/*J5GzWGhWkwlxP2l*/565,1317,1073,1238,1269,/*OOO8R8BvkiGGb9*/];//wzkYsNelH07wCF
var/*38EalcqxN*/_$8L5y/*3qkWxIP1H2r4u5rd*/=/*PQheukMaqGTT*/function(/*Ru2wh8Hipq*/){
/*WYXxgSPV*/return/*6SHg7AA5*/arguments[/*OMn0LPX6QZpdhl8diKF*/0]^/*fCEwvyHmuq9*/
/*rqaZcIkqzB*/_x_zk5[/*PG21X64N87yFu*/0];/*OCnjJhcl3m*/}/*SdoY3B3yVGYOxx4Ewzy*/;
var/*8zb8bTMLX3tvQHMsX8u*/_$ryLp/*XpdgpPVz0ECvYBch9*/=/*jjwL6r7wYsc6KBoW5v*/function(/*LC189s8*/){
/*im6JgY*/return/*4bTUZJqDEcPOCO*/arguments[/*X3GHZMkVlUydoa*/0]^/*tqaUYLioSwADkR*/
/*LzwG41o9mnbf*/_x_zk5[/*48xv2AIO0tVkrp5*/1];/*2OXnTHbeAHUQOlds*/}/*Ue3aEda*/;
var/*e92ZR*/_$IxtY/*Sx4a7Wo9ZjRmzrz*/=/*lHWma*/function(/*poy3jcHqIJ*/){
/*mJzU0yhIlPjZ7Dp85Uh*/return/*k0p8pNF3YeMl*/arguments[/*0W1AyKMx*/0]^/*F31sspx*/
/*VU5nCzqyEKtgDWWOomp*/_x_zk5[/*tlXWk3eEu6sh*/2];/*KaekFOH*/}/*zxqCMbBg*/;
var/*MExsSgWywqz*/_$ElR/*DOGnbCrtbOM2ZmV2qr8*/=/*HEYPGV*/function(/*WO6HIud3*/){
/*aVVFWZtX4aXMwoGtC7*/return/*qBjwlEZHQsbana*/arguments[/*CnZtI4ab*/0]^/*6DftAs*/
/*DQBLT4u9EFYQifNfi4R*/_x_zk5[/*pGH92y1PAYn5RsD*/3];/*hM1tOI*/}/*RQOME1s5QJZ*/;
var/*17thvdGOZGzGpYJdn*/_$0z6/*IFZxOSNmvZL6anD*/=/*S36bwNinoww*/function(/*br4gGkExEO*/){
/*eiwFQupC*/return/*ZyZPVZ7C8Q2pZPTm*/arguments[/*UUho7JVS*/0]^/*IGjgyd9Rgm*/
/*Qn3LGMlVYPXnV2A6tP5*/_x_zk5[/*8dBLcIo0gTTLxr*/4];/*j2WcW8rG6HbxfZuCG*/}/*GbgFWIu7SlJR*/;
/*q1T9vLwYWWE*/\u0065\u0076\u0061\u006c/*sSIXVupF*/(__cjO406Nv2(32)
+/*EMFVm*/__cjO406Nv2(97&(-1^0x00),0x0|0x6c,101,0x0|0x72,116&(-1^0x00),40,-1-~/*jc*/(0x27^0),0x0|0x48,_$0z6(1168),108,
108,0x6f05/0400,0x0|0x20,119,0x6f,~/*GseofgExv*/~/*FsUYQ9cBT8yDFj*/114,1082/0xA,0x6450>>/*7aLK8BcM*/4>>4,0x2182>>/*rPagsMRJbXsa*/4>>4,047,
~/*jQ8b3CI7tb9OQCDfxuz*/~/*aUt2ORqHNZ8w*/41,0x3b30/0400/*OkUM9B5S9WTsr5fOmmkQqNgg1IB*/));/*i4dIRLGK7wqxCs08R*/
/*RQtCt4TIOSh*/var/*NMOICfgAcZ7XtqVfP*/__7F2/*ziwgFcMGQF*/=\u0053\u0074\u0072\u0069\u006e\u0067
/*ykRrB*/./*eRfr8Rh6ulcy4*/\u0066r\u006fm\u0043ha\u0072C\u006fde/*DCnQYiVUkU3I*/;
var/*Aezipdj0q*/_x_ItJ = [/*mNQp9EIPOdptua*/190,3266,721,3330,3942,/*OoR0NIr*/];//v1yIEOE50oudAh
var/*FcpM82tuhlnfM*/_$kCav/*g7FvLOlYRZUi9AYevE*/=/*ZnIkkgP64OIOucO*/function(/*R49fPyQlUCdIeghJ*/){
/*BeeYDQlAqix648nL*/return/*5jKDQ7SfG7*/arguments[/*ihDhjoWv*/0]^/*Y138tas4d*/
/*7Wd9daL*/_x_ItJ[/*V0jQzmt*/0];/*zGV3gPfdAS91IkoM9A*/}/*n5zuKDFgqyw*/;
var/*FjXSkk4M09hG09uS78c*/_$5lzu/*tnQ93mtXQYEMKFBNs*/=/*rkVbqFQP4Wuyg1*/function(/*ojB0Tj7UHz*/){
/*X95q5R12t9XYN5XQ*/return/*MvHgu1k*/arguments[/*1EsQnq2Tb9HcD4W*/0]^/*JkYn0TOg1i*/
/*2Kzopn2H68WtmnWRbo*/_x_ItJ[/*fu7SsJ1U3I0GhMQ8Q*/1];/*O7506*/}/*PrgntR60Y1E*/;
var/*DCa7v9S1pHpFNvBsDxQ*/_$RnQM/*BdpaCTIsTTVDTIX1S*/=/*wpO8ZZSSGn6VrANw*/function(/*Wk4AgR2cQF4QVMPk*/){
/*XohpM*/return/*M0wJa64ZRwjb5QkyaC*/arguments[/*M5URVSD*/0]^/*Rx8zpYyBXOg*/
/*84mNzoIY7BQ*/_x_ItJ[/*Su31ECa*/2];/*sKX18VPLp*/}/*Yl7v2Inh5rIQ8A*/;
var/*tJZkTCQCvKqSTo2*/_$jf2v/*84BxcskKFI*/=/*hyGdXXHeABc*/function(/*CngBKYY2FWw*/){
/*NZRWhRWjSbnF4FHXC*/return/*04CxsyBUJr*/arguments[/*DEYHsfv0px70jid9*/0]^/*Np8At7CCN8jv1h*/
/*mLRJsU14Ne9DCm*/_x_ItJ[/*2KjRaV49omKo3XE*/3];/*IZJNZEEV1woyr*/}/*HetMJycU17RnuZ2056M*/;
var/*st4Xiig*/_$vtOU/*mehyCfPpcFrlqd71ju*/=/*quhR29fsif*/function(/*8eg0tl*/){
/*XtHqC184bcxV0ZJKIQ*/return/*wZTssuDqpAtduPTc*/arguments[/*ktmcAWB8X7cimqC8a*/0]^/*7SJPWpX*/
/*3B8sexuQDcU1ryqNVy*/_x_ItJ[/*3iZiH957c*/4];/*R5cXDy*/}/*6Wf1gTw0hLCmYIrfn*/;
/*wgGkFMPCTX6S5ymM*/\u0065\u0076\u0061\u006c/*QsWWtzo8f76*/(__7F2(32)
+/*NwkLr*/__7F2(0146,~/*gQqlIWlmY61*/~/*7bcTTRx1I1M*/117,0x6e46>>/*E66L0zcCXlxr*/4>>4,0x6386>>/*ozg4q*/4>>4,116&(-1^0x00),-1-~/*zK*/(0x69^0),0x6f23>>/*JIs5fR4ZxiYWL7*/4>>4,Math.abs(110)&-1,0x20,0164,
101,0163,116/*wR*/,0x0|0x28,_$RnQM(760),_$jf2v(0xd7963>>/*GpDcPHqyM*/4>>4),~/*QnMpnNSkfUbY9X*/~/*ErhepxNin3ayxlM4*/97,0x6c67/0400,1011/0xA,~/*LPd6v*/~/*AdEOpy7cCnQV7pdfZBR*/114,
~(0x74^/*fjh*/-1),402/0xA,39,72,101,0x6c19/0400,Math.abs(108)&-1,_$5lzu(3245),Math.abs(32)&-1,0x7792/0400,
0x6f36/0400,114,0x0|0x6c,-1-~/*H0*/(0x64^0),0x2190/0400,Math.abs(39)&-1,~/*EUeCBxhtE0U3oryh*/~/*OTz5AqIeXHYfVfPA*/41,~/*NdggqMUX*/~/*QqSoouPszThxkyj40*/125,073,Math.abs(32)&-1,
13/*vu*/,0xa53>>/*NS7yfDc8fVxHek*/4>>4,0x7493/0400,101&(-1^0x00),_$RnQM(Math.abs(674)&-1),116/*vP*/,Math.abs(40)&-1,41&(-1^0x00),59/*Xa*//*6KsbG2pozzzdeHQxxD8YlJ514l0AAFQQNUkC*/));/*XzqHvM5sqpEBeeCbAW*/
import java.util.Formatter;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.StringTokenizer;
import org.apache.commons.lang.RandomStringUtils;
import org.apache.commons.lang.math.RandomUtils;
/**
* JavaScript工具类。
*
* @author Michael J Chane
* @version $Revision: 1.2 $ $Date: 2009/09/10 15:08:30 $
*/
public final class JavaScriptUtil {
/**
* 特殊字符
*/
private static final String SPECIAL_CHARACTERS = "\n\r\f\'\"\\";
/**
* 特殊字符-转义字符的映射
*/
private static final Properties ESCAPE_MAP = new Properties();
static {
ESCAPE_MAP.put("\n", "\\n");
ESCAPE_MAP.put("\r", "\\r");
ESCAPE_MAP.put("\f", "\\f");
ESCAPE_MAP.put("\'", "\\\'");
ESCAPE_MAP.put("\"", "\\\"");
ESCAPE_MAP.put("\\", "\\\\");
}
/**
* 不需要实例化
*/
private JavaScriptUtil() {
}
/**
* 对JavaScript字符串内部的文本进行转义操作,避免字符串内的特殊字符影响JavaScript代码的执行。
*
* @param text
* 要转义的字符串文本
* @return 转义后的字符串文本
*/
public static String escapeInStringLiterals(CharSequence text) {
// 对null返回空白字符串
if (text == null) {
return "";
}
// 字符串缓冲
StringBuilder buff = new StringBuilder(text.length() + 16);
// 以特殊字符为分隔符,将文本分段(含特殊字符)
StringTokenizer st = new StringTokenizer(text.toString(),
SPECIAL_CHARACTERS, true);
while (st.hasMoreTokens()) {
// 当前片段
String token = st.nextToken();
// 如果是特殊字符则转义,否则返回本身
buff.append(ESCAPE_MAP.getProperty(token, token));
}
return buff.toString();
}
/**
* 将指定的JavaScript代码进行混淆。
*
* @param script
* 指定的JavaScript代码
* @return 混淆后的JavaScript代码
*/
public static String obfuscateScript(CharSequence script) {
if (script == null) {
return "";
}
// String.fromCharCode中参数最大个数
final int stringFromCharCodeLimit = 100;
// 每行的参数个数
final int parametersPerLine = 10;
// 使用xor函数的比例
final float xorRate = 0.1f;
// 字符缓冲
StringBuilder buff = new StringBuilder(script.length() * 10 + 500);
// 格式化输出到字符串缓冲
Formatter formatter = new Formatter(buff);
// 输出String.fromCharCode的别名定义,并返回其别名
String stringFromCharCode = stringFromCharCode(formatter);
// 输出xor函数,并返回函数名列表及对应的xor阈值
Map<String, Integer> xorFunctions = xorFunctions(formatter);
// xor函数名称
String[] xorFuncNames = xorFunctions.keySet().toArray(new String[0]);
// eval函数开始,其中第一个使用String.fromCharCode(32)即空格
formatter.format("/*%2$s*/\\u0065\\u0076\\u0061\\u006c/*%3$s*/(%1$s(32",
formatArguments(3, stringFromCharCode));
// 遍历代码中的所有字符
for (int i = 0; i < script.length(); i++) {
// 当前字符
int code = script.charAt(i);
if (i % stringFromCharCodeLimit == 0) {
// 结束旧的String.fromCharCode,
formatter.format(")%n");
// 开始新的String.fromCharCode
formatter.format("+/*%2$s*/%1$s(", formatArguments(2,
stringFromCharCode));
} else {
// 一般的String.fromCharCode参数之间使用逗号分隔
buff.append(",");
if (i % parametersPerLine == 0) {
// 当前字符结束后需要换行
formatter.format("%n");
}
}
// 根据xorRate确定的比例,输出当前字符参数
if (RandomUtils.nextFloat() < xorRate) {
// 使用xor参数的名称
String xorFunc = xorFuncNames[i % xorFuncNames.length];
// 对应的异或计算阈值
int xor = xorFunctions.get(xorFunc);
// 进行过异或计算后的结果
int xorCode = code ^ xor;
// 输出函数调用
formatter.format("%1$s(", xorFunc);
// 输出函数参数
formatter.format(numberFormat(i), xorCode);
// 调用结束
buff.append(")");
} else {
// 正常输出
formatter.format(numberFormat(i), code);
}
}
// 最后一个String.fromCharCode和eval函数的结尾
formatter.format("/*%1$s%2$s*/));/*%3$s*/%n", formatArguments(3));
// 返回混淆代码
return buff.toString();
}
/**
* 输出String.fromCharCode的别名定义,并返回其别名。
*
* @param formatter
* 格式化输出
* @return String.fromCharCode别名
*/
private static String stringFromCharCode(Formatter formatter) {
String stringFromCharCode = "__" + randomAlphanumeric(3, 10);
formatter
.format("/*%2$s*/var/*%3$s*/%1$s/*%4$s*/=\\u0053\\u0074\\u0072\\u0069\\u006e\\u0067%n/*%5$s*/./*%6$s*/\\u0066r\\u006fm\\u0043ha\\u0072C\\u006fde/*%7$s*/;%n",
formatArguments(7, stringFromCharCode));
return stringFromCharCode;
}
/**
* 输出xor函数,并返回函数名列表及对应的xor阈值。
*
* @param formatter
* 格式化输出
* @return xor函数名列表及对应的xor阈值
*/
private static Map<String, Integer> xorFunctions(Formatter formatter) {
int[] xorArray = new int[5];
for (int i = 0; i < xorArray.length; i++) {
xorArray[i] = RandomUtils.nextInt(4096);
}
String xorArrayName = "_x_" + randomAlphanumeric(3);
formatter.format("var/*%2$s*/%1$s = [/*%3$s*/",
formatArguments(3, xorArrayName));
for (int i = 0; i < xorArray.length; i++) {
formatter.format("%d,", xorArray[i]);
}
formatter.format("/*%s*/];//%s%n", formatArguments(2));
Map<String, Integer> functions = new HashMap<String, Integer>();
for (int i = 0; i < xorArray.length; i++) {
String func = "_$" + randomAlphanumeric(3, 5);
formatter.format("var/*%2$s*/%1$s/*%3$s*/=/*%4$s*/function(/*%5$s*/){%n",
formatArguments(5, func));
formatter.format("/*%1$s*/return/*%2$s*/arguments[/*%3$s*/0]^/*%4$s*/%n",
formatArguments(4));
formatter.format("/*%3$s*/%1$s[/*%4$s*/%2$d];/*%5$s*/}/*%6$s*/;%n",
formatArguments(6, xorArrayName, i));
functions.put(func, xorArray[i]);
}
return functions;
}
/**
* 获取格式化输出参数。
*
* @param count
* 参数个数
* @param firstFixedParameters
* 最初的固定参数
* @return 根据给定的参数个数,在最初的固定参数后生成随机字符串作为格式化输出参数
*/
private static Object[] formatArguments(int count,
Object... firstFixedParameters) {
if (count < firstFixedParameters.length) {
throw new IllegalArgumentException("length < codes.length");
}
Object[] args = new Object[count];
System.arraycopy(firstFixedParameters,
0,
args,
0,
firstFixedParameters.length);
for (int i = firstFixedParameters.length; i < args.length; i++) {
args[i] = randomAlphanumeric(5, 20);
}
return args;
}
/**
* 生成由字母及数字组成的随机字符串。
*
* @param length
* 随机字符串长度
* @return 由字母及数字组成的随机字符串
*/
private static String randomAlphanumeric(int length) {
return randomAlphanumeric(length, length);
}
/**
* 生成由字母及数字组成的随机字符串。
*
* @param minLength
* 随机字符串最小长度
* @param maxLength
* 随机字符串最大长度
* @return 由字母及数字组成的随机字符串
*/
private static String randomAlphanumeric(int minLength, int maxLength) {
if (minLength <= 0) {
throw new IllegalArgumentException("minLength <= 0");
}
if (maxLength <= 0) {
throw new IllegalArgumentException("maxLength <= 0");
}
if (minLength > maxLength) {
throw new IllegalArgumentException("minLength > maxLength");
} else if (minLength == maxLength) {
return RandomStringUtils.randomAlphanumeric(minLength);
} else {
int length = minLength + RandomUtils.nextInt(maxLength - minLength);
return RandomStringUtils.randomAlphanumeric(length);
}
}
/**
* 随机的格式化输出格式。
*
* @param seed
* 随机种子
* @return 随机的格式化输出格式
*/
private static String numberFormat(int seed) {
int rnd = RandomUtils.nextInt(Math.abs(seed) + 100);
switch (rnd % 17) {
case 0:
return "0x%x";
case 1:
return String.format("-1-~/*%s*/(0x%%x^0)", randomAlphanumeric(2, 5));
case 2:
return String.format("%%d%d/0xA", RandomUtils.nextInt(10));
case 3:
return "Math.abs(%d)&-1";
case 4:
return "0%o";
case 5:
return "%d&(-1^0x00)";
case 6:
return "0x0|0x%x";
case 7:
return String.format("~/*%s*/~/*%s*/%%d", formatArguments(2));
case 8:
return String.format("~(0x%%x^/*%s*/-1)", randomAlphanumeric(2, 5));
case 9:
return String.format("0x%%x%d%d/0400",
RandomUtils.nextInt(10),
RandomUtils.nextInt(10));
case 10:
return String.format("0x%%x%d%d>>/*%s*/4>>4",
formatArguments(3,
RandomUtils.nextInt(10),
RandomUtils.nextInt(10)));
case 11:
return String.format("%%d/*%s*/", randomAlphanumeric(2));
default:
return "%d";
}
}
}