1. 程式人生 > >js程式碼不可逆混淆(自程式設計)

js程式碼不可逆混淆(自程式設計)

這個程式碼找不到出處了。侵刪

以前在哪個論壇上看見的,拷貝下來發現挺好使。

百度搜的市面上的線上混淆工具無法恢復這個混淆後的程式碼,個人整理成一個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>