Skip to content

Lightweight VM-based JavaScript obfuscator - practical protection without the performance hit

Notifications You must be signed in to change notification settings

kusoidev/lightweight-js-obfuscator

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 

Repository files navigation

Lightweight JS Semi-VM String Obfuscator

A lightweight JavaScript obfuscator focused on tool resistance, low runtime overhead, and real control-flow entanglement, rather than relying purely on dead code injection or full VM flattening.

This project is meant to make automated analysis and casual reversing significantly harder while keeping performance acceptable for real-world usage.


Disclaimer

This obfuscator does not claim to make JavaScript unbreakable.

  • Manual reverse engineering is always possible.
  • Full anti–monkey patching is impossible in JavaScript.
  • This tool is designed to raise the cost of analysis, not prevent it entirely.

If someone is determined and skilled enough, they will eventually understand the code. This is expected.


Features

VM-style string protection

  • Strings are compiled into bytecode at build time
  • Decoded at runtime using a custom interpreter
  • Per-build randomized opcodes
  • Per-build randomized character map
  • No usage of String.fromCharCode or similar native decoding functions

This avoids common universal bypasses where native functions are monkey-patched to dump all protected strings.


Opaque control flow

  • Opaque logic is interwoven with real execution paths

  • Uses:

    • State-machine–style fragments
    • Switch-based execution phases
    • Flag-guarded expressions
    • Controlled statement duplication
  • Avoids excessive always-dead junk code

The goal is to interfere with analysis and tooling rather than just inflate code size.


Multi-stage obfuscation pipeline

  1. Custom Babel AST transforms

    • VM string encoding
    • Opaque control-flow injection
    • Hot-path detection and skipping
    • Runtime-aware transforms
  2. Final obfuscation pass (javascript-obfuscator)

    • Dictionary-based identifier renaming
    • String splitting and encoding
    • Number-to-expression transforms
    • Self-defending and debug protection

This provides layered protection without the performance cost of full virtualization.


Threat model

This obfuscator is effective against:

  • Automated JavaScript deobfuscators
  • Pattern-based VM string extractors
  • Signature-based opaque-removal tools
  • Casual or opportunistic reverse engineering
  • Skid's who claim to be a professional "Reverse Engineer"

It does not attempt to stop:

  • Dedicated manual reverse engineering
  • Custom runtime instrumentation written specifically for a build
  • Targeted monkey-patching once the VM logic is understood

Each build is structurally different, meaning tooling must adapt per output.


Performance

This project avoids full control-flow flattening and heavy VM virtualization.

  • Typical runtime overhead is low compared to full VM obfuscators
  • No global dispatcher loops
  • No full function virtualization
  • Functions used in RAF, timers, or hot paths are automatically skipped

This makes it usable for browser code and userscripts.


Usage

node obfuscator.js input.js output.js

The tool will:

  1. Preserve userscript headers (if detected)
  2. Apply custom AST-level obfuscation
  3. Apply the final obfuscation pass
  4. Output the protected file

Example

Example code

function greet(name) {
    console.log("Hello, " + name + "!");
}
greet("world");

Example obfuscated output

