代码混淆与加密

为什么加密或混淆

  • JavaScript 代码运行于客户端
  • JavaScript 代码是公开透明的

如何对 JavaScript 进行保护

  • 代码压缩:去除空格、换行等
  • 代码加密:eval、emscripten、WebAssembly 等
  • 代码混淆:变量混淆、常量混淆、控制流扁平化、调试保护等

JavaScript 加密实现

eval 加密

利用 eval 函数将 JavaScrpt 代码变成参数, eval 方法就是 JavaScript 代码的一个执行器,它可以把其中的参数按照 JavaScript 语法进行解析并执行。

这种加密方式其实就是把 JavaScript 代码变成 eval 方法的字符串参数,其中的一些字符都会被按照特定的格式编码。

encrypt_01.png

这种加密方式并不复杂,将代码在控制台执行运行就可以得到结果。或者将 eval 包裹去掉,我们也可以得到一个函数。

Emscripten

  • 核心:C/C++
  • 编译:Emscripten
  • 结果:asm.js
  • 调用:JavaScript

WebAssembly

  • 核心:C/C++
  • 结果:wasm 文件
  • 调用:JavaScript

encrypt_02.png

基本和 Emscripten 一致,不过它使用的是二进制编码,运行速度会更快,体积也会更小。

性能相对其他加密方式会好一些,但是涉及 C/C++ 代码改写,还需要进行编译,整体成本还是比较高的,这里仅做一下介绍。

JavaScript 混淆技术

相关技术

  • 变量混淆
    • 源代码变量名基本都具有语义,例如 count 代表计数器等。
    • 变量混淆之后将变量变成一些无意义的、看起来比较乱的一些字符串,例如 16 进制的字符串,降低代码可读性。
  • 字符串混淆
    • 将字符串进行 md5 加密、base64 编码、RC4,确保代码不会通过搜索的功能查到原始字符串,降低通过字符串寻找入口的风险。
  • 属性加密
    • javascript 存在对象类型,可能是 key-value 的键值对,所以我们可以把 javascript 中的对象进行加密转化,将 key- value 映射关系混淆掉,变的更加难以寻找其中逻辑。
  • 控制流平坦化
    • 打乱原有代码的执行流程和函数调用关系。
    • 例如之前我们存在一些逻辑区块,它是由 A 到 B 到 C。 我们可以给它的控制流加上一个前置的控制流,前置的控制流中再加上一些条件判断,由前置的控制流进行分流。这样我们就可以把执行的逻辑变得更加复杂,难读。
  • 僵尸代码注入
    • 将一些无用代码、不可能被执行到的代码注入到当前的代码里面,实现一些认为的扰乱。
  • 代码压缩
    • 去除一些空格,回车,调试语句等代码,使文件变得更小,由多行代码变为一行代码,压缩代码体积,使代码更难读。
  • 反调试
    • 基于浏览器的一些特性,对当前环境进行检验,加上 debugger 语句,例如无限 debugger,定时器 debugger,用一些断点进行干扰。
  • 多态变异
    • JavaScript 代码被调用时,一旦代码被调用,代码就会立刻发生变化,变成和原来完全不同的代码,但是依旧可以保持功能完全,只是代码形式发生变化。 避免代码被动态分析、调试。
  • 锁定域名
    • 对域名进行检测,JavaScript 代码必须运行在特定的域名下。
  • 反格式化
    • 将代码格式化后,会有一些机制使得代码在运行的时候无法正常工作。
  • 特殊编码
    • 将 JavaScript 代码编码成一些特别难读的代码,例如中括号,叹号等等,编译成一些表情,符号等等,不易读。

开源项目

在线工具

商业服务

JavaScript 混淆实现

基于 javascript-obfuscator 演示、使用多种混淆技术、依赖 Node.js。

pnpm init
js
pnpm i javascript-obfuscator --save-dev
js

基础案例

// demo01.js

const obfuscator = require('javascript-obfuscator')

const code = `
  const x  = 'l' + 1
  console.log('x', x)
`

const options = {
  compact: false, // 是否压缩成一行
  controlFlowFlattening: true // 控制流平坦化
}

const obfuscate = (code, options) => obfuscator.obfuscate(code, options).getObfuscatedCode()
console.log(obfuscate(code, options))

