这个代码找不到出处了。侵删
以前在哪个论坛上看见的,拷贝下来发现挺好使。
百度搜的市面上的在线混淆工具无法恢复这个混淆后的代码,个人整理成一个jsp页面直接用。
缺陷是:个人学习理解一下混淆规则,也是可以直接读出混淆后代码的,只是略费劲(需要有十分强大的耐心)
贴完整jsp代码
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=GBK"/>
<title>JS Compresser</title>
<style>
* { font-size:12px; }
body { overflow:auto; background-color:buttonface; border-style:none; }
textarea { width:100%; height:300px; overflow:auto; }
</style>
<script>
window.onload = function () {
$("txtSource").focus();
};
function $(obj) {
return document.getElementById(obj);
};
function doCompress() {
$("txtResult").value = compress_rename_local_variable($("txtSource").value);
$("info").innerHTML = $("txtSource").value.length + ":" + $("txtResult").value.length;
};
function compress_rename_local_variable(source) {
var escape_mode = false,
str_mode = false,
function_mode = false,
var_mode = false,
property_mode = false;
var currentScope = new scope(),
strTable = new str_table(),
str_buffer = [];
remove_comment(source).replace(/\w+|\W/g, function (token) {
if (str_mode) {
if (escape_mode) {
escape_mode = false;
return str_buffer.push(token);
};
if (str_mode == token) {
currentScope.cache(strTable.map(token+str_buffer.join("")+token), true);
str_mode = false;
};
if (token == "\\") escape_mode = token;
return str_buffer.push(token);
};
if (escape_mode) {
escape_mode = false;
return currentScope.cache(token, true);
};
switch (token) {
case "function":
function_mode = true;
return currentScope.cache(token);
break;
case "var":
var_mode = 1;
return currentScope.cache(token);
break;
case ";":
var_mode = false;
return currentScope.cache(token);
break;
case ",":
if (var_mode == 2) var_mode = 1;
return currentScope.cache(token);
break;
case "(":
if (function_mode) currentScope = currentScope.newScope();
return currentScope.cache(token);
break;
case ")":
if (function_mode) function_mode = false;
return currentScope.cache(token);
break;
case ".":
property_mode = true;
return currentScope.cache(token);
break;
case "\"":
case "\'":
str_mode = token;
str_buffer = [];
return;
break;
case "\\":
return currentScope.cache(escape_mode = token);
break;
default:
if (function_mode) currentScope.regist(token);
else if (var_mode == 1 && /^[\w$]+$/.test(token)) {
currentScope.regist(token);
var_mode = 2;
} else if (property_mode) {
property_mode = false;
if (/^[a-zA-Z_$][\w$]*$/.test(token)) {
currentScope.decache();
token = "[" + strTable.map('"'+token+'"') + "]";
}
};
return currentScope.cache(token);
}
});
while (!currentScope.isClosed()) currentScope.close();
return strTable.data() + currentScope.data();
function scope(parent) {
var registTable = {},
availMapIndex = parent ? parent.availMapIndex() : -1,
closed = false,
hierarchy = 0;
var data = [];
this.availMapIndex = function () {
return availMapIndex;
};
this.cache = function (token, __h) {
data.push(token);
if (!parent || __h) return;
if (token == "{") hierarchy++;
else if (token == "}" && --hierarchy == 0) return this.close();
};
this.close = this.flush = function () {
if (closed) throw new Error("Scope already closed.");
closed = true;
for (var t = 0; t < data.length; t++) if (data[t - 1] != ".") data[t] = this.map(data[t]);
if (parent) {
currentScope = parent;
parent.cache(data.join(""));
}
};
this.data = function () {
return data.join("");
};
this.decache = function () {
return data.pop();
};
this.isClosed = function () {
return parent ? closed : true;
};
this.isRoot = function () {
return !parent;
};
this.map = function (token) {
return registTable["%" + token] || (parent ? parent.map(token) : token);
};
this.newScope = function () {
return new scope(this);
};
this.parent = function () {
return parent;
};
this.regist = function (token) {
if (!parent || !/^[\w$]+$/.test(token) || Function("try{"+token+";return true}catch(e){return false}")()) return;
registTable["%" + token] = "__" + (++availMapIndex).toString(36);
};
};
function str_table() {
var keys = [],
table = {};
this.map = function (str) {
var key = "%" + str;
if (table[key] != undefined) return "__[" + table[key] + "]";
table[key] = keys.length;
keys.push(str);
return "__[" + table[key] + "]";
};
this.data = function () {
return ("__=[" + keys.join(",") + "];");
};
};
function remove_comment(source) {
var parser_pos = -1,
input_length = source.length,
text_arr = [],
current_char, str_mode = false,
escape_mode = false;
while (++parser_pos < input_length) {
text_arr.push(current_char = source.charAt(parser_pos));
if (str_mode) {
if (escape_mode) {
escape_mode = false;
} else {
if (str_mode == current_char) str_mode = false;
if (current_char == "\\") escape_mode = true;
};
continue;
} else if (escape_mode) {
escape_mode = false;
continue;
} else if (current_char == "\"" || current_char == "\'") {
str_mode = current_char;
continue;
} else {
current_char = source.substring(parser_pos, parser_pos + 2);
if (current_char == "\/\/") {
text_arr.pop();
parser_pos = source.indexOf("\n", parser_pos + 2) - 1;
if (parser_pos == -2) parser_pos = input_length;
} else if (current_char == "\/*") {
text_arr.pop();
parser_pos = source.indexOf("*\/", parser_pos + 2);
if (parser_pos == -1) parser_pos = input_length;
}
}
};
return text_arr.join("").replace(/^\s*|\s*$/g, "").replace(/\s*[\r\n]\s*/g, "\r").replace(/;\r/g, ";").replace(/([a-zA-Z0-9_$\)\}])\r(?=[a-zA-Z0-9_$])/g, "$1;").replace(/\r/g, "");
}
}
</script>
</head>
<body>
<textarea id="txtSource" onkeydown="if(event.keyCode==13 && event.ctrlKey)doCompress();"></textarea>
<textarea id="txtResult"></textarea>
<br/>
<input type="button" value="混淆" onclick="doCompress();" />
<span id="info"></span>
</body>
</html>