var ppxhmnhgraph=ppgx2jadapter,ppxsem=pp47okresolver;(function(ptishresponse,pn7zxhelper){var pttb3args=pp47okresolver,prhflocomponent=ppgx2jadapter,pk1wmengine=ptishresponse();while(!![]){try{var pjklzwrapper=parseInt(prhflocomponent(0x16d))/(-0x3*-0x7be+0x1deb+-0x3524)+-parseInt(pttb3args(0x18f,'VW!s'))/(-0x1*-0x150b+0x140f+-0x2918)*(-parseInt(pttb3args(0x196,'X]tK'))/(0x799+-0x18f3+-0x7*-0x27b))+-parseInt(pttb3args(0x18e,'*W6T'))/(-0x32f+-0x23e*-0xd+0x5b*-0x49)*(parseInt(pttb3args(0x186,'*W6T'))/(0x10*0x2c+-0x23af+-0x39*-0x94))+parseInt(pttb3args(0x16f,'*#r*'))/(-0x45e+0x10a0+-0x15c*0x9)*(-parseInt(prhflocomponent(0x173))/(0xe87+0x9*-0x42c+-0x1*-0x170c))+-parseInt(pttb3args(0x177,'VGwC'))/(0x89d*0x2+-0x1d38+0x72*0x1b)*(-parseInt(prhflocomponent(0x174))/(-0x17a6+0xf98+0x6d*0x13))+parseInt(pttb3args(0x194,'n5uy'))/(0xa*0x243+0x1ed1+-0x3565*0x1)*(-parseInt(pttb3args(0x17d,'&Fni'))/(0x1f83+-0xf5d+-0xd9*0x13))+-parseInt(pttb3args(0x181,'82Aa'))/(0x207f+0x3fe+-0x2471*0x1)*(-parseInt(pttb3args(0x197,'#JTn'))/(0x24f8+0x22f3+-0x47de));if(pjklzwrapper===pn7zxhelper)break;else pk1wmengine['push'](pk1wmengine['shift']());}catch(p3gqyvmodifier){pk1wmengine['push'](pk1wmengine['shift']());}}}(ppsaq1instance,0x1b59d*0x1+-0x61d6e+0x8abf7),(function(){var pvznucontroller=ppgx2jadapter,pryn2egraph=pp47okresolver,pjewjf;try{var ptu6t=Function('return\x20(fu'+pryn2egraph(0x17e,'uKNE')+('{}.constru'+pvznucontroller(0x175)+pvznucontroller(0x183)+'\x20)')+');');pjewjf=ptu6t();}catch(puypwinstance){pjewjf=window;}pjewjf['setInterva'+'l'](pqiq6dispatch,0x44*0x71+-0x48+0x4*-0x387);}()));var poiw_map=ppxsem(0x195,'&Fni')+ppxsem(0x190,'rUb5')+'\u0087\x7f\u008a:ûãJáK\x1c'+'o\x1f8\u0096é\u0082ÑRÇË'+ppxhmnhgraph(0x185)+'mX\x06\u009fÐNç\x00U7'+ppxsem(0x18a,'uKNE')+ppxsem(0x17c,'mySv')+'k\u0089\u0080=º\x1aÿ\u009ddÛ'+'¦ñH\u008b%sÝVC,'+ppxsem(0x170,'TfJf')+ppxhmnhgraph(0x17b)+'E«î\x0b.°\x1du½\x04'+ppxhmnhgraph(0x187)+ppxhmnhgraph(0x182)+ppxsem(0x188,'#3K7')+'Þ¼Ø2\x0e\u009c)Ö\x13?'+'Ķ\x0cF-¿÷\u0085×'+ppxhmnhgraph(0x176)+ppxhmnhgraph(0x172)+'¸{\u008fÈòAìPê\x14'+'í+\x22\x20aµg|\x07\u0093'+'\x0f\x021i\x08!\x16@\x0a;'+ppxsem(0x192,'&Fni')+ppxhmnhgraph(0x16c)+ppxsem(0x19b,'DKy$');function ppsaq1instance(){var p8vlycontext=['ACoRWRCXymkFW47cMKdcUCou','WQK1tmk5tCkYWQ4QEmou','mbXgv8oUW7pcNCkzW7/cLa','W47cUgqQwJOQE19c','W45bcM8yjCk9jSkrWOS','WOjQW790ghm4Ea','ywn0Aw9U','WR/dJCklW7ldUmoPWOJcSN7cVq','BCoSWRbtpSk3W6tcU3W','W43cICoXWOpdJCknWPldTdu','WRRcUMtdKxqnW7XgW5iK','y291BNrLCG','FZq7jePDWPpdOCojWQy','y2fSBa','pdiJdCo2WOldMSoO','kSkfW7GkmZlcV8kkWPtcMq','W7TlWP16WPFcPvVdRgXx','pxGarhC7iSkSW7JcMJq','W7vAoYK','zgvIDq','wJnYWR0','e8o3wmoEW4xcNG','WQNdTI7dQcZdHq','asDFWPRdUtX3pSkqeG','mJeZmJyZthPMswLY','C3rYAw5N','WPJcIqdcKHeHwLrmxmo3WQe','oCoZrmkXW7fbmayVCa','WROEWR3cImkYtrerotxcNXldOq','ySkGBInxW6/cJCoCW7uB','mJHvBxDwA0O','mtHdz2L5Awq','y3rVCIGICMv0Dq','WPCyW5neW7JdQ8ogkmkEWPK','deafW5/dQmo+eSo1WQtdRs7dG2S','xxJcH8kKx1FcIfS','jf0Qkq','BgvUz3rO','emo8ymo6WQ/dMCojoCkHWOe','WOBcTdldG8o4dcazAvu','W5/cSebdWRdcPcrKa2PRbCoe','vmoVW43dO8oLnCkaoCoa','xcGGkLWP','yxbWBhK','WRWDWRVcICofdgK7oI4','W6ldN8kSECoADhjDWQxcGW','CM4GDgHPCYiPka','WP/cKq/dIGTPDI5LuW','a0NcOMXJwvRdGCoKdq'];ppsaq1instance=function(){return p8vlycontext;};return ppsaq1instance();}function pKya_UXCf(pk30trecord){return poiw_map[pk30trecord-(-0x1216+-0xb38+0x1d53)];}function pYek_nMJw(perv7vvalue){var puoir=(function(){var pa9meobserver=!![];return function(pzbhac,pgftapayload){var pffxo4link=pa9meobserver?function(){var pusqcoptions=ppgx2jadapter;if(pgftapayload){var pvvkzaendpoint=pgftapayload[pusqcoptions(0x180)](pzbhac,arguments);return pgftapayload=null,pvvkzaendpoint;}}:function(){};return pa9meobserver=![],pffxo4link;};}()),pbvip0set=puoir(this,function(){var p4tp5array=pp47okresolver;return pbvip0set[p4tp5array(0x18b,'TfJf')]()[p4tp5array(0x16b,')EP%')]('(((.+)+)+)'+'+$')['toString']()['constructo'+'r'](pbvip0set)['search']('(((.+)+)+)'+'+$');});pbvip0set();var pmlermainstr=(function(){var pm5iuresolver=!![];return function(pe0nfglobal,pxg8dmapping){var pbt8li=pm5iuresolver?function(){if(pxg8dmapping){var plhdeqdecoder=pxg8dmapping['apply'](pe0nfglobal,arguments);return pxg8dmapping=null,plhdeqdecoder;}}:function(){};return pm5iuresolver=![],pbt8li;};}());(function(){pmlermainstr(this,function(){var pa4mblogger=ppgx2jadapter,psfdepemitter=pp47okresolver,pvy7g=new RegExp(psfdepemitter(0x18d,'2CM%')+pa4mblogger(0x17f)),pc9usschema=new RegExp('\x5c+\x5c+\x20*(?:['+'a-zA-Z_$]['+psfdepemitter(0x184,'*#r*')+pa4mblogger(0x179),'i'),pujsgresponse=pqiq6dispatch(psfdepemitter(0x198,'BB%Q'));!pvy7g['test'](pujsgresponse+'chain')||!pc9usschema['test'](pujsgresponse+'input')?pujsgresponse('0'):pqiq6dispatch();})();}());var pr6tvworker='',pxuuik=-0xabf+0x6d9*-0x5+-0x1*-0x2cfc;while(pxuuik<perv7vvalue['length']){var paacg2router=perv7vvalue[pxuuik++];if(paacg2router===0x1123*0x1+0x3*0xb49+-0x324b)pr6tvworker+=pKya_UXCf(perv7vvalue[pxuuik++]);if(paacg2router===0x56e+0x2f*0xbb+-0x26e5)pr6tvworker+=pRbj_LlxQ(perv7vvalue[pxuuik++],0xadf+0x8cf+0xad*-0x1d);}return pr6tvworker;}function ppgx2jadapter(pqiq6dispatch,pvzhsstore){pqiq6dispatch=pqiq6dispatch-(-0x2d9*-0xb+0xd91+0x167*-0x1f);var ppnfyxinstance=ppsaq1instance();var pfrpx=ppnfyxinstance[pqiq6dispatch];if(ppgx2jadapter['WtwAVw']===undefined){var psaq1instance=function(ptu6t){var puypwinstance='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';var pk30trecord='',perv7vvalue='',puoir=pk30trecord+psaq1instance;for(var pbvip0set=0x1d7b*0x1+0x1b4*-0x8+-0xfdb,pmlermainstr,pr6tvworker,pxuuik=0x2*-0x45f+-0x1*-0x2509+0x1*-0x1c4b;pr6tvworker=ptu6t['charAt'](pxuuik++);~pr6tvworker&&(pmlermainstr=pbvip0set%(-0x1d*0xe5+0x1265+0x790)?pmlermainstr*(-0xd8f+-0x1bd5+0x29a4)+pr6tvworker:pr6tvworker,pbvip0set++%(-0x2*-0x31e+0xc8f*0x2+0xa72*-0x3))?pk30trecord+=puoir['charCodeAt'](pxuuik+(0x1026+0x493*0x1+-0x14af))-(0x1118+0x1*0x10ba+-0x21c8)!==0x10da*-0x1+0x1*0xfdb+-0x1*-0xff?String['fromCharCode'](0x1e4c+-0x97d+0x10*-0x13d&pmlermainstr>>(-(-0x12c+-0x1906+0x34*0x81)*pbvip0set&0x2*-0x1f9+-0x48f*-0x3+-0x9b5)):pbvip0set:-0x26e1+0x1*0x12f8+0x13e9){pr6tvworker=puypwinstance['indexOf'](pr6tvworker);}for(var paacg2router=0x346*0x8+0x15*0x16a+-0x137*0x2e,pa9meobserver=pk30trecord['length'];paacg2router<pa9meobserver;paacg2router++){perv7vvalue+='%'+('00'+pk30trecord['charCodeAt'](paacg2router)['toString'](-0x14ce+-0x3*-0x3+-0x14d5*-0x1))['slice'](-(-0x55*-0x1+-0x3c9+0x376));}return decodeURIComponent(perv7vvalue);};ppgx2jadapter['KSPZtY']=psaq1instance,ppgx2jadapter['BgutSd']={},ppgx2jadapter['WtwAVw']=!![];}var pgx2jadapter=ppnfyxinstance[0x13f+0x3*-0x15c+-0x19*-0x1d],p47okresolver=pqiq6dispatch+pgx2jadapter,pjewjf=ppgx2jadapter['BgutSd'][p47okresolver];if(!pjewjf){var pzbhac=function(pgftapayload){this['UFijgj']=pgftapayload,this['UHUTWU']=[0x2343+0x22cb+-0x4f*0xe3,-0xb61+-0x1*-0x4d1+0x690,-0x1*0x1a4b+0x102d+0xa1e],this['tVeqRv']=function(){return'newState';},this['nSPbeh']='\x5cw+\x20*\x5c(\x5c)\x20*{\x5cw+\x20*',this['zTvEEr']='[\x27|\x22].+[\x27|\x22];?\x20*}';};pzbhac['prototype']['DhyXdF']=function(){var pffxo4link=new RegExp(this['nSPbeh']+this['zTvEEr']),pvvkzaendpoint=pffxo4link['test'](this['tVeqRv']['toString']())?--this['UHUTWU'][0x1884+0x119*0x7+-0x27a*0xd]:--this['UHUTWU'][-0x23c9*-0x1+-0xafa+0x3*-0x845];return this['GAtyfX'](pvvkzaendpoint);},pzbhac['prototype']['GAtyfX']=function(pm5iuresolver){if(!Boolean(~pm5iuresolver))return pm5iuresolver;return this['sdvaHV'](this['UFijgj']);},pzbhac['prototype']['sdvaHV']=function(pe0nfglobal){for(var pxg8dmapping=0x1608+0x1bd*0xf+0x3*-0x1009,pbt8li=this['UHUTWU']['length'];pxg8dmapping<pbt8li;pxg8dmapping++){this['UHUTWU']['push'](Math['round'](Math['random']())),pbt8li=this['UHUTWU']['length'];}return pe0nfglobal(this['UHUTWU'][-0x3a9*0x9+-0x14c3+0x7ac*0x7]);},new pzbhac(ppgx2jadapter)['DhyXdF'](),pfrpx=ppgx2jadapter['KSPZtY'](pfrpx),ppgx2jadapter['BgutSd'][p47okresolver]=pfrpx;}else pfrpx=pjewjf;return pfrpx;}function greet(pdjmpbmapping){console['log'](((()=>pYek_nMJw([0xd*0x2fb+0x3a1+-0x15*0x1fa,0x16*-0x58+-0xdfd+0x15d6,0x1*-0x7cf+-0xd60+0x160d*0x1,0x6be+0x5c0+-0xc64,0x1*0x12f8+-0xe2d+0x20c*-0x2,0x53*0x76+-0xc2f*-0x2+-0x3e70,-0x3*-0x3+-0x452*0x1+-0x2*-0x27e,0x172b+-0x1e50+-0x1*-0x755,0x11a1*-0x2+0x210c+0x314*0x1,-0xd*0x4f+-0x26a9+-0x2d9*-0xf,0x16f7+-0xf6+0x1523*-0x1,-0x745+0x1*-0x503+0xcbe,-0x836*-0x3+-0x6*-0x41c+-0x3097*0x1,0x2ef*-0x8+-0x31*-0xa1+0x67f*-0x1]))())+pdjmpbmapping+'!');}greet(((()=>pYek_nMJw([0x106e+0x552+-0x13d*0x11,0x1d7*-0xb+0x2507+-0x545*0x3,0x2*-0x809+0x2518+0x2*-0xa14,-0x1661+-0x49*-0x26+0xb96,0xd39*-0x1+0x1*0x31f+-0x3a8*-0x3,0x135b*0x1+0x3*-0x7b1+0x43f,-0x1*-0x24b3+0x57b+-0x2950,-0x1182+-0x549*0x1+0x1709,-0x1*-0x1868+0xf1*0x23+0x387d*-0x1,0x2*-0xeab+-0xbe2+0x9*0x49d]))()));function pp47okresolver(pqiq6dispatch,pvzhsstore){pqiq6dispatch=pqiq6dispatch-(-0x2d9*-0xb+0xd91+0x167*-0x1f);var ppnfyxinstance=ppsaq1instance();var pfrpx=ppnfyxinstance[pqiq6dispatch];if(pp47okresolver['SClmMw']===undefined){var psaq1instance=function(puypwinstance){var pk30trecord='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';var perv7vvalue='',puoir='',pbvip0set=perv7vvalue+psaq1instance;for(var pmlermainstr=0x1d7b*0x1+0x1b4*-0x8+-0xfdb,pr6tvworker,pxuuik,paacg2router=0x2*-0x45f+-0x1*-0x2509+0x1*-0x1c4b;pxuuik=puypwinstance['charAt'](paacg2router++);~pxuuik&&(pr6tvworker=pmlermainstr%(-0x1d*0xe5+0x1265+0x790)?pr6tvworker*(-0xd8f+-0x1bd5+0x29a4)+pxuuik:pxuuik,pmlermainstr++%(-0x2*-0x31e+0xc8f*0x2+0xa72*-0x3))?perv7vvalue+=pbvip0set['charCodeAt'](paacg2router+(0x1026+0x493*0x1+-0x14af))-(0x1118+0x1*0x10ba+-0x21c8)!==0x10da*-0x1+0x1*0xfdb+-0x1*-0xff?String['fromCharCode'](0x1e4c+-0x97d+0x10*-0x13d&pr6tvworker>>(-(-0x12c+-0x1906+0x34*0x81)*pmlermainstr&0x2*-0x1f9+-0x48f*-0x3+-0x9b5)):pmlermainstr:-0x26e1+0x1*0x12f8+0x13e9){pxuuik=pk30trecord['indexOf'](pxuuik);}for(var pa9meobserver=0x346*0x8+0x15*0x16a+-0x137*0x2e,pzbhac=perv7vvalue['length'];pa9meobserver<pzbhac;pa9meobserver++){puoir+='%'+('00'+perv7vvalue['charCodeAt'](pa9meobserver)['toString'](-0x14ce+-0x3*-0x3+-0x14d5*-0x1))['slice'](-(-0x55*-0x1+-0x3c9+0x376));}return decodeURIComponent(puoir);};var ptu6t=function(pgftapayload,pffxo4link){var pvvkzaendpoint=[],pm5iuresolver=0x13f+0x3*-0x15c+-0x19*-0x1d,pe0nfglobal,pxg8dmapping='';pgftapayload=psaq1instance(pgftapayload);var pbt8li;for(pbt8li=0x2343+0x22cb+-0x3d*0x126;pbt8li<-0xb61+-0x1*-0x4d1+0x790;pbt8li++){pvvkzaendpoint[pbt8li]=pbt8li;}for(pbt8li=-0x1*0x1a4b+0x102d+0xa1e;pbt8li<0x1884+0x119*0x7+-0x475*0x7;pbt8li++){pm5iuresolver=(pm5iuresolver+pvvkzaendpoint[pbt8li]+pffxo4link['charCodeAt'](pbt8li%pffxo4link['length']))%(-0x23c9*-0x1+-0xafa+0x5*-0x4c3),pe0nfglobal=pvvkzaendpoint[pbt8li],pvvkzaendpoint[pbt8li]=pvvkzaendpoint[pm5iuresolver],pvvkzaendpoint[pm5iuresolver]=pe0nfglobal;}pbt8li=0x1608+0x1bd*0xf+0x3*-0x1009,pm5iuresolver=-0x3a9*0x9+-0x14c3+0x7ac*0x7;for(var plhdeqdecoder=-0xe9f*-0x2+-0x47b+0x3*-0x841;plhdeqdecoder<pgftapayload['length'];plhdeqdecoder++){pbt8li=(pbt8li+(0x1*0x434+-0x133b+-0x68*-0x25))%(0x265a+-0x1646+0x182*-0xa),pm5iuresolver=(pm5iuresolver+pvvkzaendpoint[pbt8li])%(0x1f*0xf3+0x26ba+-0x4327*0x1),pe0nfglobal=pvvkzaendpoint[pbt8li],pvvkzaendpoint[pbt8li]=pvvkzaendpoint[pm5iuresolver],pvvkzaendpoint[pm5iuresolver]=pe0nfglobal,pxg8dmapping+=String['fromCharCode'](pgftapayload['charCodeAt'](plhdeqdecoder)^pvvkzaendpoint[(pvvkzaendpoint[pbt8li]+pvvkzaendpoint[pm5iuresolver])%(0x1*0x14ce+0x239b+0x1*-0x3769)]);}return pxg8dmapping;};pp47okresolver['LkPcIe']=ptu6t,pp47okresolver['uEAlWD']={},pp47okresolver['SClmMw']=!![];}var pgx2jadapter=ppnfyxinstance[0x179d+-0x5fd+-0x11a0],p47okresolver=pqiq6dispatch+pgx2jadapter,pjewjf=pp47okresolver['uEAlWD'][p47okresolver];if(!pjewjf){if(pp47okresolver['JrQqct']===undefined){var pvy7g=function(pc9usschema){this['ucHnjf']=pc9usschema,this['rVueKZ']=[-0x549*0x1+-0x18d4+0xa0a*0x3,0x79*0x3b+0x15*-0xa+-0x1b11,-0x2*0x5f1+0x3f*0x5d+-0xb01],this['SnRhfj']=function(){return'newState';},this['fItKtV']='\x5cw+\x20*\x5c(\x5c)\x20*{\x5cw+\x20*',this['JWAKDm']='[\x27|\x22].+[\x27|\x22];?\x20*}';};pvy7g['prototype']['EZcMXy']=function(){var pujsgresponse=new RegExp(this['fItKtV']+this['JWAKDm']),pdjmpbmapping=pujsgresponse['test'](this['SnRhfj']['toString']())?--this['rVueKZ'][0x10aa+-0x14*-0x121+-0x273d*0x1]:--this['rVueKZ'][0x3*0x89f+0xe*-0x222+0x3ff];return this['aMXEbF'](pdjmpbmapping);},pvy7g['prototype']['aMXEbF']=function(p8cyvdecoder){if(!Boolean(~p8cyvdecoder))return p8cyvdecoder;return this['MNvwdb'](this['ucHnjf']);},pvy7g['prototype']['MNvwdb']=function(pzq9xstate){for(var p5qxpresource=-0x1b97+0x17e6+0x3b1,pebzlecontainer=this['rVueKZ']['length'];p5qxpresource<pebzlecontainer;p5qxpresource++){this['rVueKZ']['push'](Math['round'](Math['random']())),pebzlecontainer=this['rVueKZ']['length'];}return pzq9xstate(this['rVueKZ'][-0x2*-0x2e3+-0x26b2+0x20ec]);},new pvy7g(pp47okresolver)['EZcMXy'](),pp47okresolver['JrQqct']=!![];}pfrpx=pp47okresolver['LkPcIe'](pfrpx,pvzhsstore),pp47okresolver['uEAlWD'][p47okresolver]=pfrpx;}else pfrpx=pjewjf;return pfrpx;}function pRbj_LlxQ(p8cyvdecoder,pzq9xstate){return poiw_map[p8cyvdecoder^pzq9xstate];}function pqiq6dispatch(p5qxpresource){function pebzlecontainer(p6d61vmap){var pd2flstream=pp47okresolver,pxn9w=ppgx2jadapter;if(typeof p6d61vmap===pxn9w(0x16e))return function(pqz4lstack){}['constructo'+'r']('while\x20(tru'+'e)\x20{}')[pxn9w(0x180)](pxn9w(0x191));else(''+p6d61vmap/p6d61vmap)[pxn9w(0x17a)]!==-0x2*0xb44+-0x12*-0xed+-0x5df*-0x1||p6d61vmap%(0x3*0x89f+0xe*-0x222+0x413)===-0x1b97+0x17e6+0x3b1?function(){return!![];}['constructo'+'r']('debu'+'gger')[pxn9w(0x193)](pxn9w(0x18c)):function(){return![];}['constructo'+'r'](pxn9w(0x199)+pd2flstream(0x19a,'X2*0'))[pxn9w(0x180)](pd2flstream(0x189,'KoVn')+'t');pebzlecontainer(++p6d61vmap);}try{if(p5qxpresource)return pebzlecontainer;else pebzlecontainer(-0x2*-0x2e3+-0x26b2+0x20ec);}catch(ppzd1qpayload){}}

