How to decode this hex code javascript?

Issue

I just came across a bit of code par my understanding can anyone help me in decoding the code .

var _0x98fd = ["\x2E\x6F\x76\x65\x72\x6C\x61\x70\x62\x6C\x61\x63\x6B\x62\x67\x2C\x20\x2E\x73\x6C\x69\x64\x65\x4C\x65\x66\x74", "\x2E\x77\x73\x6D\x65\x6E\x75\x63\x6F\x6E\x74\x65\x6E\x74", "\x6D\x65\x6E\x75\x6F\x70\x65\x6E", "\x61\x64\x64\x43\x6C\x61\x73\x73", "\x6D\x65\x6E\x75\x63\x6C\x6F\x73\x65", "\x72\x65\x6D\x6F\x76\x65\x43\x6C\x61\x73\x73", "\x68\x61\x73\x43\x6C\x61\x73\x73", "\x63\x6C\x69\x63\x6B", "\x23\x6E\x61\x76\x54\x6F\x67\x67\x6C\x65", "\x6D\x72\x67\x69\x6E\x6C\x65\x66\x74", "\x74\x6F\x67\x67\x6C\x65\x43\x6C\x61\x73\x73", "\x2E\x77\x73\x6D\x65\x6E\x75\x63\x6F\x6E\x74\x61\x69\x6E\x65\x72", "\x6F\x6E", "\x23\x6E\x61\x76\x54\x6F\x67\x67\x6C\x65\x2C\x2E\x6F\x76\x65\x72\x6C\x61\x70\x62\x6C\x61\x63\x6B\x62\x67", "\x3C\x73\x70\x61\x6E\x20\x63\x6C\x61\x73\x73\x3D\x22\x77\x73\x6D\x65\x6E\x75\x2D\x63\x6C\x69\x63\x6B\x22\x3E\x3C\x69\x20\x63\x6C\x61\x73\x73\x3D\x22\x77\x73\x6D\x65\x6E\x75\x2D\x61\x72\x72\x6F\x77\x20\x66\x61\x20\x66\x61\x2D\x61\x6E\x67\x6C\x65\x2D\x64\x6F\x77\x6E\x22\x3E\x3C\x2F\x69\x3E\x3C\x2F\x73\x70\x61\x6E\x3E", "\x70\x72\x65\x70\x65\x6E\x64", "\x2E\x77\x73\x6D\x65\x6E\x75\x2D\x73\x75\x62\x6D\x65\x6E\x75\x2C\x20\x2E\x77\x73\x6D\x65\x6E\x75\x2D\x73\x75\x62\x6D\x65\x6E\x75\x2D\x73\x75\x62\x2C\x20\x2E\x77\x73\x6D\x65\x6E\x75\x2D\x73\x75\x62\x6D\x65\x6E\x75\x2D\x73\x75\x62\x2D\x73\x75\x62", "\x68\x61\x73", "\x2E\x77\x73\x6D\x65\x6E\x75\x2D\x6C\x69\x73\x74\x20\x6C\x69", "\x2E\x6D\x65\x67\x61\x6D\x65\x6E\x75", "\x73\x6C\x6F\x77", "\x73\x6C\x69\x64\x65\x54\x6F\x67\x67\x6C\x65", "\x2E\x77\x73\x6D\x65\x6E\x75\x2D\x6C\x69\x73\x74", "\x2E\x77\x73\x6D\x65\x6E\x75\x2D\x6D\x6F\x62\x69\x6C\x65", "\x2E\x77\x73\x6D\x65\x6E\x75\x2D\x73\x75\x62\x6D\x65\x6E\x75", "\x73\x69\x62\x6C\x69\x6E\x67\x73", "\x77\x73\x6D\x65\x6E\x75\x2D\x72\x6F\x74\x61\x74\x65", "\x2E\x77\x73\x6D\x65\x6E\x75\x2D\x61\x72\x72\x6F\x77", "\x63\x68\x69\x6C\x64\x72\x65\x6E", "\x2E\x77\x73\x6D\x65\x6E\x75\x2D\x73\x75\x62\x6D\x65\x6E\x75\x2D\x73\x75\x62", "\x2E\x77\x73\x6D\x65\x6E\x75\x2D\x73\x75\x62\x6D\x65\x6E\x75\x2D\x73\x75\x62\x2D\x73\x75\x62", "\x2E\x77\x73\x6D\x65\x6E\x75\x2D\x63\x6C\x69\x63\x6B"];
$(function() {
    var _0x5c8dx1 = $(_0x98fd[0]);
    var _0x5c8dx2 = $(_0x98fd[1]);
    var _0x5c8dx3 = function() {
        $(_0x5c8dx1)[_0x98fd[5]](_0x98fd[4])[_0x98fd[3]](_0x98fd[2])
    };
    var _0x5c8dx4 = function() {
        $(_0x5c8dx1)[_0x98fd[5]](_0x98fd[2])[_0x98fd[3]](_0x98fd[4])
    };
    $(_0x98fd[8])[_0x98fd[7]](function() {
        if (_0x5c8dx2[_0x98fd[6]](_0x98fd[2])) {
            $(_0x5c8dx4)
        } else {
            $(_0x5c8dx3)
        }
    });
    _0x5c8dx2[_0x98fd[7]](function() {
        if (_0x5c8dx2[_0x98fd[6]](_0x98fd[2])) {
            $(_0x5c8dx4)
        }
    });
    $(_0x98fd[13])[_0x98fd[12]](_0x98fd[7], function() {
        $(_0x98fd[11])[_0x98fd[10]](_0x98fd[9])
    });
    $(_0x98fd[18])[_0x98fd[17]](_0x98fd[16])[_0x98fd[15]](_0x98fd[14]);
    $(_0x98fd[18])[_0x98fd[17]](_0x98fd[19])[_0x98fd[15]](_0x98fd[14]);
    $(_0x98fd[23])[_0x98fd[7]](function() {
        $(_0x98fd[22])[_0x98fd[21]](_0x98fd[20])
    });
    $(_0x98fd[31])[_0x98fd[7]](function() {
        $(this)[_0x98fd[25]](_0x98fd[24])[_0x98fd[21]](_0x98fd[20]);
        $(this)[_0x98fd[28]](_0x98fd[27])[_0x98fd[10]](_0x98fd[26]);
        $(this)[_0x98fd[25]](_0x98fd[29])[_0x98fd[21]](_0x98fd[20]);
        $(this)[_0x98fd[25]](_0x98fd[30])[_0x98fd[21]](_0x98fd[20]);
        $(this)[_0x98fd[25]](_0x98fd[19])[_0x98fd[21]](_0x98fd[20]);
    });
});