// const _0x319a8e = _0x17c8;
// (function (_0x52f8e7, _0x57164d) {
//     const _0x46023b = _0x17c8, _0x430115 = _0x52f8e7();
//     while (!![]) {
//         try {
//             const _0x139205 = parseInt(_0x46023b(0x1c2)) / 0x1 + -parseInt(_0x46023b(0x1c0)) / 0x2 + -parseInt(_0x46023b(0x1c4)) / 0x3 + parseInt(_0x46023b(0x1be)) / 0x4 * (-parseInt(_0x46023b(0x1bc)) / 0x5) + -parseInt(_0x46023b(0x1ba)) / 0x6 + -parseInt(_0x46023b(0x1bb)) / 0x7 * (-parseInt(_0x46023b(0x1bd)) / 0x8) + -parseInt(_0x46023b(0x1c1)) / 0x9 * (-parseInt(_0x46023b(0x1c3)) / 0xa);
//             if (_0x139205 === _0x57164d)
//                 break;
//             else
// heora@yueluodeMBP obfuscator % node demo01.js
// function _0x37c2(_0x15e667, _0x179462) {
//     const _0x3fc284 = _0x3fc2();
//     return _0x37c2 = function (_0x37c288, _0x365673) {
//         _0x37c288 = _0x37c288 - 0x149;
//         let _0x3bb96b = _0x3fc284[_0x37c288];
//         return _0x3bb96b;
//     }, _0x37c2(_0x15e667, _0x179462);
// }
// const _0x41fee7 = _0x37c2;
// function _0x3fc2() {
//     const _0xff6162 = [
//         '2180445LYHBNw',
//         '6PoXlVC',
//         '1062245HPVdof',
//         '4962699JsvSZR',
//         '2037424UwkIQW',
//         '2wCqcbN',
//         '22550990HHAjbJ',
//         'log',
//         '181064EFBbAW',
//         '744311jBDKbx',
//         '153fCiFKW'
//     ];
//     _0x3fc2 = function () {
//         return _0xff6162;
//     };
//     return _0x3fc2();
// }
// (function (_0x44b360, _0x36241e) {
//     const _0x352cf1 = _0x37c2, _0x59526 = _0x44b360();
//     while (!![]) {
//         try {
//             const _0x546e33 = -parseInt(_0x352cf1(0x153)) / 0x1 + parseInt(_0x352cf1(0x14f)) / 0x2 * (parseInt(_0x352cf1(0x14a)) / 0x3) + -parseInt(_0x352cf1(0x14e)) / 0x4 + -parseInt(_0x352cf1(0x14c)) / 0x5 * (parseInt(_0x352cf1(0x14b)) / 0x6) + -parseInt(_0x352cf1(0x14d)) / 0x7 + parseInt(_0x352cf1(0x152)) / 0x8 * (-parseInt(_0x352cf1(0x149)) / 0x9) + parseInt(_0x352cf1(0x150)) / 0xa;
//             if (_0x546e33 === _0x36241e)
//                 break;
//             else
//                 _0x59526['push'](_0x59526['shift']());
//         } catch (_0x479a3c) {
//             _0x59526['push'](_0x59526['shift']());
//         }
//     }
// }(_0x3fc2, 0x670c0));
// const x = 'l' + 0x1;
// console[_0x41fee7(0x151)]('x', x);
js

整体来看,混淆之后可读性变得非常差。

代码压缩

启用 compact 配置可以进行代码压缩,将多行代码压缩为一行。

const obfuscator = require('javascript-obfuscator')

const code = `
  const x  = 'l' + 1
  console.log('x', x)
`

const options = {
  compact: true, // 是否压缩成一行
  controlFlowFlattening: true // 控制流平坦化
}

const obfuscate = (code, options) => obfuscator.obfuscate(code, options).getObfuscatedCode()
console.log(obfuscate(code, options))

