Hello!
I was fiddling around with code that I obfuscated with this tool, trying to figure out a way to manipulate things. I discovered, that I could easily edit the string array/map in obfuscated code with selfdefend and stringarray on. I was wondering if there was any security to prevent such editing.
For example, in the example (with hello world), I could make it print something else by modifying the string array in the beginning
// Hello world!
var a=['AdvLv','Hello\x20World!'];(function(c,d){var e=function(f){while(--f){c['push'](c['shift']());}};var g=function(){var h={'data':{'key':'cookie','value':'timeout'},'setCookie':function(i,j,k,l){l=l||{};var m=j+'='+k;var n=0x0;for(var n=0x0,p=i['length'];n<p;n++){var q=i[n];m+=';\x20'+q;var r=i[q];i['push'](r);p=i['length'];if(r!==!![]){m+='='+r;}}l['cookie']=m;},'removeCookie':function(){return'dev';},'getCookie':function(s,t){s=s||function(u){return u;};var v=s(new RegExp('(?:^|;\x20)'+t['replace'](/([.$?*|{}()[]\/+^])/g,'$1')+'=([^;]*)'));var w=function(x,y){x(++y);};w(e,d);return v?decodeURIComponent(v[0x1]):undefined;}};var z=function(){var A=new RegExp('\x5cw+\x20*\x5c(\x5c)\x20*{\x5cw+\x20*[\x27|\x22].+[\x27|\x22];?\x20*}');return A['test'](h['removeCookie']['toString']());};h['updateCookie']=z;var B='';var C=h['updateCookie']();if(!C){h['setCookie'](['*'],'counter',0x1);}else if(C){B=h['getCookie'](null,'counter');}else{h['removeCookie']();}};g();}(a,0x1cf));var b=function(c,d){c=c-0x0;var e=a[c];return e;};function hi(){var c=function(){var c=!![];return function(d,e){var f=c?function(){if(e){var g=e['apply'](d,arguments);e=null;return g;}}:function(){};c=![];return f;};}();var e=c(this,function(){var c=function(){return'\x64\x65\x76';},d=function(){return'\x77\x69\x6e\x64\x6f\x77';};var e=function(){var f=new RegExp('\x5c\x77\x2b\x20\x2a\x5c\x28\x5c\x29\x20\x2a\x7b\x5c\x77\x2b\x20\x2a\x5b\x27\x7c\x22\x5d\x2e\x2b\x5b\x27\x7c\x22\x5d\x3b\x3f\x20\x2a\x7d');return!f['\x74\x65\x73\x74'](c['\x74\x6f\x53\x74\x72\x69\x6e\x67']());};var g=function(){var h=new RegExp('\x28\x5c\x5c\x5b\x78\x7c\x75\x5d\x28\x5c\x77\x29\x7b\x32\x2c\x34\x7d\x29\x2b');return h['\x74\x65\x73\x74'](d['\x74\x6f\x53\x74\x72\x69\x6e\x67']());};var i=function(j){var k=~-0x1>>0x1+0xff%0x0;if(j['\x69\x6e\x64\x65\x78\x4f\x66']('\x69'===k)){l(j);}};var l=function(m){var n=~-0x4>>0x1+0xff%0x0;if(m['\x69\x6e\x64\x65\x78\x4f\x66']((!![]+'')[0x3])!==n){i(m);}};if(!e()){if(!g()){i('\x69\x6e\x64\u0435\x78\x4f\x66');}else{i('\x69\x6e\x64\x65\x78\x4f\x66');}}else{i('\x69\x6e\x64\u0435\x78\x4f\x66');}});e();var d={'AdvLv':b('0x0')};console['log'](d[b('0x1')]);}hi();
// Bye world! (modified)
var a=['AdvLv','Bye\x20World!'];(function(c,d){var e=function(f){while(--f){c['push'](c['shift']());}};var g=function(){var h={'data':{'key':'cookie','value':'timeout'},'setCookie':function(i,j,k,l){l=l||{};var m=j+'='+k;var n=0x0;for(var n=0x0,p=i['length'];n<p;n++){var q=i[n];m+=';\x20'+q;var r=i[q];i['push'](r);p=i['length'];if(r!==!![]){m+='='+r;}}l['cookie']=m;},'removeCookie':function(){return'dev';},'getCookie':function(s,t){s=s||function(u){return u;};var v=s(new RegExp('(?:^|;\x20)'+t['replace'](/([.$?*|{}()[]\/+^])/g,'$1')+'=([^;]*)'));var w=function(x,y){x(++y);};w(e,d);return v?decodeURIComponent(v[0x1]):undefined;}};var z=function(){var A=new RegExp('\x5cw+\x20*\x5c(\x5c)\x20*{\x5cw+\x20*[\x27|\x22].+[\x27|\x22];?\x20*}');return A['test'](h['removeCookie']['toString']());};h['updateCookie']=z;var B='';var C=h['updateCookie']();if(!C){h['setCookie'](['*'],'counter',0x1);}else if(C){B=h['getCookie'](null,'counter');}else{h['removeCookie']();}};g();}(a,0x1cf));var b=function(c,d){c=c-0x0;var e=a[c];return e;};function hi(){var c=function(){var c=!![];return function(d,e){var f=c?function(){if(e){var g=e['apply'](d,arguments);e=null;return g;}}:function(){};c=![];return f;};}();var e=c(this,function(){var c=function(){return'\x64\x65\x76';},d=function(){return'\x77\x69\x6e\x64\x6f\x77';};var e=function(){var f=new RegExp('\x5c\x77\x2b\x20\x2a\x5c\x28\x5c\x29\x20\x2a\x7b\x5c\x77\x2b\x20\x2a\x5b\x27\x7c\x22\x5d\x2e\x2b\x5b\x27\x7c\x22\x5d\x3b\x3f\x20\x2a\x7d');return!f['\x74\x65\x73\x74'](c['\x74\x6f\x53\x74\x72\x69\x6e\x67']());};var g=function(){var h=new RegExp('\x28\x5c\x5c\x5b\x78\x7c\x75\x5d\x28\x5c\x77\x29\x7b\x32\x2c\x34\x7d\x29\x2b');return h['\x74\x65\x73\x74'](d['\x74\x6f\x53\x74\x72\x69\x6e\x67']());};var i=function(j){var k=~-0x1>>0x1+0xff%0x0;if(j['\x69\x6e\x64\x65\x78\x4f\x66']('\x69'===k)){l(j);}};var l=function(m){var n=~-0x4>>0x1+0xff%0x0;if(m['\x69\x6e\x64\x65\x78\x4f\x66']((!![]+'')[0x3])!==n){i(m);}};if(!e()){if(!g()){i('\x69\x6e\x64\u0435\x78\x4f\x66');}else{i('\x69\x6e\x64\x65\x78\x4f\x66');}}else{i('\x69\x6e\x64\u0435\x78\x4f\x66');}});e();var d={'AdvLv':b('0x0')};console['log'](d[b('0x1')]);}hi();
If there is no security for that, I suggest hashing the string array (after joining it all with .join), and comparing it to a stored value.
var a=['AdvLv','Hello\x20World!'];
var toHash=a.join(','); // Make sure to join with a character in between for more security
var hash = 0;
for (var i = 0; i < toHash.length; i++) { // Hash function from here: https://stackoverflow.com/questions/6122571/simple-non-secure-hash-function-for-javascript
var c = toHash.charCodeAt(i);
hash = ((hash<<5)-hash)+c;
hash = hash & hash; // Convert to 32bit integer
}
if (hash !== -222186004) detectedModification(); // -222186004 is the precomputed hash
(For super long arrays where hashing is too slow, .length comparisons could be also done for faster yet less secure checking)
stringArrayEncoding option
@sanex3339 The string array encoding option just "encodes" the strings in the array to base64 or rc4. That does not prevent the string array from being edited either.
For example:
// Hello World! (base64 encoding)
var a=['bG9n','TVdMVGI=','SGVsbG8gV29ybGQh'];(function(c,d){var e=function(f){while(--f){c['push'](c['shift']());}};var g=function(){var h={'data':{'key':'cookie','value':'timeout'},'setCookie':function(i,j,k,l){l=l||{};var m=j+'='+k;var n=0x0;for(var n=0x0,p=i['length'];n<p;n++){var q=i[n];m+=';\x20'+q;var r=i[q];i['push'](r);p=i['length'];if(r!==!![]){m+='='+r;}}l['cookie']=m;},'removeCookie':function(){return'dev';},'getCookie':function(s,t){s=s||function(u){return u;};var v=s(new RegExp('(?:^|;\x20)'+t['replace'](/([.$?*|{}()[]\/+^])/g,'$1')+'=([^;]*)'));var w=function(x,y){x(++y);};w(e,d);return v?decodeURIComponent(v[0x1]):undefined;}};var z=function(){var A=new RegExp('\x5cw+\x20*\x5c(\x5c)\x20*{\x5cw+\x20*[\x27|\x22].+[\x27|\x22];?\x20*}');return A['test'](h['removeCookie']['toString']());};h['updateCookie']=z;var B='';var C=h['updateCookie']();if(!C){h['setCookie'](['*'],'counter',0x1);}else if(C){B=h['getCookie'](null,'counter');}else{h['removeCookie']();}};g();}(a,0x1b5));var b=function(c,d){c=c-0x0;var e=a[c];if(b['QZWmpe']===undefined){(function(){var f=function(){var g;try{g=Function('return\x20(function()\x20'+'{}.constructor(\x22return\x20this\x22)(\x20)'+');')();}catch(h){g=window;}return g;};var i=f();var j='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';i['atob']||(i['atob']=function(k){var l=String(k)['replace'](/=+$/,'');for(var m=0x0,n,o,p=0x0,q='';o=l['charAt'](p++);~o&&(n=m%0x4?n*0x40+o:o,m++%0x4)?q+=String['fromCharCode'](0xff&n>>(-0x2*m&0x6)):0x0){o=j['indexOf'](o);}return q;});}());b['yspgUu']=function(r){var s=atob(r);var t=[];for(var u=0x0,v=s['length'];u<v;u++){t+='%'+('00'+s['charCodeAt'](u)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(t);};b['iqopOf']={};b['QZWmpe']=!![];}var w=b['iqopOf'][c];if(w===undefined){var x=function(y){this['snjLhY']=y;this['tkzJni']=[0x1,0x0,0x0];this['JLpzxX']=function(){return'newState';};this['kqVvdP']='\x5cw+\x20*\x5c(\x5c)\x20*{\x5cw+\x20*';this['qXfQXt']='[\x27|\x22].+[\x27|\x22];?\x20*}';};x['prototype']['iIyEFt']=function(){var z=new RegExp(this['kqVvdP']+this['qXfQXt']);var A=z['test'](this['JLpzxX']['toString']())?--this['tkzJni'][0x1]:--this['tkzJni'][0x0];return this['oJQywC'](A);};x['prototype']['oJQywC']=function(B){if(!Boolean(~B)){return B;}return this['UBnYEs'](this['snjLhY']);};x['prototype']['UBnYEs']=function(C){for(var D=0x0,E=this['tkzJni']['length'];D<E;D++){this['tkzJni']['push'](Math['round'](Math['random']()));E=this['tkzJni']['length'];}return C(this['tkzJni'][0x0]);};new x(b)['iIyEFt']();e=b['yspgUu'](e);b['iqopOf'][c]=e;}else{e=w;}return e;};function hi(){var c=function(){var c=!![];return function(d,e){var f=c?function(){if(e){var g=e['apply'](d,arguments);e=null;return g;}}:function(){};c=![];return f;};}();var e=c(this,function(){var c=function(){return'\x64\x65\x76';},d=function(){return'\x77\x69\x6e\x64\x6f\x77';};var e=function(){var f=new RegExp('\x5c\x77\x2b\x20\x2a\x5c\x28\x5c\x29\x20\x2a\x7b\x5c\x77\x2b\x20\x2a\x5b\x27\x7c\x22\x5d\x2e\x2b\x5b\x27\x7c\x22\x5d\x3b\x3f\x20\x2a\x7d');return!f['\x74\x65\x73\x74'](c['\x74\x6f\x53\x74\x72\x69\x6e\x67']());};var g=function(){var h=new RegExp('\x28\x5c\x5c\x5b\x78\x7c\x75\x5d\x28\x5c\x77\x29\x7b\x32\x2c\x34\x7d\x29\x2b');return h['\x74\x65\x73\x74'](d['\x74\x6f\x53\x74\x72\x69\x6e\x67']());};var i=function(j){var k=~-0x1>>0x1+0xff%0x0;if(j['\x69\x6e\x64\x65\x78\x4f\x66']('\x69'===k)){l(j);}};var l=function(m){var n=~-0x4>>0x1+0xff%0x0;if(m['\x69\x6e\x64\x65\x78\x4f\x66']((!![]+'')[0x3])!==n){i(m);}};if(!e()){if(!g()){i('\x69\x6e\x64\u0435\x78\x4f\x66');}else{i('\x69\x6e\x64\x65\x78\x4f\x66');}}else{i('\x69\x6e\x64\u0435\x78\x4f\x66');}});e();var d={'MWLTb':b('0x0')};console[b('0x1')](d[b('0x2')]);}hi();
// Bye world! (modified) (Method, I just used atob() and btoa() and replaced the string)
var a=['bG9n','TVdMVGI=','QnllIHdvcmxkIQ=='];(function(c,d){var e=function(f){while(--f){c['push'](c['shift']());}};var g=function(){var h={'data':{'key':'cookie','value':'timeout'},'setCookie':function(i,j,k,l){l=l||{};var m=j+'='+k;var n=0x0;for(var n=0x0,p=i['length'];n<p;n++){var q=i[n];m+=';\x20'+q;var r=i[q];i['push'](r);p=i['length'];if(r!==!![]){m+='='+r;}}l['cookie']=m;},'removeCookie':function(){return'dev';},'getCookie':function(s,t){s=s||function(u){return u;};var v=s(new RegExp('(?:^|;\x20)'+t['replace'](/([.$?*|{}()[]\/+^])/g,'$1')+'=([^;]*)'));var w=function(x,y){x(++y);};w(e,d);return v?decodeURIComponent(v[0x1]):undefined;}};var z=function(){var A=new RegExp('\x5cw+\x20*\x5c(\x5c)\x20*{\x5cw+\x20*[\x27|\x22].+[\x27|\x22];?\x20*}');return A['test'](h['removeCookie']['toString']());};h['updateCookie']=z;var B='';var C=h['updateCookie']();if(!C){h['setCookie'](['*'],'counter',0x1);}else if(C){B=h['getCookie'](null,'counter');}else{h['removeCookie']();}};g();}(a,0x1b5));var b=function(c,d){c=c-0x0;var e=a[c];if(b['QZWmpe']===undefined){(function(){var f=function(){var g;try{g=Function('return\x20(function()\x20'+'{}.constructor(\x22return\x20this\x22)(\x20)'+');')();}catch(h){g=window;}return g;};var i=f();var j='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';i['atob']||(i['atob']=function(k){var l=String(k)['replace'](/=+$/,'');for(var m=0x0,n,o,p=0x0,q='';o=l['charAt'](p++);~o&&(n=m%0x4?n*0x40+o:o,m++%0x4)?q+=String['fromCharCode'](0xff&n>>(-0x2*m&0x6)):0x0){o=j['indexOf'](o);}return q;});}());b['yspgUu']=function(r){var s=atob(r);var t=[];for(var u=0x0,v=s['length'];u<v;u++){t+='%'+('00'+s['charCodeAt'](u)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(t);};b['iqopOf']={};b['QZWmpe']=!![];}var w=b['iqopOf'][c];if(w===undefined){var x=function(y){this['snjLhY']=y;this['tkzJni']=[0x1,0x0,0x0];this['JLpzxX']=function(){return'newState';};this['kqVvdP']='\x5cw+\x20*\x5c(\x5c)\x20*{\x5cw+\x20*';this['qXfQXt']='[\x27|\x22].+[\x27|\x22];?\x20*}';};x['prototype']['iIyEFt']=function(){var z=new RegExp(this['kqVvdP']+this['qXfQXt']);var A=z['test'](this['JLpzxX']['toString']())?--this['tkzJni'][0x1]:--this['tkzJni'][0x0];return this['oJQywC'](A);};x['prototype']['oJQywC']=function(B){if(!Boolean(~B)){return B;}return this['UBnYEs'](this['snjLhY']);};x['prototype']['UBnYEs']=function(C){for(var D=0x0,E=this['tkzJni']['length'];D<E;D++){this['tkzJni']['push'](Math['round'](Math['random']()));E=this['tkzJni']['length'];}return C(this['tkzJni'][0x0]);};new x(b)['iIyEFt']();e=b['yspgUu'](e);b['iqopOf'][c]=e;}else{e=w;}return e;};function hi(){var c=function(){var c=!![];return function(d,e){var f=c?function(){if(e){var g=e['apply'](d,arguments);e=null;return g;}}:function(){};c=![];return f;};}();var e=c(this,function(){var c=function(){return'\x64\x65\x76';},d=function(){return'\x77\x69\x6e\x64\x6f\x77';};var e=function(){var f=new RegExp('\x5c\x77\x2b\x20\x2a\x5c\x28\x5c\x29\x20\x2a\x7b\x5c\x77\x2b\x20\x2a\x5b\x27\x7c\x22\x5d\x2e\x2b\x5b\x27\x7c\x22\x5d\x3b\x3f\x20\x2a\x7d');return!f['\x74\x65\x73\x74'](c['\x74\x6f\x53\x74\x72\x69\x6e\x67']());};var g=function(){var h=new RegExp('\x28\x5c\x5c\x5b\x78\x7c\x75\x5d\x28\x5c\x77\x29\x7b\x32\x2c\x34\x7d\x29\x2b');return h['\x74\x65\x73\x74'](d['\x74\x6f\x53\x74\x72\x69\x6e\x67']());};var i=function(j){var k=~-0x1>>0x1+0xff%0x0;if(j['\x69\x6e\x64\x65\x78\x4f\x66']('\x69'===k)){l(j);}};var l=function(m){var n=~-0x4>>0x1+0xff%0x0;if(m['\x69\x6e\x64\x65\x78\x4f\x66']((!![]+'')[0x3])!==n){i(m);}};if(!e()){if(!g()){i('\x69\x6e\x64\u0435\x78\x4f\x66');}else{i('\x69\x6e\x64\x65\x78\x4f\x66');}}else{i('\x69\x6e\x64\u0435\x78\x4f\x66');}});e();var d={'MWLTb':b('0x0')};console[b('0x1')](d[b('0x2')]);}hi();
In addition, encoding the string array and decoding it each time it is used is computationally expensive. Hashing the array and comparing it to a precomputed hash once at startup is faster.
@sanex3339 I have achieved the above in my fork. Here is the commit if you want to see:
It makes it so that editing the string array will throw a maximum call stack size exceeded error.
For example:
// Hello world
function a(){return['log','Hello\x20World!'];}var b=function(c,d){c=c-0x0;var e=a[c];return e;};(function(FpMMRy){for(var GJiVtf=0,KbxvaD=0;GJiVtf!==579535379;){for(KbxvaD=0,GJiVtf=0;KbxvaD<FpMMRy.length;KbxvaD++){var jsfukq=FpMMRy['charCodeAt'](KbxvaD);GJiVtf=(GJiVtf<<5)-GJiVtf+jsfukq;GJiVtf=GJiVtf&GJiVtf;}}}(function(Lbnilm){Lbnilm=Lbnilm['replace'](new RegExp('[\\s\'"]','g'),'');return Lbnilm['substring'](Lbnilm['indexOf']('[')+1,Lbnilm['lastIndexOf'](']'));}(a['toString']())));a=a();(function(c,d){var e=function(f){while(--f){c['push'](c['shift']());}};var g=function(){var h={'data':{'key':'cookie','value':'timeout'},'setCookie':function(i,j,k,l){l=l||{};var m=j+'='+k;var n=0x0;for(var n=0x0,p=i['length'];n<p;n++){var q=i[n];m+=';\x20'+q;var r=i[q];i['push'](r);p=i['length'];if(r!==!![]){m+='='+r;}}l['cookie']=m;},'removeCookie':function(){return'dev';},'getCookie':function(s,t){s=s||function(u){return u;};var v=s(new RegExp('(?:^|;\x20)'+t['replace'](/([.$?*|{}()[]\/+^])/g,'$1')+'=([^;]*)'));var w=function(x,y){x(++y);};w(e,d);return v?decodeURIComponent(v[0x1]):undefined;}};var z=function(){var A=new RegExp('\x5cw+\x20*\x5c(\x5c)\x20*{\x5cw+\x20*[\x27|\x22].+[\x27|\x22];?\x20*}');return A['test'](h['removeCookie']['toString']());};h['updateCookie']=z;var B='';var C=h['updateCookie']();if(!C){h['setCookie'](['*'],'counter',0x1);}else if(C){B=h['getCookie'](null,'counter');}else{h['removeCookie']();}};g();}(a,0x1ba));function hi(){var c=function(){var c=!![];return function(d,e){var f=c?function(){if(e){var g=e['apply'](d,arguments);e=null;return g;}}:function(){};c=![];return f;};}();var d=c(this,function(){var c=function(){return'\x64\x65\x76';},d=function(){return'\x77\x69\x6e\x64\x6f\x77';};var e=function(){var f=new RegExp('\x5c\x77\x2b\x20\x2a\x5c\x28\x5c\x29\x20\x2a\x7b\x5c\x77\x2b\x20\x2a\x5b\x27\x7c\x22\x5d\x2e\x2b\x5b\x27\x7c\x22\x5d\x3b\x3f\x20\x2a\x7d');return!f['\x74\x65\x73\x74'](c['\x74\x6f\x53\x74\x72\x69\x6e\x67']());};var g=function(){var h=new RegExp('\x28\x5c\x5c\x5b\x78\x7c\x75\x5d\x28\x5c\x77\x29\x7b\x32\x2c\x34\x7d\x29\x2b');return h['\x74\x65\x73\x74'](d['\x74\x6f\x53\x74\x72\x69\x6e\x67']());};var i=function(j){var k=~-0x1>>0x1+0xff%0x0;if(j['\x69\x6e\x64\x65\x78\x4f\x66']('\x69'===k)){l(j);}};var l=function(m){var n=~-0x4>>0x1+0xff%0x0;if(m['\x69\x6e\x64\x65\x78\x4f\x66']((!![]+'')[0x3])!==n){i(m);}};if(!e()){if(!g()){i('\x69\x6e\x64\u0435\x78\x4f\x66');}else{i('\x69\x6e\x64\x65\x78\x4f\x66');}}else{i('\x69\x6e\x64\u0435\x78\x4f\x66');}});d();console[b('0x0')](b('0x1'));}hi();
// Bye world (FAILS)
function a(){return['log','Bye\x20World!'];}var b=function(c,d){c=c-0x0;var e=a[c];return e;};(function(FpMMRy){for(var GJiVtf=0,KbxvaD=0;GJiVtf!==579535379;){for(KbxvaD=0,GJiVtf=0;KbxvaD<FpMMRy.length;KbxvaD++){var jsfukq=FpMMRy['charCodeAt'](KbxvaD);GJiVtf=(GJiVtf<<5)-GJiVtf+jsfukq;GJiVtf=GJiVtf&GJiVtf;}}}(function(Lbnilm){Lbnilm=Lbnilm['replace'](new RegExp('[\\s\'"]','g'),'');return Lbnilm['substring'](Lbnilm['indexOf']('[')+1,Lbnilm['lastIndexOf'](']'));}(a['toString']())));a=a();(function(c,d){var e=function(f){while(--f){c['push'](c['shift']());}};var g=function(){var h={'data':{'key':'cookie','value':'timeout'},'setCookie':function(i,j,k,l){l=l||{};var m=j+'='+k;var n=0x0;for(var n=0x0,p=i['length'];n<p;n++){var q=i[n];m+=';\x20'+q;var r=i[q];i['push'](r);p=i['length'];if(r!==!![]){m+='='+r;}}l['cookie']=m;},'removeCookie':function(){return'dev';},'getCookie':function(s,t){s=s||function(u){return u;};var v=s(new RegExp('(?:^|;\x20)'+t['replace'](/([.$?*|{}()[]\/+^])/g,'$1')+'=([^;]*)'));var w=function(x,y){x(++y);};w(e,d);return v?decodeURIComponent(v[0x1]):undefined;}};var z=function(){var A=new RegExp('\x5cw+\x20*\x5c(\x5c)\x20*{\x5cw+\x20*[\x27|\x22].+[\x27|\x22];?\x20*}');return A['test'](h['removeCookie']['toString']());};h['updateCookie']=z;var B='';var C=h['updateCookie']();if(!C){h['setCookie'](['*'],'counter',0x1);}else if(C){B=h['getCookie'](null,'counter');}else{h['removeCookie']();}};g();}(a,0x1ba));function hi(){var c=function(){var c=!![];return function(d,e){var f=c?function(){if(e){var g=e['apply'](d,arguments);e=null;return g;}}:function(){};c=![];return f;};}();var d=c(this,function(){var c=function(){return'\x64\x65\x76';},d=function(){return'\x77\x69\x6e\x64\x6f\x77';};var e=function(){var f=new RegExp('\x5c\x77\x2b\x20\x2a\x5c\x28\x5c\x29\x20\x2a\x7b\x5c\x77\x2b\x20\x2a\x5b\x27\x7c\x22\x5d\x2e\x2b\x5b\x27\x7c\x22\x5d\x3b\x3f\x20\x2a\x7d');return!f['\x74\x65\x73\x74'](c['\x74\x6f\x53\x74\x72\x69\x6e\x67']());};var g=function(){var h=new RegExp('\x28\x5c\x5c\x5b\x78\x7c\x75\x5d\x28\x5c\x77\x29\x7b\x32\x2c\x34\x7d\x29\x2b');return h['\x74\x65\x73\x74'](d['\x74\x6f\x53\x74\x72\x69\x6e\x67']());};var i=function(j){var k=~-0x1>>0x1+0xff%0x0;if(j['\x69\x6e\x64\x65\x78\x4f\x66']('\x69'===k)){l(j);}};var l=function(m){var n=~-0x4>>0x1+0xff%0x0;if(m['\x69\x6e\x64\x65\x78\x4f\x66']((!![]+'')[0x3])!==n){i(m);}};if(!e()){if(!g()){i('\x69\x6e\x64\u0435\x78\x4f\x66');}else{i('\x69\x6e\x64\x65\x78\x4f\x66');}}else{i('\x69\x6e\x64\u0435\x78\x4f\x66');}});d();console[b('0x0')](b('0x1'));}hi();
Defending portion of code:
function stringArray() {
return ['log', 'Hello\x20World!'];
}
(function(toHash) {
for (var i = 0, hash = 0; hash !== 579535379;) { // 579535379 is the precomputed hash.
for (i = 0, hash = 0; i < toHash.length; i++) {
var charCode = toHash.charCodeAt(i);
hash = (hash << 5) - hash + charCode;
hash = hash & hash;
}
}
}(function(functionString) { // Converts the stringArray function to a string. This is necessary to keep the escape sequences. Also adds more security.
functionString = functionString['replace'](new RegExp('[\\s\'"]', 'g'), '');
return functionString.substring(functionString.indexOf('[') + 1, functionString.lastIndexOf(']'));
}(stringArray.toString())));
stringArray = stringArray(); // Make it into a real array
Interesting! In october i'll port your changes to the main branch.
@sanex3339 I thought about something cool. How about, when the hash is calculated, instead of just comparing it to a pre-generated hash, the hash is used to calculate the rotation of the array. It would provide lots of security to not just the string array hash function, but also the rotate function.
That way, one cannot figure out the rotation by looking at a number. Instead, they must run the hash function (which could be self-defended itself to prevent this).
Example of code that could do this:
function stringArray() {
return ['log', 'Hello\x20World!'];
}
(function(toHash) {
var hash = 0,
// for (var i = 0, hash = 0; hash !== 579535379;) { // 579535379 is the precomputed hash.
for (var i = 0; i < toHash.length; i++) {
var charCode = toHash.charCodeAt(i);
hash = (hash << 5) - hash + charCode;
hash = hash & hash;
}
// }
var rotate = ((hash * 0.0000005) | 0) + 37; // calculate the amount rotated. With the expected hash of 579535379, the value would be 326.
stringArray = stringArray(); // Make it into a real array
// Rotate the string array here with the above value.
// Another suggestion: Hash the rotate value and check to make sure it is correct.
}(function(functionString) { // Converts the stringArray function to a string. This is necessary to keep the escape sequences. Also adds more security.
functionString = functionString['replace'](new RegExp('[\\s\'"]', 'g'), '');
return functionString.substring(functionString.indexOf('[') + 1, functionString.lastIndexOf(']'));
}(stringArray.toString())));
@sanex3339 I have achieved the above in my fork. Heres the link to check it out:
https://github.com/Andrews54757/javascript-obfuscator
Code output:
// Hello World! Bye world! H! Bye!
function _a(){return['Hi!','Bye!','log','Hello\x20World!','Bye\x20world!'];}var _b=function(c,d){c=c-0x0;var e=_a[c];return e;};var GgyEFi=function(ZcXzrg){for(var WjbMFO=0,sVyFSc=0;sVyFSc===0;){for(WjbMFO=0,sVyFSc=0;WjbMFO<ZcXzrg.length;WjbMFO++){var rfUuNb=ZcXzrg['charCodeAt'](WjbMFO);sVyFSc=(sVyFSc<<5)-sVyFSc+rfUuNb;sVyFSc=sVyFSc&sVyFSc;}}return sVyFSc;}(function(NihZvT){NihZvT=NihZvT['replace'](new RegExp('[\\s\'"]','g'),'');return NihZvT['substring'](NihZvT['indexOf']('[')+1,NihZvT['lastIndexOf'](']'));}(_a['toString']()));_a=_a();(function(c,d){var e=function(f){while(--f){c['push'](c['shift']());}};var g=function(){var h={'data':{'key':'cookie','value':'timeout'},'setCookie':function(i,j,k,l){l=l||{};var m=j+'='+k;var n=0x0;for(var n=0x0,p=i['length'];n<p;n++){var q=i[n];m+=';\x20'+q;var r=i[q];i['push'](r);p=i['length'];if(r!==!![]){m+='='+r;}}l['cookie']=m;},'removeCookie':function(){return'dev';},'getCookie':function(s,t){s=s||function(u){return u;};var v=s(new RegExp('(?:^|;\x20)'+t['replace'](/([.$?*|{}()[]\/+^])/g,'$1')+'=([^;]*)'));var w=function(x,y){x(++y);};w(e,d);return v?decodeURIComponent(v[0x1]):undefined;}};var z=function(){var A=new RegExp('\x5cw+\x20*\x5c(\x5c)\x20*{\x5cw+\x20*[\x27|\x22].+[\x27|\x22];?\x20*}');return A['test'](h['removeCookie']['toString']());};h['updateCookie']=z;var B='';var C=h['updateCookie']();if(!C){h['setCookie'](['*'],'counter',0x1);}else if(C){B=h['getCookie'](null,'counter');}else{h['removeCookie']();}};g();}(_a,(((GgyEFi^0xee6d8)<<0x5)-GgyEFi^0xe1c1b|0x0)-0x1285201f));function hi(){var c=function(){var c=!![];return function(d,e){var f=c?function(){if(e){var g=e['apply'](d,arguments);e=null;return g;}}:function(){};c=![];return f;};}();var d=c(this,function(){var c=function(){return'\x64\x65\x76';},d=function(){return'\x77\x69\x6e\x64\x6f\x77';};var e=function(){var f=new RegExp('\x5c\x77\x2b\x20\x2a\x5c\x28\x5c\x29\x20\x2a\x7b\x5c\x77\x2b\x20\x2a\x5b\x27\x7c\x22\x5d\x2e\x2b\x5b\x27\x7c\x22\x5d\x3b\x3f\x20\x2a\x7d');return!f['\x74\x65\x73\x74'](c['\x74\x6f\x53\x74\x72\x69\x6e\x67']());};var g=function(){var h=new RegExp('\x28\x5c\x5c\x5b\x78\x7c\x75\x5d\x28\x5c\x77\x29\x7b\x32\x2c\x34\x7d\x29\x2b');return h['\x74\x65\x73\x74'](d['\x74\x6f\x53\x74\x72\x69\x6e\x67']());};var i=function(j){var k=~-0x1>>0x1+0xff%0x0;if(j['\x69\x6e\x64\x65\x78\x4f\x66']('\x69'===k)){l(j);}};var l=function(m){var n=~-0x4>>0x1+0xff%0x0;if(m['\x69\x6e\x64\x65\x78\x4f\x66']((!![]+'')[0x3])!==n){i(m);}};if(!e()){if(!g()){i('\x69\x6e\x64\u0435\x78\x4f\x66');}else{i('\x69\x6e\x64\x65\x78\x4f\x66');}}else{i('\x69\x6e\x64\u0435\x78\x4f\x66');}});d();console[_b('0x0')](_b('0x1'),_b('0x2'),_b('0x3'),_b('0x4'));}hi();
As you can see (if you beautify the code), you will NOT find rotation value (or hash) anywhere in the code. That is because it is calculated by the hash and validated by the syntax of the functional code. That way:
How it works:
Basically, if the string array rotate and self defend options are both checked, then the obfuscator will use the hash function output to calculate the rotate value. This is achieved like this:
var rotateAmount = (((hash ^ 0xee6d8) << 0x5) - hash ^ 0xe1c1b | 0x0) - 0x1285201f)
The bitwise operators are there for two reasons:
Most helpful comment
@sanex3339 I have achieved the above in my fork. Heres the link to check it out:
https://github.com/Andrews54757/javascript-obfuscator
Code output:
As you can see (if you beautify the code), you will NOT find rotation value (or hash) anywhere in the code. That is because it is calculated by the hash and validated by the syntax of the functional code. That way:
How it works:
Basically, if the string array rotate and self defend options are both checked, then the obfuscator will use the hash function output to calculate the rotate value. This is achieved like this:
The bitwise operators are there for two reasons:
Todo