JavaScript混淆

JavaScript混淆以上 我们就介绍了接口加密技术和 JavaScript 的压缩 混淆和加密技术 知己知彼方能百战不殆 了解了原理 我们才能更好地去实现 JavaScript 的逆向

大家好,欢迎来到IT知识分享网。

前言

当今互联网时代,JavaScript已经成为了web前端开发的重点技术之一。其中,JavaScript代码的安全性问题一直是关注的焦点。为了保护JavaScript代码的安全性,很多人对其进行加密处理,众所周知,对于单纯的加密算法,通过反向工程或逆向分析也能够激活成功教程。在此情况下,JavaScript代码混淆技术成为了一种应对加密激活成功教程的有效措施。
 


提示:以下是本篇文章正文内容,下面案例可供参考

  • 一、js混淆是什么?

二、js混淆作用

JavaScript混淆是保护JavaScript代码和数据安全的重要技术。为了防止爬虫通过分析js内容,轻易的还原出网站的加密逻辑,而做出的安全防御手段之一,常常将一个逻辑简单的可能十几行算法代码思路,通过变量混淆替换、增加冗余无效代码、增加无限debugger反调试功能、增加多层的套娃式if~else代码、以及埋陷阱等混淆成几千行的js代码,给人第一印象难读,对入门分析者造成恐惧心理。

三、JavaScript 混淆技术主要有以下几种:

  • 变量混淆 将带有含意的变量名、方法名、常量名随机变为无意义的类乱码字符串,降低代码可读性,如转成单个字符或十六进制字符串。
  • 字符串混淆 将字符串阵列化集中放置、并可进行 MD5 或 Base64 加密存储,使代码中不出现明文字符串,这样可以避免使用全局搜索字符串的方式定位到入口点。
  • 属性加密 针对 JavaScript 对象的属性进行加密转化,隐藏代码之间的调用关系。
  • 控制流平坦化 打乱函数原有代码执行流程及函数调用关系,使代码逻变得混乱无序。
  • 僵尸代码 随机在代码中插入无用的僵尸代码、僵尸函数,进一步使代码混乱。
  • 调试保护 基于调试器特性,对当前运行环境进行检验,加入一些强制调试 debugger 语句,使其在调试模式下难以顺利执行 JavaScript 代码。
  • 多态变异 使 JavaScript 代码每次被调用时,将代码自身即立刻自动发生变异,变化为与之前完全不同的代码,即功能完全不变,只是代码形式变异,以此杜绝代码被动态分析调试。
  • 锁定域名 使 JavaScript 代码只能在指定域名下执行。
  • 反格式化 如果对 JavaScript 代码进行格式化,则无法执行,导致浏览器假死。
  • 特殊编码 将 JavaScript 完全编码为人不可读的代码,如表情符号、特殊表示内容等等

四、常见的混淆 

URL:JS加密,JS 安全加密, AAencode 加密 —在线加密 (sojson.com)

1)、OB混淆

OB 混淆全称 Obfuscator,Obfuscator 其实就是混淆的意思,官网:https://obfuscator.io/ ,其作者是一位叫 Timofey Kachalov 的俄罗斯JavaScript开发工程师,早在 2016 年就发布了第一个版本。

OB 混淆具有以下特征:

1、一般由一个大数组或者含有大数组的函数、一个自执行函数、解密函数和加密后的函数四部分组成;

2、函数名和变量名通常以 _0x 或者 0x 开头,后接 1~6 位数字或字母组合;

3、自执行函数,进行移位操作,有明显的 push、shift 关键字;

例如在上面的例子中,_0x3ed1() 方法就定义了一个大数组,自执行函数里有 push、shift 关键字,主要是对大数组进行移位操作,_0x2e12() 就是解密函数,hi() 就是加密后的函数

JavaScript混淆

 

