1

I am trying to protect my app code from theft. Since most of it is written in javascript I had to use many obfuscation techniques to make it incomprehensible.

I have written a very small piece of code for demonstration purposes (under 20 lines) which has been obfuscated. I wonder how easy it is to reverse engineer or is it difficult enough to make life a hell?

Here a demo with the code:

http://jsfiddle.net/0s84pxvc/1/

Goal: can you find out how the string inside the alert is generated when you fire a click event on the window?

  • 2
    Because this is a challenge you should give a flag to capture or a change to do that you want to make impossible to do. Sometimes we do not need to deobfuscate code too much for simply intercept a code, or similar. So... Give a goal. This is because obfuscation is not the solution for every problem. Anyway I will try tomorrow. – realtebo Aug 5 '18 at 10:55
  • @realtebo added a goal. Thanks for the advice – Asperger Aug 5 '18 at 12:50
  • The first array is simply to attack, we convert octal to ascii then base64decode and we got the dictionary. – realtebo Aug 5 '18 at 14:05
  • @realtebo so did you figure out how im generating the string: "I am still 24 hours a day obfuscated" when clicking on the window? :) – Asperger Aug 5 '18 at 14:07
  • 1
    Full Solved, i'm available for next level challenge.I succesfully solved the 'on the fly' fake redirect of paypal last week.... I didn't gained a single dollar, but was so fun. Rember one thing: if you create an entire custom fw in js, probably no one will be interested in copying it. So obfuscate it, ok, it will be protected enough. But if there is something of important under js, it's just question of time and patience. – realtebo Aug 5 '18 at 21:29
2

Resolved.

  1. generally nothing in js is impossible to reverse
  2. in this case the 'alert' string in plain text give me a big help, because I simply started to resolve function value one step back at time.
  3. same thing for the setInterval, it was in plain Text
  4. This is near the same identical schema of obfuscation of a PDF virus, a JS that internally was doing massive click on a ad rotator; I never see another sample of this before... this is simply strange, I hope
  5. to kill the anti debug trap, simply overrife the debugger function or at first debugger pause, simply click 'disable breakpoint'. Note that this lead to a memory leak, a big memory leak, and Chrome protect itself by stopping recursion. To avoid this, when in pause see the stack call list, get the place when the anonimous function is called and overrie it to simply do nothing

DECODE THE ARRAY

Decode unicode. Use an online tool like this and you can got

var _0x1b0e=['RNBwL','ScKnC','BdjwA','gjKqY','NLCsj','3|2|1|5|0|4|6','iXTyC','constructor','call','Pvdko','ymXVL','uEdcI','I am obfuscated...','riWLD','click','addEventListener','Handler','bind','PwLbK','jYzDF','ndilm','AYDEt','stateObject','vIaGc','pZYix','yTHkP','NHTVJ','CRKBx','enNxX','I am still ','JEZNs',' hours a day obfuscated!','RBXnA','0|1|3|6|5|2|4','TlFHD','NIHXQ','bKETV','ZvwJA','jTRge','lwamn','xjQhJ','tZgNp','PEeVj','FwPPe','HyevS','ffbgA','uQzhD','hOThG','RDxue','zUlaT','qxKfp','7|0|6|4|8|1|5|2|3','kEOXz','hDbut','DEbtW','EWekr','string','uLpny','OKzxq','NUsPS','xQKWu','while (true) {}','YNeoc','counter','hlebj','vtlYy','FxZTK','pLTxF','GWIKo','MHAff','Vgchj','RVWUv','length','Yplhb','DhPfd','RYVOZ','IJelL','LEBxy','uopuc','JTcvT','emAWc','GNCRi','nnpzO','kFplL','UBabX','leugg','hgMkn','uwEeM','IsYwa','xvqSS','WBYyN','wYbEn','NVOhv','lrXaL','sCqTs','tlBST','QVIIo','RqrUk','oyxkA','UpIwZ','TADqK','KHgQl','lyfsc','LuNwu','xVbVv','OsXCq','ItQkC','uXiDn','QnQvl','GVxah','SofZe','VunRI','wnuof','fUBve','foyFv','DlhfN','7|4|1|0|2|5|8|3|6','lkihY','qOXDh','ErKPA','YtkOE','qwIQA','ywRts','CjQTl','WLHwy','apply','console','split','debug','warn','info','trace','log','error','exception','cBfic','FdtOi','xXeRs','oKaof','return (function() ','tbYvC','{}.constructor("return this")( )','IjtnV','JRoNn','mQiLi','OIhHz','function *\( *\)','Smwjb','\+\+ *(?:_0x(?:[a-f0-9]){4,6}|(?:\b|\d)[a-z0-9]{1,4}(?:\b|\d))','anVxw','init','PBXIl','DedOs','chain','oLLoP','input','PjnEZ','btVNP','zPhfG','WLdDf','Glpfp','IJdqv','WCdVE','gwVJU','IbJVG','ZHHTo','aNucS','cHacR','CEAKU','sSJyA','test','cgpWb','duVJu','zdtWo','PbmnJ','IQbBw','naiWO','QewNf','TpeaO','kDYZL','GJZry','YGCTR','ztBcC','lkDUw','RJjSU','LbegF','gxAQf','BToeI','LsOQW','HyNsS','hUvxa','FrcoK','xaYAI','dxdFC','glyis','fLiNQ','zgXtG','oLHYG','GOzNr','dJbqD','CyyGn','nAaFv','JTpMq','cyOzF','INWzx','wTsIO','EdBey','pfRVT','eOkUT','ophhQ','wuWdq','lPvac','rQIPK','vxJVR','rRYsV','qQKiS','debu','piAiF','gger','PnsCa','action','afbRz','HKuCd','eRGsq','BisqR','KdEkB','gMVsG','XEayW','LPtpl','ErVeQ','EEfQz','jKbtX','xCKWk','wfZEF','GgolG','sBRCc','yNhcf','jVPUr','jOCmP','DjMYX','6|4|7|5|2|0|3|8|1','bmgZk','UFuMD','vrpeE','MbsEY'];