I am not new to Javascript and its confusing for me

Solution

That is obfuscated & minified JavaScript. The array of Hex characters decodes to an array of method names, class names, and jQuery selectors:

".overlapblackbg, .slideLeft"
".wsmenucontent"
"menuopen"
"addClass"
"menuclose"
"removeClass"
"hasClass"
"click"
"#navToggle"
"mrginleft"
"toggleClass"
".wsmenucontainer"
"on"
"#navToggle,.overlapblackbg"
"<span class="wsmenu-click"><i class="wsmenu-arrow fa fa-angle-down"></i></span>"
"prepend"
".wsmenu-submenu, .wsmenu-submenu-sub, .wsmenu-submenu-sub-sub"
"has"
".wsmenu-list li"
".megamenu"
"slow"
"slideToggle"
".wsmenu-list"
".wsmenu-mobile"
".wsmenu-submenu"
"siblings"
"wsmenu-rotate"
".wsmenu-arrow"
"children"
".wsmenu-submenu-sub"
".wsmenu-submenu-sub-sub"
".wsmenu-click"

I also wrote a quick decoder, in a JSFiddle,

http://jsfiddle.net/TrueBlueAussie/1jwb60pe/1/

that came up with this:

$(function() {
    var $menu = $(".overlapblackbg, .slideLeft");
    var $wsmenucontent = $(".wsmenucontent");
    var openMenu = function() {
        $($menu).removeClass("menuclose").addClass("menuopen")
    };
    var closeMenu = function() {
        $($menu).removeClass("menuopen").addClass("menuclose")
    };
    $("#navToggle").click(function() {
        if ($wsmenucontent.hasClass("menuopen")) {
            $(closeMenu)
        } else {
            $(openMenu)
        }
    });
    $wsmenucontent.click(function() {
        if ($wsmenucontent.hasClass("menuopen")) {
            $(closeMenu)
        }
    });
    $("#navToggle,.overlapblackbg").on(click, function() {
        $(".wsmenucontainer").toggleClass("mrginleft")
    });
    $(".wsmenu-list li").has(".wsmenu-submenu, .wsmenu-submenu-sub, .wsmenu-submenu-sub-sub").prepend("<span class="wsmenu-click"><i class="wsmenu-arrow fa fa-angle-down"></i></span>");
    $(".wsmenu-list li").has(".megamenu").prepend("<span class="wsmenu-click"><i class="wsmenu-arrow fa fa-angle-down"></i></span>");
    $(".wsmenu-mobile").click(function() {
        $(".wsmenu-list").slideToggle("slow")
    });
    $(".wsmenu-click").click(function() {
        $(this).siblings(".wsmenu-submenu").slideToggle("slow");
        $(this).children(".wsmenu-arrow").toggleClass("wsmenu-rotate");
        $(this).siblings(".wsmenu-submenu-sub").slideToggle("slow");
        $(this).siblings(".wsmenu-submenu-sub-sub").slideToggle("slow");
        $(this).siblings(".megamenu").slideToggle("slow");
    });
});