(function(_0x1cbb42, _0x27ca96) { var _0x35e2ac = _0x2e12 , _0x22ba7c = _0x1cbb42(); while (!![]) { try { var _0x108d6f = -parseInt(_0x35e2ac(0x1e6)) / 0x1 + parseInt(_0x35e2ac(0x1eb)) / 0x2 + parseInt(_0x35e2ac(0x1e5)) / 0x3 * (-parseInt(_0x35e2ac(0x1ef)) / 0x4) + parseInt(_0x35e2ac(0x1ed)) / 0x5 + parseInt(_0x35e2ac(0x1ee)) / 0x6 + parseInt(_0x35e2ac(0x1e9)) / 0x7 * (parseInt(_0x35e2ac(0x1e7)) / 0x8) + -parseInt(_0x35e2ac(0x1ea)) / 0x9 * (parseInt(_0x35e2ac(0x1ec)) / 0xa); if (_0x108d6f === _0x27ca96) break; else _0x22ba7c['push'](_0x22ba7c['shift']()); } catch (_0x55c1fe) { _0x22ba7c['push'](_0x22ba7c['shift']()); } } }(_0x3ed1, 0x4cc24)); function _0x2e12(_0x57166b, _0x) { var _0x3ed14f = _0x3ed1(); return _0x2e12 = function(_0x2e123b, _0xa39d85) { _0x2e123b = _0x2e123b - 0x1e5; var _0x532ba1 = _0x3ed14f[_0x2e123b]; return _0x532ba1; } , _0x2e12(_0x57166b, _0x); } function _0x3ed1() { var _0x5dda6c = ['iBYQbo', '54eYZLaO', 'jEsBIU', 'nxCbIq', '13950Avaqin', 'wOmjhe', '60CEfoUI', '20127fpZoZw', 'ExCnkT', '16trzBpq', 'log']; _0x3ed1 = function() { return _0x5dda6c; } ; return _0x3ed1(); } function hi() { var _0xf7fbc1 = _0x2e12; console[_0xf7fbc1(0x1e8)]('Hello\x20World!'); } hi(); 

2)、eval混淆

  • 定义: eval(string) ,可计算某个字符串,并执行其中的的 JavaScript 代码。 有返回值
  • 举例
// eval()函数使用举例 a=eval('(function xxx(){return "hello world"})()'); console.log(a) // hello world // 将上边的eval字体进行base64加密 xxx=btoa('(function xxx(){return "hello world"})()'); console.log(xxx) // KGZ1bmN0aW9uIHh4eCgpe3JldHVybiAiaGVsbG8gd29ybGQifSkoKQ== // 然后混淆的时候,可能就会放入加密的东西 console.log(eval(atob('KGZ1bmN0aW9uIHh4eCgpe3JldHVybiAiaGVsbG8gd29ybGQifSkoKQ==\n'))); 
  • 缺点 :想要运行字符串的值,只能通过明文的eval()函数执行,然后里面的字符串可能是多层加密的,我们通常在eval处下断点。

        想要运行字符串的值,只能通过明文的eval()函数执行,然后里面的字符串可能是多层加密的,我们通常在eval处下断点。

3)、AAEncode混淆(表情包加密)

  • js支持Unicode,因此支持Unicode里收录的所有国家语言,如果我们有的语言和我们定义的变量长得很相似(例如0和o),那么因此有了这种混淆。

示例:console.log(“hello world!”);

JavaScript混淆

  •  解决方法:
  1. 控制台,增删代码,让其报错,即可在虚拟机(VM)处看见源码 
  2. 在线调试,在 AAEncode 代码第一行下断点,然后一步一步执行,最终也会在虚拟机(VM)里看到源码

 4)、jsfuck混淆

  • 思想: jsfuck源于一门编程语言brainfuck,其主要的思想就是只使用8种特定的符号来编写代码。而jsfuck也是沿用了这个思想,它仅仅使用6种符号来编写代码。它们分别是(、)、+、[、]、!
  • 示例:console.log(“hello world!”);

JavaScript混淆 

  • 解决方法:
  1. 如果是非虚拟机的数字/字符串加密使用解密工具:JS 不可逆加密,JS fuck 加密、JavaScript在线加密
  2. 上述解决不了只能一段一段手动控制台复制得结果
  3. 如果是虚拟机加密,让其强制报错

 5)、JJEncode混淆

  • 示例:alert("Hello, JavaScript" );

JavaScript混淆 

6)、sojson混淆

它可以为js代码添加加密混淆压缩成一行防止格式化死代码注入等属性。

  • 加密混淆:将代码中的所有标识符 (变量名, 函数名) 替换成没有意义的以下划线开始的十六进制数字,如 _0x546d, _0x28239d等。
  • 压缩成一行: 将原本多行的代码都写到一行。
  • 防止格式化:如果调试者希望借助 IDE 对代码进行格式化, 代码将无法正常运行, 陷入卡死状态。
  • 死代码注入:如果调试这对代码进行了格式化, 陷入的卡死状态就是注入的死代码导致的

 示例:

JS原文:

(function(w, d) { w.update = "2023年07月16日15:24:29更新"; d.info = "这个是一个本站对JavaScript 脚本的一个最牛加密,兼容性适中,解密难度极大"; })(window, document); 

js混淆后:

var version_ = 'jsjiami.com.v7'; function _0x56f8(_0x239c5e, _0x4296e5) { var _0x342bf4 = _0x342b(); return _0x56f8 = function(_0x56f859, _0x) { _0x56f859 = _0x56f859 - 0xeb; var _0x2e680a = _0x342bf4[_0x56f859]; if (_0x56f8['OGfwbD'] === undefined) { var _0x2c3003 = function(_0x116e29) { var _0x4e35db = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0+/='; var _0x32ef41 = '' , _0x3c2092 = ''; for (var _0x4f8508 = 0x0, _0x28e3e8, _0x3c5243, _0x56e51d = 0x0; _0x3c5243 = _0x116e29['charAt'](_0x56e51d++); ~_0x3c5243 && (_0x28e3e8 = _0x4f8508 % 0x4 ? _0x28e3e8 * 0x40 + _0x3c5243 : _0x3c5243, _0x4f8508++ % 0x4) ? _0x32ef41 += String['fromCharCode'](0xff & _0x28e3e8 >> (-0x2 * _0x4f8508 & 0x6)) : 0x0) { _0x3c5243 = _0x4e35db['indexOf'](_0x3c5243); } for (var _0x49fa53 = 0x0, _0x151cea = _0x32ef41['length']; _0x49fa53 < _0x151cea; _0x49fa53++) { _0x3c2092 += '%' + ('00' + _0x32ef41['charCodeAt'](_0x49fa53)['toString'](0x10))['slice'](-0x2); } return decodeURIComponent(_0x3c2092); }; var _0x1ca9f8 = function(_0x57c253, _0x3c21bc) { var _0x2a0b7d = [], _0x4cb5fb = 0x0, _0x4d43fe, _0x99a74b = ''; _0x57c253 = _0x2c3003(_0x57c253); var _0x; for (_0x = 0x0; _0x < 0x100; _0x++) { _0x2a0b7d[_0x] = _0x; } for (_0x = 0x0; _0x < 0x100; _0x++) { _0x4cb5fb = (_0x4cb5fb + _0x2a0b7d[_0x] + _0x3c21bc['charCodeAt'](_0x % _0x3c21bc['length'])) % 0x100, _0x4d43fe = _0x2a0b7d[_0x], _0x2a0b7d[_0x] = _0x2a0b7d[_0x4cb5fb], _0x2a0b7d[_0x4cb5fb] = _0x4d43fe; } _0x = 0x0, _0x4cb5fb = 0x0; for (var _0x = 0x0; _0x < _0x57c253['length']; _0x++) { _0x = (_0x + 0x1) % 0x100, _0x4cb5fb = (_0x4cb5fb + _0x2a0b7d[_0x]) % 0x100, _0x4d43fe = _0x2a0b7d[_0x], _0x2a0b7d[_0x] = _0x2a0b7d[_0x4cb5fb], _0x2a0b7d[_0x4cb5fb] = _0x4d43fe, _0x99a74b += String['fromCharCode'](_0x57c253['charCodeAt'](_0x) ^ _0x2a0b7d[(_0x2a0b7d[_0x] + _0x2a0b7d[_0x4cb5fb]) % 0x100]); } return _0x99a74b; }; _0x56f8['Dtwoep'] = _0x1ca9f8, _0x239c5e = arguments, _0x56f8['OGfwbD'] = !![]; } var _0x2898ad = _0x342bf4[0x0] , _0x5dd41f = _0x56f859 + _0x2898ad , _0x3ba330 = _0x239c5e[_0x5dd41f]; return !_0x3ba330 ? (_0x56f8['lYcCWy'] === undefined && (_0x56f8['lYcCWy'] = !![]), _0x2e680a = _0x56f8['Dtwoep'](_0x2e680a, _0x), _0x239c5e[_0x5dd41f] = _0x2e680a) : _0x2e680a = _0x3ba330, _0x2e680a; } , _0x56f8(_0x239c5e, _0x4296e5); } (function(_0x57cb6, _0x4314f7, _0x12aca8, _0x16b392, _0x1875bd, _0x, _0x394cbe) { return _0x57cb6 = _0x57cb6 >> 0x1, _0x = 'hs', _0x394cbe = 'hs', function(_0x7b10f6, _0x1a79f7, _0xd8cd20, _0x3f28ea, _0x385c4a) { var _0x2eb8f7 = _0x56f8; _0x3f28ea = 'tfi', _0x = _0x3f28ea + _0x, _0x385c4a = 'up', _0x394cbe += _0x385c4a, _0x = _0xd8cd20(_0x), _0x394cbe = _0xd8cd20(_0x394cbe), _0xd8cd20 = 0x0; var _0x7b2355 = _0x7b10f6(); while (!![] && --_0x16b392 + _0x1a79f7) { try { _0x3f28ea = parseInt(_0x2eb8f7(0xfa, 'Iw8r')) / 0x1 + -parseInt(_0x2eb8f7(0xf8, 'mhb8')) / 0x2 + parseInt(_0x2eb8f7(0xf0, 'lK2M')) / 0x3 * (-parseInt(_0x2eb8f7(0xf5, 'og&u')) / 0x4) + -parseInt(_0x2eb8f7(0xec, '$CGx')) / 0x5 + parseInt(_0x2eb8f7(0xed, 'T^LQ')) / 0x6 + -parseInt(_0x2eb8f7(0xf4, 'sW9l')) / 0x7 * (-parseInt(_0x2eb8f7(0xf3, 'g]XJ')) / 0x8) + -parseInt(_0x2eb8f7(0xf1, 'sW9l')) / 0x9 * (-parseInt(_0x2eb8f7(0xeb, 'QMK%')) / 0xa); } catch (_0x) { _0x3f28ea = _0xd8cd20; } finally { _0x385c4a = _0x7b2355[_0x](); if (_0x57cb6 <= _0x16b392) _0xd8cd20 ? _0x1875bd ? _0x3f28ea = _0x385c4a : _0x1875bd = _0x385c4a : _0xd8cd20 = _0x385c4a; else { if (_0xd8cd20 == _0x1875bd['replace'](/[eWyXFGnhNPAERSqkCKLrg=]/g, '')) { if (_0x3f28ea === _0x1a79f7) { _0x7b2355['un' + _0x](_0x385c4a); break; } _0x7b2355[_0x394cbe](_0x385c4a); } } } } }(_0x12aca8, _0x4314f7, function(_0x28f1b0, _0x2ae9e5, _0x, _0x14fb7b, _0x8bf826, _0x11755b, _0x537a44) { return _0x2ae9e5 = '\x73\x70\x6c\x69\x74', _0x28f1b0 = arguments[0x0], _0x28f1b0 = _0x28f1b0[_0x2ae9e5](''), _0x = '\x72\x65\x76\x65\x72\x73\x65', _0x28f1b0 = _0x28f1b0[_0x]('\x76'), _0x14fb7b = '\x6a\x6f\x69\x6e', (0x134e3c, _0x28f1b0[_0x14fb7b]('')); }); }(0x18e, 0x6c4ae, _0x342b, 0xc9), _0x342b) && (version_ = _0x342b); (function(_0x1c9e5b, _0x5351dd) { var _0x = _0x56f8 , _0xd0dfd9 = { 'PQflt': '这个是一个本站对JavaScript\x20脚本的一个最牛加密,兼容性适中,解密难度极大' }; _0x1c9e5b['update'] = _0x(0xf7, 'sW9l'), _0x5351dd[_0x(0xfc, '7k)1')] = _0xd0dfd9['PQflt']; }(window, document)); function _0x342b() { var _0x407a63 = (function() { return [version_, 'EFyjWshNKjGFSiraCqmXeinP.cEoPAWmggk.RvL7==', 'pSonW4VdLxvJdSosW4md', 'WQaKmSosnSkIWPruFSoYW6u', 'ivvAWQCpWPNdUmo0W63cQq', 'jNxdLSkfnvNcPmon', 'WQqRnCoDmCkfWQHrsSohW7q'].concat((function() { return ['WO/dShRcRCkiz8oaW6VcU8os', 'ymkZWOKevGZcL8orW7ddO8klua', 'WQaJnSoz5BM2W7pdHEACSchcKUAvUfxcKXHdWQhcUqldV+AzUEAuGG', 'W6NcSNBdRConWOlcSgDjd8kby8kg', 'WQ5Ww8k8iSkHkmklDd4b', 'WRSeWQtdTCoaWPaGW4pcLCodySky', 'iIXhWRGRbt3dOW'].concat((function() { return ['ohVcPJu', 'W7alF3jzWO5wdSkAWRu', 'W6pdRLhdRr4eW550f8kPW6r2W68', 'W5PrWOSgW6mNv1NcNYdcUZm', 'WRSgWQxdVSkDW4K7W4lcV8ov', 'W5ldR3ahD8kCzmo6WPtcSSoPW6OQ']; }())); }())); }()); _0x342b = function() { return _0x407a63; } ; return _0x342b(); } ;var version_ = 'jsjiami.com.v7'; 


总结

以上,我们就介绍了接口加密技术和 JavaScript 的压缩、混淆和加密技术,知己知彼方能百战不殆,了解了原理,我们才能更好地去实现 JavaScript 的逆向。

参考文献

  • https://www.ruanyifeng.com/blog/2017/09/asmjs_emscripten.html
  • https://juejin.im/post/5cfcb9de853fa71c#heading-23
  • https://www.jianshu.com/p/cbd4fa
  • https://github.com/javascript-obfuscator/javascript-obfuscator
  • https://obfuscator.io/
  • https://www.sojson.com/jjencode.html
  • http://dean.edwards.name/packer/

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/111450.html

(0)
上一篇 2026-01-24 18:21
下一篇 2026-01-24 18:33

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信