Here you find the "I am still obsfuscated..." and the other string, but this is just the color of the flag, not the flah itself, because you asked 'how you showed it'.

I can point to the alert function near the bottom of the code, but it was too simple ....

The key for the work is the 2n function

var _0x2bb4 = function(_0x5c85d8, _0xdd28ab) {
    _0x5c85d8 = _0x5c85d8 - 0x0;
    var _0xda35ee = _0x1b0e[_0x5c85d8];
    return _0xda35ee;
};

Wich can be simplified as

var _0x2bb4 = function(index) { return _0x1b0e[index] };

Then I replaced _0x1b0e with string_array, So I got

var _0x2bb4 = function(index) { 
  console.log (index, string_array[index]);
  return string_array[index]; 
};

And replace every call to _0x2bb4(something) with their result.

.. at the end of the story ..

The first call is done at the end of the code where there is this code

if( 
 _0x28a0fa[_0x2bb4('0xd2')] (
    _0x28a0fa[_0x2bb4('0xec')],
    _0x28a0fa[_0x2bb4('0xec')]
  )
){
 _0x28a0fa[_0x2bb4('0xde')]
 (alert,_0x28a0fa[_0x2bb4('0xdf')]);

 window[_0x2bb4('0x97')](_0x28a0fa[_0x2bb4('0xe0')],this[_0x2bb4('0x98')][_0x2bb4('0x99')](this));}

The if is a if ( 1 ) because is comparing two identical strings and the _0x28a0fa[_0x2bb4('0xde')]( arg1, arg2 ) is a simple

args1(arg2)

doing

alert (_0x28a0fa["uwEeM"]);

where _0x28a0fa["uwEeM"] is _0x2bb4('0x94') that returns _0x1b0e[0x94] that is exactly the string "I am still obfsuscated"

While the second time the alert is showed is thanks this

setInterval(function() {
    var _0x3d8cab = {};
    _0x3d8cab[_0x2bb4('0x91')] = function(_0x2383ea) {
        return _0x2383ea();
    };
    _0x3d8cab[_0x2bb4('0x91')](_0x58c724);
}, 0xfa0);


setInterval(function() {
    var _0x3d8cab = {};
    _0x3d8cab["Pvdko"] = function(_0x2383ea) {
        return _0x2383ea();
    };
    _0x3d8cab["Pvdko"](_0x58c724);
}, 0xfa0);


setInterval(function() {

    what_to_call = function(_0x2383ea) {
        return _0x2383ea();
    };
    what_to_call(_0x58c724);
}, 0xfa0);

setInterval(function() {

    what_to_call = function(function_to_call) {
        return function_to_call();
    };
    what_to_call(_0x58c724);
}, 0xfa0);

setInterval(function() {

   _0x58c724();
}, 4000);

The function _0x58c724(); in defined in the code, you can simply search vy its name.

It's accepting an argument. and it's nead just few line before the previous alert code

if (_0x3f8146) {
            if (_0x28a0fa[_0x2bb4('0xc8')](_0x28a0fa[_0x2bb4('0xe8')], _0x28a0fa[_0x2bb4('0xea')])) {
                return ![];
            } else {
                return _0x3145db;
            }
        }
  • Was the exact implementation obvious though? Here is the original code: jsfiddle.net/05Ln8ur3 – Asperger Aug 5 '18 at 22:54
  • The implementation of the obfuscator, yes, was a little too obvious,... the method for display alert and a delayed alert also, but ... no, i've no idea of what the code looked like originally. It can be enough depending on your goal – realtebo Aug 7 '18 at 12:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.