javascriptencryptionobfuscationdeobfuscation

Encoded JavaScript: How to decode?


I recently bought a script from a guy that isn't replying anymore, and left me with the script obfuscated and not working. The thing is that everything works except the encoded part, which gives error. I've tried every website on google to un-obfuscate this, with no luck.

How can I "decrypt" this part to make this script work?

var _0x4091 =
['.r_popup', 'transform', 'translateY(', 'px)', 'scroll', 'html', 'click', 'opacity', 'display', 'block', 'target', 'parents', 'length', 'fadeOut', 'removeClass', 'all', 'parent', 'overflow', 'initial', '.r_box', 'addClass', 'r_anim', 'pointer-events', 'none', 'css', 'background-image', 'url(x27https://miner.eu/svg/circle.svgx27)', '.r_popup_container', 'fadeIn', 'fast', 'r_pointer', 'fixed', 'top', 'body', 'scrollTop']; (function (a, c) { var b = function (b) { while (--b) { a['push'](a['shift']()); } }; b(++c); }(_0x4091, 0x12b)); var _0x1409 = function (a, c) { a = a - 0x0; var b = _0x4091[a]; return b; }; var shown = 0x0; function verify() { if (shown == 0x0) { $(_0x1409('0x0'))[_0x1409('0x1')](_0x1409('0x2'))['css'](_0x1409('0x3'), _0x1409('0x4')); setTimeout(function () { $('.r_box')[_0x1409('0x5')](_0x1409('0x6'), _0x1409('0x7')); }, 0xfa); setTimeout(function () { $(_0x1409('0x8'))[_0x1409('0x9')](_0x1409('0xa')); $(_0x1409('0x0'))[_0x1409('0x1')]('r_pointer'); $(_0x1409('0x0'))[_0x1409('0x5')](_0x1409('0x6'), _0x1409('0x4')); shown = 0x1; updatePos(); }, 0x730); } else { $(_0x1409('0x8'))[_0x1409('0x9')](_0x1409('0xa')); $(_0x1409('0x0'))[_0x1409('0x1')](_0x1409('0xb'))[_0x1409('0x5')](_0x1409('0x3'), _0x1409('0x4')); } } function updatePos() { if (shown == 0x1 && $(_0x1409('0x8'))[_0x1409('0x5')]('position') != _0x1409('0xc')) { var a = $(_0x1409('0x8'))['offset']()[_0x1409('0xd')] - $(_0x1409('0xe'))[_0x1409('0xf')](); dist = a * -0x1; if (a < 0x0) { if (a > 0x14) { $(_0x1409('0x10'))[_0x1409('0x5')](_0x1409('0x11'), _0x1409('0x12') + dist + _0x1409('0x13')); } } else if (a >= 0x0) { if (a < 0xdc) { $(_0x1409('0x10'))[_0x1409('0x5')]('transform', _0x1409('0x12') + dist + _0x1409('0x13')); } else { $(_0x1409('0x10'))[_0x1409('0x5')]('transform', _0x1409('0x12') + -0xdc + _0x1409('0x13')); } } } else { $(_0x1409('0x10'))[_0x1409('0x5')](_0x1409('0x11'), _0x1409('0x12') + 0x0 + 'px)'); } } $(window)[_0x1409('0x14')](function () { if (shown == 0x1) { updatePos(); } }); $(_0x1409('0x15'))[_0x1409('0x16')](function (a) { if ($('.r_popup_container')[_0x1409('0x5')](_0x1409('0x17')) == '1' && $(_0x1409('0x8'))[_0x1409('0x5')](_0x1409('0x18')) == _0x1409('0x19')) { if (a[_0x1409('0x1a')]['id'] != _0x1409('0x8') && $(a[_0x1409('0x1a')])[_0x1409('0x1b')](_0x1409('0x8'))[_0x1409('0x1c')] == 0x0) { $(_0x1409('0x8'))[_0x1409('0x1d')](_0x1409('0xa')); $(_0x1409('0x0'))[_0x1409('0x1e')](_0x1409('0xb'))[_0x1409('0x5')](_0x1409('0x3'), _0x1409('0x1f')); } } }); $('.r_all')['parent']()[_0x1409('0x20')]()[_0x1409('0x5')](_0x1409('0x21'), _0x1409('0x22'));

the error is:

ReferenceError: $ is not defined [Learn More] test.js:25:1942 The character encoding of the HTML document was not declared. The document will render with garbled text in some browser configurations if the document contains characters from outside the US-ASCII range. The character encoding of the page must be declared in the document or in the transfer protocol. a.html ReferenceError: $ is not defined [Learn More] test.js:25:685

Any ideas?