// function _0x1ed0(){const _0x11ff60=['1696072pCxUdw','9081JMWsXK','58LluwlY','log','2552oFOSUn','1122qjQuAv','25537SpbjXH','711552eXkfAf','4202505CboVKg','8669610XfCMvT','29701fxdBiQ'];_0x1ed0=function(){return _0x11ff60;};return _0x1ed0();}const _0x34263e=_0x2ad4;(function(_0x51afa7,_0x14bd8d){const _0x11aac9=_0x2ad4,_0x4255eb=_0x51afa7();while(!![]){try{const _0x2f7cdd=parseInt(_0x11aac9(0x1a4))/0x1*(parseInt(_0x11aac9(0x1a0))/0x2)+-parseInt(_0x11aac9(0x19a))/0x3+-parseInt(_0x11aac9(0x19e))/0x4+-parseInt(_0x11aac9(0x19b))/0x5+parseInt(_0x11aac9(0x1a3))/0x6*(parseInt(_0x11aac9(0x19d))/0x7)+parseInt(_0x11aac9(0x1a2))/0x8*(-parseInt(_0x11aac9(0x19f))/0x9)+parseInt(_0x11aac9(0x19c))/0xa;if(_0x2f7cdd===_0x14bd8d)break;else _0x4255eb['push'](_0x4255eb['shift']());}catch(_0x12ce85){_0x4255eb['push'](_0x4255eb['shift']());}}}(_0x1ed0,0x8cf79));const x='l'+0x1;function _0x2ad4(_0x3170d9,_0x25c3ba){const _0x1ed02b=_0x1ed0();return _0x2ad4=function(_0x2ad40e,_0x2457e3){_0x2ad40e=_0x2ad40e-0x19a;let _0xf8cd45=_0x1ed02b[_0x2ad40e];return _0xf8cd45;},_0x2ad4(_0x3170d9,_0x25c3ba);}console[_0x34263e(0x1a1)]('x',x);
js

变量名混淆

controlFlowFlattening 配置为 true,使用的是 16 进制混淆。我们还可以使用 identifierNameGenerator 属性, 设置其值为 mangled,即普通混淆。

const obfuscator = require('javascript-obfuscator')

const code = `
  const x  = 'l' + 1
  console.log('x', x)
`

const options = {
  compact: true, // 是否压缩成一行
  // controlFlowFlattening: true // 控制流平坦化
  identifierNamesGenerator: 'mangled'
}

const obfuscate = (code, options) => obfuscator.obfuscate(code, options).getObfuscatedCode()
console.log(obfuscate(code, options))

// function a(){const i=['1402511atPvUm','226fjmYht','1084160Vfcblk','6748XotdGE','6ldcOls','374521DOItpE','587862aDEfQq','56gRDPSI','307471KdMVmp','5862OyJEBp','215otlhqL'];a=function(){return i;};return a();}(function(c,d){const h=b,e=c();while(!![]){try{const f=-parseInt(h(0x184))/0x1+parseInt(h(0x188))/0x2*(parseInt(h(0x185))/0x3)+parseInt(h(0x17f))/0x4*(parseInt(h(0x186))/0x5)+-parseInt(h(0x180))/0x6*(-parseInt(h(0x181))/0x7)+parseInt(h(0x183))/0x8*(parseInt(h(0x182))/0x9)+-parseInt(h(0x189))/0xa+-parseInt(h(0x187))/0xb;if(f===d)break;else e['push'](e['shift']());}catch(g){e['push'](e['shift']());}}}(a,0x3fa4c));function b(c,d){const e=a();return b=function(f,g){f=f-0x17f;let h=e[f];return h;},b(c,d);}const x='l'+0x1;console['log']('x',x);
js

字符串混淆

const options = {
  stringArray: true,
  rotateStringArray: true,
  stringArrayEncoding: ['base64'], // none, base64, rc4
  stringArrayThreshold: 1
}

const obfuscate = (code, options) => obfuscator.obfuscate(code, options).getObfuscatedCode()
console.log(obfuscate(code, options))