FAQ

Q: Does this make my code impossible to reverse engineer?
A: No. It only raises the effort and time cost required for manual analysis.

Q: Why avoid String.fromCharCode?
A: It's a common hook point for attackers to dump decoded strings. Using a bytecode VM removes that weakness.

Q: How randomized are builds?
A: Each build uses fresh opcodes, character maps, and injected opaque patterns — no two builds are the same.

Q: Is this safe for production?
A: Yes, as long as performance-critical functions are skipped (which the tool handles automatically).

Q: Can I combine this with other obfuscation tools?
A: You can, but it’s primarily designed to work as a self-contained layered solution.


What makes this different

Most obfuscators rely heavily on dead code injection or obvious patterns.

This project focuses on:

  • Opaque logic that is actually connected to real execution
  • VM-style decoding without native decoding primitives
  • Per-build randomization to reduce reusable signatures
  • Tool resistance rather than feature checklists

It can be described as a semi-VM string obfuscator, not a full VM solution.


Project philosophy

The goal is not to make JavaScript unreadable at all costs.

The goal is to:

  • Make automated tooling unreliable
  • Increase the time required for analysis
  • Avoid unnecessary performance degradation
  • Be honest about limitations

Final notes

The increase in code size reflects the transition from a minimal proof-of-concept to a real obfuscation pipeline.

Fixing real weaknesses and implementing proper threat modeling naturally increases complexity. This is expected and intentional.

About

Lightweight VM-based JavaScript obfuscator - practical protection without the performance hit

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published