The advantage of the decoder of course is that you can keep tweaking it to do more decoding without having to redo it manually.

It is interesting to note that the decoded version actually shows that they have made errors, like wrapping jQuery objects a second time!

e.g.

var _0x5c8dx1 = $(".overlapblackbg, .slideLeft");

then

$(_0x5c8dx1).removeClass("menuclose").addClass("menuopen")

It also uses obscure side effects to run functions like:

$(closeMenu)

Which is a shortcut for $(document).ready(closeMenu) which will fire the function immediately.


Working de-obfuscation demo

const variableMap = {
  "_0x5c8dx1": "$menu",
  "_0x5c8dx2": "$wsmenucontent",
  "_0x5c8dx3": "openMenu",
  "_0x5c8dx4": "closeMenu"
};

var obfuscatedCode   = document.querySelector('#source-code').value;
var deobfuscatedCode = decode(obfuscatedCode);

let editor = ace.edit("ace-editor");
editor.setTheme("ace/theme/github");
editor.session.setMode("ace/mode/javascript");
editor.setValue(deobfuscatedCode);
editor.clearSelection();

// Beautify the code...
editor.getSession().setValue(js_beautify(editor.getValue(), {
  indent_size: 2
}));

function decode(script) {
  var decoded = parseAscii(script);
  decoded = replaceWithStrings(decoded, parseStringArray(decoded));
  decoded = replaceVariables(decoded.substring(decoded.indexOf('\n') + 1), variableMap);
  decoded = bracketToDotNotation(decoded);
  return decoded;
}

function parseAscii(input) {
  return input.replace(/\\x([0-9A-F]{2})/g, (g, g1) => {
    return String.fromCharCode(parseInt(g1, 16));
  });
}

function parseStringArray(input) {
  return input.substring(input.indexOf('["') + 2, input.indexOf('"];')).split(/"\s*,\s*"/g);
}

function replaceWithStrings(input, arr) {
  return input.replace(/_0x[0-9a-f]+\[(\d+)\]/g, (m, m1) => {
    return `"${escapeQuotes(arr[parseInt(m1, 10)])}"`;
  });
}

function escapeQuotes(input) {
  return input.replace(/"/g, "\\\"");
}

function replaceVariables(input, variableMap) {
  return Object.keys(variableMap).reduce((decoded, key) => {
    return decoded.replace(new RegExp('\\b' + key + '\\b', 'g'), () => {
      return variableMap[key];
    });
  }, input);
}