// const _0x58c2e4=_0x30f4;(function(_0x3dd5c3,_0x43cf03){const _0x50015b=_0x30f4,_0x175929=_0x3dd5c3();while(!![]){try{const _0x179e3e=parseInt(_0x50015b(0x13b))/0x1+-parseInt(_0x50015b(0x13d))/0x2+parseInt(_0x50015b(0x13e))/0x3+-parseInt(_0x50015b(0x13a))/0x4*(parseInt(_0x50015b(0x13f))/0x5)+-parseInt(_0x50015b(0x143))/0x6+-parseInt(_0x50015b(0x141))/0x7+-parseInt(_0x50015b(0x140))/0x8*(-parseInt(_0x50015b(0x13c))/0x9);if(_0x179e3e===_0x43cf03)break;else _0x175929['push'](_0x175929['shift']());}catch(_0x541ffd){_0x175929['push'](_0x175929['shift']());}}}(_0x1ccc,0xe0350));function _0x30f4(_0x4eb79e,_0x329d01){const _0x1ccc2c=_0x1ccc();return _0x30f4=function(_0x30f48d,_0x5a5d5e){_0x30f48d=_0x30f48d-0x13a;let _0x2d532d=_0x1ccc2c[_0x30f48d];if(_0x30f4['xjhYfs']===undefined){var _0x41f5fe=function(_0x56b76d){const _0x53a9ee='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x1528e0='',_0x57a8e8='';for(let _0x170a79=0x0,_0xdbd185,_0x647290,_0x1847b2=0x0;_0x647290=_0x56b76d['charAt'](_0x1847b2++);~_0x647290&&(_0xdbd185=_0x170a79%0x4?_0xdbd185*0x40+_0x647290:_0x647290,_0x170a79++%0x4)?_0x1528e0+=String['fromCharCode'](0xff&_0xdbd185>>(-0x2*_0x170a79&0x6)):0x0){_0x647290=_0x53a9ee['indexOf'](_0x647290);}for(let _0x7c52f0=0x0,_0x13a433=_0x1528e0['length'];_0x7c52f0<_0x13a433;_0x7c52f0++){_0x57a8e8+='%'+('00'+_0x1528e0['charCodeAt'](_0x7c52f0)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(_0x57a8e8);};_0x30f4['BApANM']=_0x41f5fe,_0x4eb79e=arguments,_0x30f4['xjhYfs']=!![];}const _0x37ec4a=_0x1ccc2c[0x0],_0x52ca06=_0x30f48d+_0x37ec4a,_0x44eed0=_0x4eb79e[_0x52ca06];return!_0x44eed0?(_0x2d532d=_0x30f4['BApANM'](_0x2d532d),_0x4eb79e[_0x52ca06]=_0x2d532d):_0x2d532d=_0x44eed0,_0x2d532d;},_0x30f4(_0x4eb79e,_0x329d01);}function _0x1ccc(){const _0x1e5d0c=['mZzTuuDct0C','mtm4ntG1m1vnshvUAa','mJu4mdq4mdLSuwnuAvq','mJa0mZKWnfbqtgvWBa','ndyXotm2n0jjuNzfCa','nti3ndKWBgX6yxr5','ofHbvfvTua','mteXnJy2mtb6yw9mBhG','Bg9N','nZG0nJK2mLfeu0zSsG'];_0x1ccc=function(){return _0x1e5d0c;};return _0x1ccc();}const x='l'+0x1;console[_0x58c2e4(0x142)]('x',x);
js
const options = {
  compact: false,
  unicodeEscaoeSequence: true
}

const obfuscate = (code, options) => obfuscator.obfuscate(code, options).getObfuscatedCode()
console.log(obfuscate(code, options))

// function _0x26ba(_0x36c780, _0x53d9ad) {
//   const _0x395a7c = _0x395a();
//   return _0x26ba = function (_0x26ba1b, _0x50e0f8) {
//       _0x26ba1b = _0x26ba1b - 0xf6;
//       let _0x673a36 = _0x395a7c[_0x26ba1b];
//       return _0x673a36;
//   }, _0x26ba(_0x36c780, _0x53d9ad);
// }
// const _0x4a8483 = _0x26ba;
// (function (_0x4f6148, _0x62c41e) {
//   const _0x12fd5b = _0x26ba, _0x1cdb96 = _0x4f6148();
//   while (!![]) {
//       try {
//           const _0x425692 = -parseInt(_0x12fd5b(0xff)) / 0x1 * (-parseInt(_0x12fd5b(0xfc)) / 0x2) + -parseInt(_0x12fd5b(0xf7)) / 0x3 + parseInt(_0x12fd5b(0xfb)) / 0x4 * (-parseInt(_0x12fd5b(0xfd)) / 0x5) + -parseInt(_0x12fd5b(0xfe)) / 0x6 * (-parseInt(_0x12fd5b(0xf9)) / 0x7) + -parseInt(_0x12fd5b(0xf6)) / 0x8 + -parseInt(_0x12fd5b(0xfa)) / 0x9 + parseInt(_0x12fd5b(0xf8)) / 0xa;
//           if (_0x425692 === _0x62c41e)
//               break;
//           else
//               _0x1cdb96['push'](_0x1cdb96['shift']());
//       } catch (_0x52d520) {
//           _0x1cdb96['push'](_0x1cdb96['shift']());
//       }
//   }
// }(_0x395a, 0xe5bec));
// function _0x395a() {
//   const _0x396de0 = [
//       '11wNEArv',
//       'log',
//       '3704680AnmDYz',
//       '4713714utvsgx',
//       '34268930dvIjTj',
//       '53137GzFDpL',
//       '8750070qAxqEg',
//       '260292YHShGR',
//       '138466fDpVBL',
//       '85BHgFkg',
//       '684wMjWNk'
//   ];
//   _0x395a = function () {
//       return _0x396de0;
//   };
//   return _0x395a();
// }
// const x = 'l' + 0x1;
// console[_0x4a8483(0x100)]('x', x);
js

