代码混淆JSFuck-一款开源的Js混淆插件JsFuck
JSFuck 可以让你只用 6 个字符 []()!+ 来编写 JavaScript 程序,其主要的思想就是只使用8种特定的符号来编写代码。而jsfuck也是沿用了这个思想,它仅仅使用6种符号来编写代码。它们分别是(、)、+、[、]、!。
JSFuck官网:点我跳转
效果展示
如下js是混淆后的代码 内容为:alert(1)
[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]][([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]((!![]+[])[+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+([][[]]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+!+[]]+(+[![]]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+!+[]]]+(!![]+[])[!+[]+!+[]+!+[]]+(+(!+[]+!+[]+!+[]+[+!+[]]))[(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([]+[])[([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]][([][[]]+[])[+!+[]]+(![]+[])[+!+[]]+((+[])[([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]+[])[+!+[]+[+!+[]]]+(!![]+[])[!+[]+!+[]+!+[]]]](!+[]+!+[]+!+[]+[!+[]+!+[]])+(![]+[])[+!+[]]+(![]+[])[!+[]+!+[]])()((![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[+!+[]+[!+[]+!+[]+!+[]]]+[+!+[]]+([+[]]+![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[!+[]+!+[]+[+[]]])
插件源码
/*
本模板由 壹影(JsHD调试器开发者) 网络查找并修改
模板作者QQ:203455278
介绍:JSFuck
JSFuck可以理解为是一种Js的代码混淆,基于JS是特性对常用的代码写法进行处理
*/
/*! JSFuck 0.5.0 - http://jsfuck.com */
(function(self){
const MIN = 32, MAX = 126;
const SIMPLE = {
'false': '![]',
'true': '!![]',
'undefined': '[][[]]',
'NaN': '+[![]]',
'Infinity': '+(+!+[]+(!+[]+[])[!+[]+!+[]+!+[]]+[+!+[]]+[+[]]+[+[]]+[+[]])' // +"1e1000"
};
const CONSTRUCTORS = {
'Array': '[]',
'Number': '(+[])',
'String': '([]+[])',
'Boolean': '(![])',
'Function': '[]["flat"]',
'RegExp': 'Function("return/"+false+"/")()',
'Object': '[]["entries"]()'
};
const MAPPING = {
'a': '(false+"")[1]',
'b': '([]["entries"]()+"")[2]',
'c': '([]["flat"]+"")[3]',
'd': '(undefined+"")[2]',
'e': '(true+"")[3]',
'f': '(false+"")[0]',
'g': '(false+[0]+String)[20]',
'h': '(+(101))["to"+String["name"]](21)[1]',
'i': '([false]+undefined)[10]',
'j': '([]["entries"]()+"")[3]',
'k': '(+(20))["to"+String["name"]](21)',
'l': '(false+"")[2]',
'm': '(Number+"")[11]',
'n': '(undefined+"")[1]',
'o': '(true+[]["flat"])[10]',
'p': '(+(211))["to"+String["name"]](31)[1]',
'q': '("")["fontcolor"]([0]+false+")[20]',
'r': '(true+"")[1]',
's': '(false+"")[3]',
't': '(true+"")[0]',
'u': '(undefined+"")[0]',
'v': '(+(31))["to"+String["name"]](32)',
'w': '(+(32))["to"+String["name"]](33)',
'x': '(+(101))["to"+String["name"]](34)[1]',
'y': '(NaN+[Infinity])[10]',
'z': '(+(35))["to"+String["name"]](36)',
'A': '(NaN+[]["entries"]())[11]',
'B': '(+[]+Boolean)[10]',
'C': 'Function("return escape")()(("")["italics"]())[2]',
'D': 'Function("return escape")()([]["flat"])["slice"]("-1")',
'E': '(RegExp+"")[12]',
'F': '(+[]+Function)[10]',
'G': '(false+Function("return Date")()())[30]',
'H': null,
'I': '(Infinity+"")[0]',
'J': null,
'K': null,
'L': null,
'M': '(true+Function("return Date")()())[30]',
'N': '(NaN+"")[0]',
'O': '(+[]+Object)[10]',
'P': null,
'Q': null,
'R': '(+[]+RegExp)[10]',
'S': '(+[]+String)[10]',
'T': '(NaN+Function("return Date")()())[30]',
'U': '(NaN+Object()["to"+String["name"]]["call"]())[11]',
'V': null,
'W': null,
'X': null,
'Y': null,
'Z': null,
' ': '(NaN+[]["flat"])[11]',
'!': null,
'"': '("")["fontcolor"]()[12]',
'#': null,
'$': null,
'%': 'Function("return escape")()([]["flat"])[21]',
'&': '("")["fontcolor"](")[13]',
'\'': null,
'(': '([]["flat"]+"")[13]',
')': '([0]+false+[]["flat"])[20]',
'*': null,
'+': '(+(+!+[]+(!+[]+[])[!+[]+!+[]+!+[]]+[+!+[]]+[+[]]+[+[]])+[])[2]',
',': '[[]]["concat"]([[]])+""',
'-': '(+(.+[0000001])+"")[2]',
'.': '(+(+!+[]+[+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+[!+[]+!+[]]+[+[]])+[])[+!+[]]',
'/': '(false+[0])["italics"]()[10]',
':': '(RegExp()+"")[3]',
';': '("")["fontcolor"](NaN+")[21]',
'<': '("")["italics"]()[0]',
'=': '("")["fontcolor"]()[11]',
'>': '("")["italics"]()[2]',
'?': '(RegExp()+"")[2]',
'@': null,
'[': '([]["entries"]()+"")[0]',
'\\': '(RegExp("/")+"")[1]',
']': '([]["entries"]()+"")[22]',
'^': null,
'_': null,
'`': null,
'{': '(true+[]["flat"])[20]',
'|': null,
'}': '([]["flat"]+"")["slice"]("-1")',
'~': null
};
const GLOBAL = 'Function("return this")()';
function fillMissingDigits(){
var output, number, i;
for (number = 0; number < 10; number++){
output = "+[]";
if (number > 0){ output = "+!" + output; }
for (i = 1; i < number; i++){ output = "+!+[]" + output; }
if (number > 1){ output = output.substr(1); }
MAPPING[number] = "[" + output + "]";
}
}
function replaceMap(){
var character = "", value, i, key;
function replace(pattern, replacement){
value = value.replace(
new RegExp(pattern, "gi"),
replacement
);
}
function digitReplacer(_,x) { return MAPPING[x]; }
function numberReplacer(_,y) {
var values = y.split("");
var head = +(values.shift());
var output = "+[]";
if (head > 0){ output = "+!" + output; }
for (i = 1; i < head; i++){ output = "+!+[]" + output; }
if (head > 1){ output = output.substr(1); }
return [output].concat(values).join("+").replace(/(\d)/g, digitReplacer);
}
for (i = MIN; i <= MAX; i++){
character = String.fromCharCode(i);
value = MAPPING[character];
if(!value) {continue;}
for (key in CONSTRUCTORS){
replace("\\b" + key, CONSTRUCTORS[key] + '["constructor"]');
}
for (key in SIMPLE){
replace(key, SIMPLE[key]);
}
replace('(\\d\\d+)', numberReplacer);
replace('\\((\\d)\\)', digitReplacer);
replace('\\[(\\d)\\]', digitReplacer);
replace("GLOBAL", GLOBAL);
replace('\\+""', "+[]");
replace('""', "[]+[]");
MAPPING[character] = value;
}
}
function replaceStrings(){
var regEx = /[^\[\]\(\)\!\+]{1}/g,
all, value, missing,
count = MAX - MIN;
function findMissing(){
var all, value, done = false;
missing = {};
for (all in MAPPING){
value = MAPPING[all];
if (value && value.match(regEx)){
missing[all] = value;
done = true;
}
}
return done;
}
function mappingReplacer(a, b) {
return b.split("").join("+");
}
function valueReplacer(c) {
return missing[c] ? c : MAPPING[c];
}
for (all in MAPPING){
if (MAPPING[all]){
MAPPING[all] = MAPPING[all].replace(/\"([^\"]+)\"/gi, mappingReplacer);
}
}
while (findMissing()){
for (all in missing){
value = MAPPING[all];
value = value.replace(regEx, valueReplacer);
MAPPING[all] = value;
missing[all] = value;
}
if (count-- === 0){
console.error("Could not compile the following chars:", missing);
}
}
}
function escapeSequence(c) {
var cc = c.charCodeAt(0);
if (cc < 256) {
return '\\' + cc.toString(8);
} else {
var cc16 = cc.toString(16);
return '\\u' + ('0000' + cc16).substring(cc16.length);
}
}
function escapeSequenceForReplace(c) {
return escapeSequence(c).replace('\\', 't');
}
function encode(input, wrapWithEval, runInParentScope){
var output = [];
if (!input){
return "";
}
var unmappped = ''
for(var k in MAPPING) {
if (MAPPING[k]){
unmappped += k;
}
}
unmappped = unmappped.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
unmappped = new RegExp('[^' + unmappped + ']','g');
var unmappedCharactersCount = (input.match(unmappped) || []).length;
if (unmappedCharactersCount > 1) {
//如果没有这种优化,一个未映射的特征符就会编码长度
//约3600个字符。每增加一个未映射的字符
//2000增加到总长度。例如“~”的长度为3605,
//“~~'是5600,而“~~`是7595。
//带有replace的加载程序的编码长度约为5300个字符
//并且每增加一个字符就将总长度加100。
//在同一个例子中,“~~”的长度变为5371和“~~~'-5463。
//因此,当我们有多个未映射的字符时,我们希望对整个输入进行编码
//除了选择字符(编码长度小于约70)
//转换为转义序列。
//注意:“t”应该被转义!
input = input.replace(/[^0123456789.adefilnrsuN]/g, escapeSequenceForReplace);
} else if (unmappedCharactersCount > 0) {
//因为我们将把输入包装成一个字符串,所以我们需要转义Backslash
//和双引号字符(我们不需要担心其他字符
//因为它们没有被明确地映射)。
//“\”的JSFuck编码表示是2121个符号,
//所以esacped的“\”是4243个符号,escaped的“”是2261个符号
//但是该字符的转义序列是
//2168和2155个符号,因此更实用
//将它们重写为转义序列。
input = input.replace(/["\\]/g, escapeSequence);
//将所有未映射的字符转换为转义序列
input = input.replace(unmappped, escapeSequence);
}
var r = "";
for (var i in SIMPLE) {
r += i + "|";
}
r+= ".";
input.replace(new RegExp(r, 'g'), function(c) {
var replacement = SIMPLE[c];
if (replacement) {
output.push("(" + replacement + "+[])");
} else {
replacement = MAPPING[c];
if (replacement){
output.push(replacement);
} else {
throw new Error('Found unmapped character: ' + c);
}
}
});
output = output.join("+");
if (/^\d$/.test(input)){
output += "+[]";
}
if (unmappedCharactersCount > 1) {
// replace `t` with `\\`
output = "(" + output + ")[" + encode("split") + "](" + encode ("t") + ")[" + encode("join") +"](" + encode("\\") + ")";
}
if (unmappedCharactersCount > 0) {
output = "[][" + encode("flat") + "]"+
"[" + encode("constructor") + "]" +
"(" + encode("return\"") + "+" + output + "+" + encode("\"") + ")()";
}
if (wrapWithEval){
if (runInParentScope){
output = "[][" + encode("flat") + "]" +
"[" + encode("constructor") + "]" +
"(" + encode("return eval") + ")()" +
"(" + output + ")";
} else {
output = "[][" + encode("flat") + "]" +
"[" + encode("constructor") + "]" +
"(" + output + ")()";
}
}
return output;
}
fillMissingDigits();
replaceMap();
replaceStrings();
self.JSFuck = {
encode: encode
};
})(typeof(exports) === "undefined" ? window : exports);
//参数1:为需要转换的字符串
//参数2:是否开启Eval Source
//参数3:是否Run In Parent Scope
strJs=JSFuck.encode("console.log(123456)",true,true)
console.log(strJs)
// eval(strJs)
如何使用?
在你的项目里创建一个script的标签将上面的代码复制到里面 或者直接将上面的代码复制到js文件中在页面引入 ,如果你觉得复制太麻烦小编已经准备好了js下面是百度云的下载链接,在js引入页面后,使用JSFuck.encode函数 来对代码进行混淆
百度云地址:点我跳转 (提取码d0vv)
JSFuck.encode有三个参数
参数1:为需要转换的字符串
参数2:是否开启Eval Source
参数3:是否Run In Parent Scope使用实例:
strJs=JSFuck.encode("console.log(123456)",true,true)
console.log(strJs)
研究的意义
写了这么多,到底意义何在?那么我就来肤浅的说几个。
1、能了解到很多JS语言最基本的语法词法。对工作几年的老鸟,被各种框架蹂躏之后,最缺的就是语言基础,重温一遍未尝不是好事。
2、合理利用可以对代码进行伪加密。比如有些正则、有些敏感字符不打算给用户和同行程序员看,使用代码混淆之后,可以用这个技术对关键信息进行一次转换,提高解码难度。
3、防止类似这种的XSS代码注入。据说这是黑客最喜欢的注入方式,因为没有特殊字符,没有阿拉伯数字,仅仅只有6个特定字符,很多系统不会过滤这6个字符。
有没有意义因人而异,更多的意义是,只要你愿意研究,这些知识你都会掌握的!
作者:壹影
链接:https://bk.yyge.net/?post=188
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
发表评论