js程式碼不可逆混淆(自程式設計)
阿新 • • 發佈:2018-12-10
這個程式碼找不到出處了。侵刪
以前在哪個論壇上看見的,拷貝下來發現挺好使。
百度搜的市面上的線上混淆工具無法恢復這個混淆後的程式碼,個人整理成一個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>