自我保护

代码混淆后,如果格式化运行,会将浏览器直接卡死。

原理:申请一些空间、新建一些对象、无限的新建一些 DOM 节点,或者有一些其他操作,它会疯狂占用浏览器和本机内存,将浏览器直接卡死,无法运行。

const options = {
  selfDefending: true
}

const obfuscate = (code, options) => obfuscator.obfuscate(code, options).getObfuscatedCode()
console.log(obfuscate(code, options))

// function _0x6a5a(_0x57ebb1,_0x288f15){const _0x57a170=_0x3833();return _0x6a5a=function(_0x2482c9,_0x25f644){_0x2482c9=_0x2482c9-0x1ef;let _0x3833aa=_0x57a170[_0x2482c9];return _0x3833aa;},_0x6a5a(_0x57ebb1,_0x288f15);}const _0x252268=_0x6a5a;(function(_0x385891,_0x470326){const _0x193ce5=_0x6a5a,_0x3015bf=_0x385891();while(!![]){try{const _0x49f914=-parseInt(_0x193ce5(0x1fb))/0x1+-parseInt(_0x193ce5(0x1fc))/0x2*(parseInt(_0x193ce5(0x1ef))/0x3)+parseInt(_0x193ce5(0x1f3))/0x4+parseInt(_0x193ce5(0x1f2))/0x5*(parseInt(_0x193ce5(0x1f4))/0x6)+-parseInt(_0x193ce5(0x1f1))/0x7+parseInt(_0x193ce5(0x1f9))/0x8+-parseInt(_0x193ce5(0x1f0))/0x9*(parseInt(_0x193ce5(0x1f7))/0xa);if(_0x49f914===_0x470326)break;else _0x3015bf['push'](_0x3015bf['shift']());}catch(_0x5897ea){_0x3015bf['push'](_0x3015bf['shift']());}}}(_0x3833,0x86bac));const _0x25f644=(function(){let _0x8e8490=!![];return function(_0x19b5dc,_0x146e4a){const _0x16be9a=_0x8e8490?function(){const _0x556212=_0x6a5a;if(_0x146e4a){const _0x495ee9=_0x146e4a[_0x556212(0x1f5)](_0x19b5dc,arguments);return _0x146e4a=null,_0x495ee9;}}:function(){};return _0x8e8490=![],_0x16be9a;};}()),_0x2482c9=_0x25f644(this,function(){const _0x35d7d9=_0x6a5a;return _0x2482c9['toString']()[_0x35d7d9(0x1fa)](_0x35d7d9(0x1f6))[_0x35d7d9(0x1fd)]()[_0x35d7d9(0x1fe)](_0x2482c9)[_0x35d7d9(0x1fa)](_0x35d7d9(0x1f6));});_0x2482c9();function _0x3833(){const _0x3304a8=['5oGONaW','2118072PoiGNm','6069912QkkLzC','apply','(((.+)+)+)+$','236020nALghG','log','8703416GbJlym','search','697721FGPyIP','41456DmSEci','toString','constructor','51yNMskw','144UZjKrD','4546612XUZMRy'];_0x3833=function(){return _0x3304a8;};return _0x3833();}const x='l'+0x1;console[_0x252268(0x1f8)]('x',x);
js

控制流平坦化

逻辑处理块统一加上前驱逻辑块,提高逻辑流程复杂度。

 const options = {
  compact: false,
  controlFLowFlattening: true
}

const obfuscate = (code, options) => obfuscator.obfuscate(code, options).getObfuscatedCode()
console.log(obfuscate(code, options))