function bracketToDotNotation(input) {
  return input.replace(/\["(\w+)"\]/g, '.$1');
}
#ace-editor { 
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.8/ace.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.8/mode-javascript.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.8/theme-github.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/js-beautify/1.10.2/beautify.min.js"></script>
<div id="ace-editor"></div>
<textarea id="source-code" style="display:none">var _0x98fd = ["\x2E\x6F\x76\x65\x72\x6C\x61\x70\x62\x6C\x61\x63\x6B\x62\x67\x2C\x20\x2E\x73\x6C\x69\x64\x65\x4C\x65\x66\x74", "\x2E\x77\x73\x6D\x65\x6E\x75\x63\x6F\x6E\x74\x65\x6E\x74", "\x6D\x65\x6E\x75\x6F\x70\x65\x6E", "\x61\x64\x64\x43\x6C\x61\x73\x73", "\x6D\x65\x6E\x75\x63\x6C\x6F\x73\x65", "\x72\x65\x6D\x6F\x76\x65\x43\x6C\x61\x73\x73", "\x68\x61\x73\x43\x6C\x61\x73\x73", "\x63\x6C\x69\x63\x6B", "\x23\x6E\x61\x76\x54\x6F\x67\x67\x6C\x65", "\x6D\x72\x67\x69\x6E\x6C\x65\x66\x74", "\x74\x6F\x67\x67\x6C\x65\x43\x6C\x61\x73\x73", "\x2E\x77\x73\x6D\x65\x6E\x75\x63\x6F\x6E\x74\x61\x69\x6E\x65\x72", "\x6F\x6E", "\x23\x6E\x61\x76\x54\x6F\x67\x67\x6C\x65\x2C\x2E\x6F\x76\x65\x72\x6C\x61\x70\x62\x6C\x61\x63\x6B\x62\x67", "\x3C\x73\x70\x61\x6E\x20\x63\x6C\x61\x73\x73\x3D\x22\x77\x73\x6D\x65\x6E\x75\x2D\x63\x6C\x69\x63\x6B\x22\x3E\x3C\x69\x20\x63\x6C\x61\x73\x73\x3D\x22\x77\x73\x6D\x65\x6E\x75\x2D\x61\x72\x72\x6F\x77\x20\x66\x61\x20\x66\x61\x2D\x61\x6E\x67\x6C\x65\x2D\x64\x6F\x77\x6E\x22\x3E\x3C\x2F\x69\x3E\x3C\x2F\x73\x70\x61\x6E\x3E", "\x70\x72\x65\x70\x65\x6E\x64", "\x2E\x77\x73\x6D\x65\x6E\x75\x2D\x73\x75\x62\x6D\x65\x6E\x75\x2C\x20\x2E\x77\x73\x6D\x65\x6E\x75\x2D\x73\x75\x62\x6D\x65\x6E\x75\x2D\x73\x75\x62\x2C\x20\x2E\x77\x73\x6D\x65\x6E\x75\x2D\x73\x75\x62\x6D\x65\x6E\x75\x2D\x73\x75\x62\x2D\x73\x75\x62", "\x68\x61\x73", "\x2E\x77\x73\x6D\x65\x6E\x75\x2D\x6C\x69\x73\x74\x20\x6C\x69", "\x2E\x6D\x65\x67\x61\x6D\x65\x6E\x75", "\x73\x6C\x6F\x77", "\x73\x6C\x69\x64\x65\x54\x6F\x67\x67\x6C\x65", "\x2E\x77\x73\x6D\x65\x6E\x75\x2D\x6C\x69\x73\x74", "\x2E\x77\x73\x6D\x65\x6E\x75\x2D\x6D\x6F\x62\x69\x6C\x65", "\x2E\x77\x73\x6D\x65\x6E\x75\x2D\x73\x75\x62\x6D\x65\x6E\x75", "\x73\x69\x62\x6C\x69\x6E\x67\x73", "\x77\x73\x6D\x65\x6E\x75\x2D\x72\x6F\x74\x61\x74\x65", "\x2E\x77\x73\x6D\x65\x6E\x75\x2D\x61\x72\x72\x6F\x77", "\x63\x68\x69\x6C\x64\x72\x65\x6E", "\x2E\x77\x73\x6D\x65\x6E\x75\x2D\x73\x75\x62\x6D\x65\x6E\x75\x2D\x73\x75\x62", "\x2E\x77\x73\x6D\x65\x6E\x75\x2D\x73\x75\x62\x6D\x65\x6E\x75\x2D\x73\x75\x62\x2D\x73\x75\x62", "\x2E\x77\x73\x6D\x65\x6E\x75\x2D\x63\x6C\x69\x63\x6B"];
$(function(){var _0x5c8dx1=$(_0x98fd[0]);var _0x5c8dx2=$(_0x98fd[1]);var _0x5c8dx3=function(){$(_0x5c8dx1)[_0x98fd[5]](_0x98fd[4])[_0x98fd[3]](_0x98fd[2])};var _0x5c8dx4=function(){$(_0x5c8dx1)[_0x98fd[5]](_0x98fd[2])[_0x98fd[3]](_0x98fd[4])};$(_0x98fd[8])[_0x98fd[7]](function(){if(_0x5c8dx2[_0x98fd[6]](_0x98fd[2])){$(_0x5c8dx4)}else{$(_0x5c8dx3)}});_0x5c8dx2[_0x98fd[7]](function(){if(_0x5c8dx2[_0x98fd[6]](_0x98fd[2])){$(_0x5c8dx4)}});$(_0x98fd[13])[_0x98fd[12]](_0x98fd[7],function(){$(_0x98fd[11])[_0x98fd[10]](_0x98fd[9])});$(_0x98fd[18])[_0x98fd[17]](_0x98fd[16])[_0x98fd[15]](_0x98fd[14]);$(_0x98fd[18])[_0x98fd[17]](_0x98fd[19])[_0x98fd[15]](_0x98fd[14]);$(_0x98fd[23])[_0x98fd[7]](function(){$(_0x98fd[22])[_0x98fd[21]](_0x98fd[20])});$(_0x98fd[31])[_0x98fd[7]](function(){$(this)[_0x98fd[25]](_0x98fd[24])[_0x98fd[21]](_0x98fd[20]);$(this)[_0x98fd[28]](_0x98fd[27])[_0x98fd[10]](_0x98fd[26]);$(this)[_0x98fd[25]](_0x98fd[29])[_0x98fd[21]](_0x98fd[20]);$(this)[_0x98fd[25]](_0x98fd[30])[_0x98fd[21]](_0x98fd[20]);$(this)[_0x98fd[25]](_0x98fd[19])[_0x98fd[21]](_0x98fd[20])})});</textarea>

Answered By – Gone Coding

Answer Checked By – Senaida (AngularFixing Volunteer)

Leave a Reply

Your email address will not be published.