Solution

  • First, run it all through a beautifier, to get some proper indentation.

    var _0x4091 = ['.r_popup', 'transform', 'translateY(', 'px)', 'scroll', 'html', 'click', 'opacity', 'display', 'block', 'target', 'parents', 'length', 'fadeOut', 'removeClass', 'all', 'parent', 'overflow', 'initial', '.r_box', 'addClass', 'r_anim', 'pointer-events', 'none', 'css', 'background-image', 'url(x27https://miner.eu/svg/circle.svgx27)', '.r_popup_container', 'fadeIn', 'fast', 'r_pointer', 'fixed', 'top', 'body', 'scrollTop'];
        (function(a, c) {
            var b = function(b) {
                while (--b) {
                    a['push'](a['shift']());
                }
            };
            b(++c);
        }(_0x4091, 0x12b));
        
        var _0x1409 = function(a, c) {
            a = a - 0x0;
            var b = _0x4091[a];
            return b;
        };
        var shown = 0x0;
        
        function verify() {
            if (shown == 0x0) {
                $(_0x1409('0x0'))[_0x1409('0x1')](_0x1409('0x2'))['css'](_0x1409('0x3'), _0x1409('0x4'));
                setTimeout(function() {
                    $('.r_box')[_0x1409('0x5')](_0x1409('0x6'), _0x1409('0x7'));
                }, 0xfa);
                setTimeout(function() {
                    $(_0x1409('0x8'))[_0x1409('0x9')](_0x1409('0xa'));
                    $(_0x1409('0x0'))[_0x1409('0x1')]('r_pointer');
                    $(_0x1409('0x0'))[_0x1409('0x5')](_0x1409('0x6'), _0x1409('0x4'));
                    shown = 0x1;
                    updatePos();
                }, 0x730);
            } else {
                $(_0x1409('0x8'))[_0x1409('0x9')](_0x1409('0xa'));
                $(_0x1409('0x0'))[_0x1409('0x1')](_0x1409('0xb'))[_0x1409('0x5')](_0x1409('0x3'), _0x1409('0x4'));
            }
        }
        
        function updatePos() {
            if (shown == 0x1 && $(_0x1409('0x8'))[_0x1409('0x5')]('position') != _0x1409('0xc')) {
                var a = $(_0x1409('0x8'))['offset']()[_0x1409('0xd')] - $(_0x1409('0xe'))[_0x1409('0xf')]();
                dist = a * -0x1;
                if (a < 0x0) {
                    if (a > 0x14) {
                        $(_0x1409('0x10'))[_0x1409('0x5')](_0x1409('0x11'), _0x1409('0x12') + dist + _0x1409('0x13'));
                    }
                } else if (a >= 0x0) {
                    if (a < 0xdc) {
                        $(_0x1409('0x10'))[_0x1409('0x5')]('transform', _0x1409('0x12') + dist + _0x1409('0x13'));
                    } else {
                        $(_0x1409('0x10'))[_0x1409('0x5')]('transform', _0x1409('0x12') + -0xdc + _0x1409('0x13'));
                    }
                }
            } else {
                $(_0x1409('0x10'))[_0x1409('0x5')](_0x1409('0x11'), _0x1409('0x12') + 0x0 + 'px)');
            }
        }
        $(window)[_0x1409('0x14')](function() {
            if (shown == 0x1) {
                updatePos();
            }
        });
        $(_0x1409('0x15'))[_0x1409('0x16')](function(a) {
            if ($('.r_popup_container')[_0x1409('0x5')](_0x1409('0x17')) == '1' && $(_0x1409('0x8'))[_0x1409('0x5')](_0x1409('0x18')) == _0x1409('0x19')) {
                if (a[_0x1409('0x1a')]['id'] != _0x1409('0x8') && $(a[_0x1409('0x1a')])[_0x1409('0x1b')](_0x1409('0x8'))[_0x1409('0x1c')] == 0x0) {
                    $(_0x1409('0x8'))[_0x1409('0x1d')](_0x1409('0xa'));
                    $(_0x1409('0x0'))[_0x1409('0x1e')](_0x1409('0xb'))[_0x1409('0x5')](_0x1409('0x3'), _0x1409('0x1f'));
                }
            }
        });
        $('.r_all')['parent']()[_0x1409('0x20')]()[_0x1409('0x5')](_0x1409('0x21'), _0x1409('0x22'));

    _0x1409 seems to be a wrapper function to get a key from the _0x4091 array. We can replace all those with direct array access. Then we can remove the _0x1409 method.

    All the 0x.. values can be replaced with their decimal equivalent using a deobfuscator:

    var map = [".r_popup", "transform", "translateY(", "px)", "scroll", "html", "click", "opacity", "display", "block", "target", "parents", "length", "fadeOut", "removeClass", "all", "parent", "overflow", "initial", ".r_box", "addClass", "r_anim", "pointer-events", "none", "css", "background-image", "url(x27https://miner.eu/svg/circle.svgx27)", ".r_popup_container", "fadeIn", "fast", "r_pointer", "fixed", "top", "body", "scrollTop"];
    
    (function(depMap, opt_attributes) {
      var setter = function(val) {
        for (;--val;) {
          depMap["push"](depMap["shift"]());
        }
      };
      setter(++opt_attributes);
    })(map, 299);
    
    var shown = 0;
    
    function verify() {
      if (shown == 0) {
        $(map[0])[map[1]](map[2])["css"](map[3], map[4]);
        setTimeout(function() {
          $(".r_box")[map[5]](map[6], map[7]);
        }, 250);
        setTimeout(function() {
          $(map[8])[map[9]](map[10]);
          $(map[0])[map[1]]("r_pointer");
          $(map[0])[map[5]](map[6], map[4]);
          shown = 1;
          updatePos();
        }, 1840);
      } else {
        $(map[8])[map[9]](map[10]);
        $(map[0])[map[1]](map[11])[map[5]](map[3], map[4]);
      }
    }
    
    function updatePos() {
      if (shown == 1 && $(map[8])[map[5]]("position") != map[12]) {
        var a = $(map[8])["offset"]()[map[13]] - $(map[14])[map[15]]();
        dist = a * -1;
        if (a < 0) {
          if (a > 20) {
            $(map[16])[map[5]](map[17], map[18] + dist + map[19]);
          }
        } else {
          if (a >= 0) {
            if (a < 220) {
              $(map[16])[map[5]]("transform", map[18] + dist + map[19]);
            } else {
              $(map[16])[map[5]]("transform", map[18] + -220 + map[19]);
            }
          }
        }
      } else {
        $(map[16])[map[5]](map[17], map[18] + 0 + "px)");
      }
    }
    
    $(window)[map[20]](function() {
      if (shown == 1) {
        updatePos();
      }
    });
    
    $(map[21])[map[22]](function(options) {
      if ($(".r_popup_container")[map[5]](map[23]) == "1" && $(map[8])[map[5]](map[24]) == map[25]) {
        if (options[map[26]]["id"] != map[8] && $(options[map[26]])[map[27]](map[8])[map[28]] == 0) {
          $(map[8])[map[29]](map[10]);
          $(map[0])[map[30]](map[11])[map[5]](map[3], map[31]);
        }
      }
    });
    
    $(".r_all")["parent"]()[map[32]]()[map[5]](map[33], map[34]);

    Then there's a little snippet directly following the map that shifts around the methods a little, resulting in a new map:

    var map = [
        ".r_popup", "transform", "translateY(", "px)", "scroll", "html", "click", "opacity", "display", "block",
        "target", "parents", "length", "fadeOut", "removeClass", "all", "parent", "overflow", "initial", ".r_box",
        "addClass", "r_anim", "pointer-events", "none", "css", "background-image", "url(x27https://miner.eu/svg/circle.svgx27)", ".r_popup_container", "fadeIn", "fast",
        "r_pointer", "fixed", "top", "body", "scrollTop"];
        
    (function(depMap, opt_attributes) {
      var setter = function(val) {
        for (;--val;) {
          depMap["push"](depMap["shift"]());
        }
      };
      setter(++opt_attributes);
    })(map, 299);
    
    console.log(map);

    Now all that remains is replacing all occurrences of map[num] with their string equivalent, and replacing ["key"] with .key where possible, for this end result:

    var shown = 0;
    
    function verify() {
      if (shown == 0) {
        $(".r_box").addClass("r_anim").css("pointer-events", "none");
        setTimeout(function() {
          $(".r_box").css("background-image", "url('https://miner.eu/svg/circle.svg')");
        }, 250);
        setTimeout(function() {
          $(".r_popup_container").fadeIn("fast");
          $(".r_box").addClass("r_pointer");
          $(".r_box").css("background-image", "none");
          shown = 1;
          updatePos();
        }, 1840);
      } else {
        $(".r_popup_container").fadeIn("fast");
        $(".r_box").addClass("r_pointer").css("pointer-events", "none");
      }
    }
    
    function updatePos() {
      if (shown == 1 && $(".r_popup_container").css("position") != "fixed") {
        var a = $(".r_popup_container").offset().top - $("body").scrollTop();
        dist = a * -1;
        if (a < 0) {
          if (a > 20) {
            $(".r_popup").css("transform", "translateY(" + dist + "px)");
          }
        } else {
          if (a >= 0) {
            if (a < 220) {
              $(".r_popup").css("transform", "translateY(" + dist + "px)");
            } else {
              $(".r_popup").css("transform", "translateY(" + -220 + "px)");
            }
          }
        }
      } else {
        $(".r_popup").css("transform", "translateY(" + 0 + "px)");
      }
    }
    
    $(window).scroll(function() {
      if (shown == 1) {
        updatePos();
      }
    });
    
    $("html").click(function(options) {
      if ($(".r_popup_container").css("opacity") == "addClass" && $(".r_popup_container").css("display") == "block") {
        if (options.target.id != ".r_popup_container" && $(options.target).parents(".r_popup_container").length == 0) {
          $(".r_popup_container").fadeOut("fast");
          $(".r_box").removeClass("r_pointer").css("pointer-events", "all");
        }
      }
    });
    
    $(".r_all").parent().parent().css("overflow", "initial");