// const _0x5dc750 = _0x5706;
// (function (_0x3705ad, _0x1ab8ab) {
//     const _0x1cd39c = _0x5706, _0x35c863 = _0x3705ad();
//     while (!![]) {
//         try {
//             const _0x1b977e = parseInt(_0x1cd39c(0xb7)) / 0x1 * (-parseInt(_0x1cd39c(0xbc)) / 0x2) + -parseInt(_0x1cd39c(0xbf)) / 0x3 * (-parseInt(_0x1cd39c(0xba)) / 0x4) + -parseInt(_0x1cd39c(0xbe)) / 0x5 * (parseInt(_0x1cd39c(0xb6)) / 0x6) + parseInt(_0x1cd39c(0xc2)) / 0x7 + -parseInt(_0x1cd39c(0xb9)) / 0x8 + parseInt(_0x1cd39c(0xbb)) / 0x9 * (-parseInt(_0x1cd39c(0xc1)) / 0xa) + -parseInt(_0x1cd39c(0xb8)) / 0xb * (-parseInt(_0x1cd39c(0xc0)) / 0xc);
//             if (_0x1b977e === _0x1ab8ab)
//                 break;
//             else
//                 _0x35c863['push'](_0x35c863['shift']());
//         } catch (_0x40471c) {
//             _0x35c863['push'](_0x35c863['shift']());
//         }
//     }
// }(_0x3311, 0x2e4d1));
// const x = 'l' + 0x1;
// function _0x5706(_0x5eb3cb, _0x2fe232) {
// heora@yueluodeMBP obfuscator % node index.js
// function _0x5e0a(_0x3c930e, _0xf6aecd) {
//     const _0xb7c1fd = _0xb7c1();
//     return _0x5e0a = function (_0x5e0a43, _0x2da791) {
//         _0x5e0a43 = _0x5e0a43 - 0x91;
//         let _0x5bad25 = _0xb7c1fd[_0x5e0a43];
//         return _0x5bad25;
//     }, _0x5e0a(_0x3c930e, _0xf6aecd);
// }
// (function (_0x5cc324, _0x3698c3) {
//     const _0x118339 = _0x5e0a, _0x5a6295 = _0x5cc324();
//     while (!![]) {
//         try {
//             const _0x2d006b = parseInt(_0x118339(0x9a)) / 0x1 * (-parseInt(_0x118339(0x97)) / 0x2) + parseInt(_0x118339(0x94)) / 0x3 + parseInt(_0x118339(0x98)) / 0x4 * (-parseInt(_0x118339(0x95)) / 0x5) + parseInt(_0x118339(0x91)) / 0x6 * (parseInt(_0x118339(0x99)) / 0x7) + parseInt(_0x118339(0x93)) / 0x8 + -parseInt(_0x118339(0x92)) / 0x9 * (parseInt(_0x118339(0x9b)) / 0xa) + parseInt(_0x118339(0x96)) / 0xb;
//             if (_0x2d006b === _0x3698c3)
//                 break;
//             else
//                 _0x5a6295['push'](_0x5a6295['shift']());
//         } catch (_0x610e47) {
//             _0x5a6295['push'](_0x5a6295['shift']());
//         }
//     }
// }(_0xb7c1, 0xe2a91));
// const x = 'l' + 0x1;
// console['log']('x', x);
// function _0xb7c1() {
//     const _0x1b686a = [
//         '13309008LblyTk',
//         '4726668qrEbyA',
//         '24065OkOLaS',
//         '849354IMMUmk',
//         '727178NkDDmz',
//         '956iVWkFu',
//         '12497821clefPv',
//         '5WaaQvM',
//         '20kFAjWw',
//         '6FgSNaA',
//         '5423157YBbrFb'
//     ];
//     _0xb7c1 = function () {
//         return _0x1b686a;
//     };
//     return _0xb7c1();
// }
js

僵尸代码注入

僵尸代码:不会被执行的代码或对上下文没有任何影响的代码,注入后可以对现有的 JavaScript 代码阅读形成干扰。

对象键名替换

对 Object 对象键名替换

const options = {
  compact: true,
  transformObjectKeys: true
}
js

禁用控制台输出

将控制台方法置空

  • debug
  • info
  • error
  • exception
  • trace
const options = {
  disableConsoleOutput: true
}
js

调试保护

无限 debug、定时 debug、debugger 关键字

const options = {
  debugProtection: true
}
js

域名锁定

只允许在特定域名下运行、降低被模拟风险

const options = {
  domainLock: ['yueluo.club']
}
js

其他实现

JSFuck

  • 将变量进行逻辑替换,例如 false 会直接等于 ![] ,然后把逻辑进行分析, 对代码进行混淆,可读性会变的非常差,体积也会变得很大。

AAEncode

  • 将代码转换成表情符号的形式

JJEncode

  • 将代码转换成 $+: 的形式

上述这几种方式放到浏览器是可以直接运行的,也可以通过一些简单的方式对代码进行还原处理,看起来很复杂,但是非常容易破解。