壹影博客.
我在下午4点钟开始想你
代码混淆JSFuck-一款开源的Js混淆插件JsFuck
  • 2023-11-2日
  • 0评论
  • 15442围观

代码混淆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
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

发表评论

渝ICP备19011465号 | 渝ICP备19011465号-1