【中等】 猿人学web第一届 第2题 js混淆 动态cookie 1

目录

  • 调试干扰
    • Hook Function
  • 加密参数定位
    • hook Cookie
  • AST 解混淆
    • 字符串解密
      • 还原解密函数
      • AST 配合解密函数还原字符串
    • ASCII 编码字符串还原
    • 字符串相加
    • 花指令(对象)
    • 剔除无用代码
      • 虚假 if
      • 剔除无引用代码
      • 剔除无引用的对象
      • 数值还原
    • switch 还原
    • 完整的 AST 代码
      • 代码
      • 注意
    • 还原加密
  • 请求代码

调试干扰

进入题目正常加载数据后
打开调试工具,等待一会(2~3分钟) 刷新页面 cookie 失效以后会弹窗
删除 cookie 中的 m 字段再刷新页面也是一样的
在这里插入图片描述
点击确定后,页面自动刷新完会进入 无限 debugger
在这里插入图片描述
查看上一层堆栈
生成 debugger 的代码 是经过混淆的
在这里插入图片描述
手动解混淆后的代码
在这里插入图片描述

(function () {// function 中的代码并不会执行,debugger主要是靠 ['constructor'](('debugger'))['call']('action') 执行
}['constructor'](('debugger'))['call']('action'))// function(){}['constructor'] 是 Function
// 上面的代码也也可以写成
Function.prototype.constructor('debugger')()

在这里插入图片描述

Hook Function

这个 debugger 是靠 Function 的构造器生成的
Hook Function.prototype.constructor 就可以过掉这个 debugger

let _Function = Function.prototype.constructor;
Function.prototype.constructor = function(Value){if (Value.indexOf('debugger') !== -1){return _Function.call(this, '')}return _Function.call(this, Value)
};

将代码在控制台运行就可以正常调试了
在这里插入图片描述

加密参数定位

数据接口在 https://match.yuanrenxue.cn/api/match 里
对应的请求参数为 page(页码)
在这里插入图片描述

加密参数在 cookie m字段在这里插入图片描述

hook Cookie

删除cookie中对应的 m 字段

在这里插入图片描述

hook cookie 找到 m字段加密的位置(加上 hook Function 的代码)

// Hook Function
let _Function = Function.prototype.constructor;
Function.prototype.constructor = function(Value){if (Value.indexOf('debugger') !== -1){return _Function.call(this, '')}return _Function.call(this, Value)
};// Hook Cookie
(function () {let cookie_func = Object.getOwnPropertyDescriptor(Document.prototype, 'cookie')Object.defineProperty(document, 'cookie', {get() {return cookie_func.get.call(this, val);},set(val) {if (val.indexOf('m') !== -1){debugger}return cookie_func.set.call(this, val);}})
})();

在这里插入图片描述

hook 到 cookie 后,向上查看堆栈就能找到生成 cookie m参数的位置
在这里插入图片描述

AST 解混淆

每次请求返回的代码都不一样,但执行逻辑是一样的,所以将 2.html 文件替换,方便调试
在这里插入图片描述

js代码是在 2.html 文件里,script代码 是被 script标签 包裹的(只需要将被标签包裹住的代码还原即可)
在这里插入图片描述
将代码 copy 到本地
在这里插入图片描述

字符串解密

先看看混淆代码

document[$dbsm_0x4638('\x30\x78\x34\x38\x39', '\x28\x37\x28\x5a') + $dbsm_0x4638('\x30\x78\x34\x61', '\x29\x69\x38\x67')] = _0x5eed8e[$dbsm_0x4638('\x30\x78\x33\x61\x36', '\x7a\x6b\x34\x53') + '\x79\x62'](_0x5eed8e[$dbsm_0x4638('\x30\x78\x63\x36', '\x64\x79\x2a\x5d') + '\x79\x62'](_0x5eed8e[$dbsm_0x4638('\x30\x78\x34\x65\x33', '\x64\x75\x52\x62') + '\x79\x62'](_0x5eed8e[$dbsm_0x4638('\x30\x78\x31\x62\x33', '\x44\x21\x4c\x4b') + '\x79\x62'](_0x5eed8e[$dbsm_0x4638('\x30\x78\x34\x62\x38', '\x54\x45\x58\x6e') + '\x79\x62'](_0x5eed8e[$dbsm_0x4638('\x30\x78\x34\x32\x65', '\x29\x69\x38\x67') + '\x79\x62']('\x6d', _0x5eed8e[$dbsm_0x4638('\x30\x78\x32\x64\x38', '\x6f\x38\x4a\x47') + '\x67\x61'](_0x2fdc55)), '\x3d'), _0x5eed8e[$dbsm_0x4638('\x30\x78\x33\x38\x31', '\x39\x52\x36\x32') + '\x70\x6d'](_0x691b6d, _0x29c654)), '\x7c'), _0x29c654), _0x5eed8e[$dbsm_0x4638('\x30\x78\x37\x38', '\x72\x69\x63\x50') + '\x62\x5a']);
location['\x72\x65\x6c' + $dbsm_0x4638('\x30\x78\x31\x31\x63', '\x6e\x34\x54\x28')]();// 解混淆后
document['cookie'] = (((((('m' + (_0x2fdc55())) + '=') + _0x691b6d(_0x29c654)) + '|') + _0x29c654) + '; path=/');
location['reload']();

还原解密函数

混淆的代码中有很多处字符串是 $dbsm_0x4638 函数生成的
查看 $dbsm_0x4638(解密函数)
在这里插入图片描述

解密函数依赖 $dbsm_0x23b3 数组
在这里插入图片描述

文件开头 $dbsm_0x23b3 是一个大数组 后经过一个自执行函数打乱排序
在这里插入图片描述
应在浏览器环境中先拿到 打乱排序后的数组 $dbsm_0x23b3在这里插入图片描述在这里插入图片描述
在断点处断住之后,copy大数组
在这里插入图片描述> 将 copy 到的数组拿到之后,替换到本地,(自执行函数就不需要了)
在这里插入图片描述

解密函数中 有很多 if 分支,在浏览器打上断点调试
这里大数组的值是对的,与浏览器相同
在这里插入图片描述
在这里插入图片描述
第一个 if 条件是通过的 通过以后进入了一个自执行函数 F9 或单机 在这里插入图片描述
进入这个自执行函数
在这里插入图片描述
首先会进入一个 try catch 块
在这里插入图片描述
查看 Function 里面的代码 在这里插入图片描述
执行这段代码后 浏览器返回的是 window (全局对象) / nodejs 返回的就是 global
在这里插入图片描述
在这里插入图片描述
atob在浏览器环境中是有的 但是在node中没有,node需要补上 atob 这个函数
true || true 不会执行后面的代码
在这里插入图片描述
后面的代码不会执行,所以 atob 还是一个系统函数 nitive code
在这里插入图片描述
在node中补 atob
atob = require(‘atob’); // npm installer atob
自执行函数执行完之后,给解密方法添加了一些属性之后,这个自执行函数就结束了
在这里插入图片描述

继续向下执行,查看这个 if 条件通过后的代码
打上断点后,F8 跳到这个断点或 单机在这里插入图片描述
在这里插入图片描述
前面都是定义,在执行方法处打上断点后直接跳到这个代码段,再单步调试查看这个函数执行了什么
在这里插入图片描述
做了一个 格式化检测
浏览器里的值是 true
在这里插入图片描述
在 node 值是 false,将 node 改写 写死为 true
在这里插入图片描述
在这里插入图片描述
上述的步骤做好后,解密函数就可以正常执行了,测试一下
在这里插入图片描述

AST 配合解密函数还原字符串

将代码拿到网站中查看对应的结构 AST explorer
在这里插入图片描述
需要遍历 CallExpression 类型的节点
并且 callee 属性为 Identifier 节点
Identifier 节点的 name 值为 $dbsm_0x4638
$dbsm_0x4638 是解密函数

// 安装 babel 库:  npm install @babel/core
const fs = require('fs')const traverse = require('@babel/traverse').default  // 用于遍历 AST 节点
const types = require('@babel/types')  // 用于判断, 生成 AST 节点const parser = require('@babel/parser')  // 将js代码解析成ast节点
const generator = require('@babel/generator').default  // 将ast节点转换成js代码// 读取(路径记得改)
const ast_code = fs.readFileSync('demo.js', {encoding: 'utf-8'
})let ast = parser.parse(ast_code)  // 将js代码解析成ast语法树// 这里插入解析规则
///// 解密函数中需要的 atob 函数
global['atob'] = require('atob');  // npm install atob
// 解密函数依赖的大数组
var $dbsm_0x23b3 = ["QjjDhA==", "IyQb", "552u776q5L6D", "eCvDoA==", "EHwT", "wpdVw6I=", "RArDvA==", "Hk8D", "MUvCnA==", "wotlw5k=", "w7xTwrU=", "wrLCvT0=", "w5LCvUc=", "w6hIwrY=", "w716Rw==", "L8OzwpI=", "MlMA", "Gm8r", "WcKVw44=", "W8KKw5s=", "w6bCgUE=", "TSnDpg==", "aEXCuw==", "HMOzwrc=", "wqs3Bg==", "KHsW", "AcOtwp4=", "N8KeIA==", "cifCig==", "wrBZw7M=", "AMKtw4g=", "FMOkwqA=", "WwEa", "DjzDqA==", "wo7CnAs=", "wpdoAQ==", "JsOfwp0=", "J8KRKA==", "ZsOCw58=", "wojCiAQ=", "w7vCuMKR", "ATY3", "ZyfCvQ==", "dCJD", "UMKpVg==", "O2US", "wqE3LA==", "SMOtwqk=", "w5PCh8Ki", "bMKyaA==", "S8OjEw==", "AcKGw68=", "wpVFw5M=", "fDvDpw==", "w7Brwqk=", "dGYb", "eC45", "AsOGwrE=", "w7fDhcKz", "YATDlA==", "DsK6w6A=", "wrNLw7U=", "biAN", "TxVF", "VzJ2", "wr3CrRc=", "wr0WEQ==", "YAvDrw==", "wqtZNg==", "K0QC", "Y8KBw6c=", "Q8KEw6E=", "wrUhKQ==", "CXfDjA==", "G34/", "esOcTQ==", "wpFiDA==", "w4xCaQ==", "Blo7", "w6vDvcKT", "eyFl", "BE8K", "w6HCvUs=", "wplqw6M=", "wqdOw5Y=", "wqzDr8KW", "XsKdcw==", "VMKsag==", "ecO9w58=", "EkcB", "wpJIw5U=", "JFrDiA==", "YsO7cg==", "eTvCiA==", "wojCuxc=", "WyXDmw==", "MUrDtg==", "w5XDhcKw", "fMKLcw==", "eMOhw5w=", "EGnCjA==", "RcKTYg==", "OALDvQ==", "HlE/", "Q8KGag==", "wpQpFA==", "wqg5wqw=", "ZsOqw4A=", "wp1Ewpk=", "wpkPwro=", "UT9O", "XsOmw7g=", "CFkm", "W0gI", "P8Ouwrw=", "eEMQ", "L8KSw7k=", "ecOvw4Y=", "WT9O", "J8KYfw==", "BiEH", "w7VnwpM=", "w6dxbg==", "wo/Ci8Os", "wqgpAg==", "wozCm8OB", "clHCjA==", "QsOsw6Y=", "woZew44=", "Zz7DnA==", "RgzDrg==", "XMKAVw==", "SwBb", "VMKCSg==", "Ryp1", "wr9Mw44=", "w4rDqMK7", "UMOiw6E=", "w6fDo1U=", "VMOEw4c=", "EcKew4c=", "c8KRZQ==", "WsOOUQ==", "wodyLA==", "e8KMUg==", "w5TDln0=", "GcKbw4s=", "BMK0w7Y=", "wpIewoU=", "R8Kcw6k=", "wobDuMOi", "BsO/wp4=", "VcOnw6w=", "w5t0wok=", "wqgPwpA=", "woTCu8Or", "fg3DvQ==", "L8KEw6g=", "wphswpI=", "woYgIg==", "AXgq", "VTLCqg==", "wrRww4Q=", "wqM1Ig==", "YCzDjQ==", "EVkx", "PWsV", "JWbDjw==", "DF4M", "WcObw54=", "DMKXw6w=", "EcKmOA==", "WsOJw58=", "ajsY", "SsK1w4Q=", "w4zDqMK0", "Gics", "UTkL", "w754wrA=", "IBw2", "wopkDA==", "NFEb", "EFHDig==", "W8Okw40=", "C8KpVg==", "EmnDsQ==", "VhvDmA==", "wqTCoMOV", "fcOfw6A=", "JsKkNw==", "ecOjKg==", "aSTDsA==", "woYfOg==", "YcOyYA==", "fMOtw4E=", "eMOSw5A=", "w7jCn8KA", "LGI2", "asO0Ow==", "f2cW", "egvDuA==", "GcOeGQ==", "w4NYQw==", "IMKvw68=", "wrfDpsO6", "BcKjJA==", "w6PDu2g=", "ayTDrA==", "B0kt", "QsKTVg==", "wpvCuMO1", "YsOHw6M=", "B1XCuA==", "B8Kjw5w=", "Q8Oqw6g=", "RMOAw4c=", "w4/DssK0", "w4rDm8KQ", "ScOwQg==", "YsOGw5s=", "RjbDjQ==", "SCLDpg==", "VcOVMQ==", "KnHCgQ==", "JMONwrU=", "WcO/Cw==", "YcKuRQ==", "wr0MCw==", "WAHDnw==", "esKuUg==", "wp8mNA==", "MMOAEw==", "bcOBw4w=", "w5LCl8K/", "KXk3", "agpl", "wprChSg=", "w5BmYw==", "S2zCrg==", "BXIv", "EMOUwpA=", "WcKvVg==", "WsKkw4I=", "w69iwqQ=", "e8KYVw==", "Y8Ojw6s=", "KUUk", "LcOYwq0=", "Xj/DvQ==", "RiXDkg==", "wrbDiMOj", "Ujd6", "cAc+", "dzt2", "QsO9w6w=", "Ghg3", "ccKkcA==", "fRvDkA==", "KcK4Og==", "H30u", "PMKyw4Y=", "YyrDtw==", "wpDCiMOh", "wqwowoc=", "wojCjDQ=", "wqHCj8OU", "w7HCm8KR", "XsOVw7Q=", "w47Cp8Kj", "w6LCnMKo", "GsKMbw==", "w5J0wrU=", "RCnDuA==", "wpfCgjE=", "wrMnBw==", "w7bDqsK/", "KEM4", "a8OKwrw=", "wpBlw5Q=", "MTAo", "X8K2w5I=", "WsOvFQ==", "Yz7DkQ==", "W8Ocw54=", "ahtQ", "D2vDrg==", "VsKcw4o=", "Fy/CkQ==", "JnAI", "MMOswrA=", "w4zDt8KI", "wrDCksOj", "GBcc", "fcO9Sg==", "w4HDgXY=", "MsKeHA==", "ccOBw4o=", "QsOgw4M=", "Q8OjBg==", "EMK5FQ==", "R8OCw6o=", "XS9D", "d8KfcA==", "wpbCmSE=", "w4XChn8=", "aMKieA==", "woVhGQ==", "wo7CnsOK", "AXwd", "dCAI", "worDhsOC", "V8Krw4A=", "VxHCvA==", "woFywrg=", "w4ZRaA==", "VMO5w6Q=", "wp1zHg==", "wqw/wqo=", "BMKRw58=", "wpxjw7U=", "McKEw4o=", "YyIF", "fkME", "wp1xw6o=", "Sg80", "HMKbAQ==", "HHoX", "MsK7Cg==", "woZWCw==", "GsOKwrE=", "P8KPGg==", "bBDDhw==", "ewLDng==", "TSMk", "wrbCrT4=", "w7tkRg==", "DDQv", "wrdpLw==", "wonDmsKK", "Tx8o", "WMODw7I=", "MXgT", "w6PCrUw=", "wobCg8OR", "Z8Odw6U=", "w55LwrA=", "O8ORwqU=", "w5vDo10=", "wq3Cl8OT", "asKMUQ==", "woBpPg==", "SnPCrA==", "wo7Dn8KG", "wqVtw54=", "wo9WNA==", "QMObNw==", "TMKAw4Y=", "eHEn", "w5rDqcKk", "wqRlw68=", "CxYO", "WcK2VA==", "wpgrAw==", "wpHCgw4=", "wrHCklU=", "BkIZ", "woh4wqM=", "wpBICg==", "AcORGg==", "wpd0NQ==", "w4HDqsKa", "YcKvew==", "wpvCusOs", "K8K5JA==", "w7LCrGU=", "XkUT", "XMOow6s=", "w7/DqcKj", "NsOdwqQ=", "VcOsw7Q=", "eXED", "McKbdA==", "AHXCow==", "K8KeQg==", "ZgMB", "Hm4g", "f8Oqwow=", "AHPDpA==", "wq4Mwq0=", "WsKeYg==", "fDjCog==", "wpY/PQ==", "V8K9cg==", "OlAN", "esO8Xw==", "GsKaJA==", "WgjDnQ==", "DW7CrA==", "f8K1Qg==", "eSw0", "RAIx", "Cls9", "FMOYwqM=", "w4bCvVE=", "wovDkMKK", "WsK/Tw==", "QRrDgw==", "wpV9w4o=", "wrXCmxA=", "wpXChik=", "wq5kw7g=", "wo5jPA==", "w5VgZQ==", "wr1Cw4o=", "wpBYw60=", "woVOwpw=", "wpB2Cg==", "cBlA", "wo52Cg==", "QcO/w58=", "w65UwrM=", "fyfCng==", "w6TCp2s=", "wrRWJQ==", "w7bCv8KW", "XsKyeQ==", "MWbDiQ==", "w4jDscK1", "d8K1w4U=", "C34+", "wprDt8O9", "VsKlw7E=", "w4JdfQ==", "wos1Jg==", "PE7DuA==", "w4bDnsKM", "w5XDq8KA", "JTIy", "w5LDpMKu", "YArDsQ==", "K8K9IQ==", "DsKmw7E=", "BMKxw7A=", "wrvDncKg", "dzrChQ==", "G1nCjg==", "YEYA", "OsKzJg==", "wrfCugs=", "XlvCkA==", "fcKDw54=", "e8OMw40=", "wpBDw68=", "w45CwoY=", "WsONwpw=", "BFDCiQ==", "w7VidA==", "Aloq", "w73Cq8KT", "IkE4", "wqN0Nw==", "dBLDmw==", "wqlRw44=", "w7lleQ==", "C1TCgQ==", "PsKPJQ==", "VcK0bg==", "XcOBwo4=", "VMOjZQ==", "w7pjXg==", "wrBvFw==", "cARj", "w4JSaQ==", "MsK4w4Y=", "acOeeQ==", "AsOQIQ==", "wqUDBQ==", "X1Zb", "RMKKaA==", "w6fDs8KB", "HsKzdw==", "V8OJLA==", "XMOFwqo=", "V8Kybw==", "w5zDhG4=", "wrFHNQ==", "RcOhw6s=", "w6Vhbg==", "XcOow48=", "w5bCi24=", "NkfDgw==", "AcOyHA==", "XUzClw==", "w5XCgGY=", "w5rDhVA=", "a1c3", "WnzCsw==", "wrvDncK4", "w7pUwqk=", "QT1j", "DmLCuA==", "w69tVA==", "w6bCvMK+", "cVUo", "dcO8wqc=", "cBlK", "w5zDhWc=", "wpt+w6w=", "w6lFwrI=", "wojDiMOS", "XcOZw78=", "UwhO", "wotmw4M=", "RC4Y", "w77CjU0=", "S8O3w6U=", "PGAG", "WsKowq8=", "wqTDmsOo", "Hlo8", "I8OuwqQ=", "c8OAKA==", "cl7Cmw==", "V3PCvA==", "DnM2", "wqQTGQ==", "WWYV", "wozDosOV", "w7fDisKb", "csO+w4A=", "IsKiPw==", "w75iQA==", "Ww7CgA==", "wqtrLA==", "fsKtw6c=", "DsKbw5M=", "w5fDgMKO", "wrcaIQ==", "S1c5", "wrMaOQ==", "AcKIcA==", "Cjww", "w6VWYA==", "OQom", "ZxjDjQ==", "wrMoNw==", "VQXDmA==", "d8KeYQ==", "BEs8", "J0k9", "wpEeEQ==", "wqAHFQ==", "w6/DicKx", "ScOiCg==", "YxXCtg==", "dsOiw4k=", "THjCqQ==", "HMK+AA==", "wpQhHw==", "wr7CvcOq", "K0bDiw==", "eMOAcg==", "w60rdg==", "L1IC", "woNlw60=", "K8KDw4k=", "wrpFDg==", "wpFEMw==", "w6fCrGw=", "wo0mCA==", "cUTCtQ==", "w7LCqMKX", "W8OiwoQ=", "QAvDqQ==", "AD03", "aDfDiQ==", "UTHDpQ==", "ZhMa", "w6bDrMKs", "AkvCuw==", "wo8yBQ==", "wo4IPQ==", "M3QK", "TwrDnw==", "wqFcDw==", "e8O7bA==", "PkHDlg==", "esOBwqk=", "eRFw", "ZyvCnw==", "w7PDtcKx", "wpQ1woA=", "WwFc", "XRsF", "BMOCPQ==", "SHHCjA==", "XcOew5w=", "wqhaKA==", "YynCvg==", "XS3Chg==", "BFI0", "wr9HDA==", "wpx7w5o=", "w6DDmHU=", "bA84", "I3AA", "w7jCn2s=", "BWPClw==", "wpbDt8O1", "wpsKYw==", "wq9jw5I=", "woFQwp4=", "wpI9Mw==", "B8KwEQ==", "DmYq", "CcKbAQ==", "TS49", "w6bDvWU=", "YsOVNw==", "dMKBRQ==", "NXg8", "wrBJwoI=", "KsKAYQ==", "EcKNdQ==", "ecO7OA==", "wrV6w7I=", "WMOSw6Y=", "wqV6wqI=", "VcKyUA==", "fcO4Sg==", "IXQl", "Z8KaXw==", "VnvCnQ==", "wr9qOg==", "w6PDiGs=", "QD0a", "wrzCm8OQ", "w6LCp1w=", "bMK+w6A=", "w7PDn24=", "T2LClg==", "woBJw7c=", "SiPDjQ==", "wqbChTI=", "Wj3Dpg==", "fxgU", "YhzCuA==", "ETsw", "W8OdCA==", "GcOxIg==", "Kxkw", "B2zCuA==", "OBER", "Cl4R", "wrLDpMK8", "wq/CnsOZ", "w5XDv8Kw", "dysc", "Y8KjVQ==", "fcOvw40=", "CWjDug==", "bMObNg==", "ScOEw4c=", "w6RTwqM=", "wpJLEw==", "BTw5", "ScKDw4c=", "XMKbw5o=", "TxjDhw==", "w5pOew==", "wpJawp0=", "ZsKwQQ==", "FGMO", "GMKRw7o=", "QMO+OA==", "wrtaMQ==", "TMOUMA==", "J3jDuA==", "D8OnwqA=", "w7zCgcKv", "VnLCmw==", "Z8OJw4I=", "bADDng==", "ccKCZg==", "wrIUJA==", "XCHDow==", "w6DCsV8=", "ZsKafw==", "w5J7fg==", "M8OMwps=", "w7DDt8KG", "W8OYXw==", "EHDDhw==", "w63ChsKU", "O8Kiw4k=", "wrlxDA==", "wrnCkcON", "wqFfHg==", "wovDsMKh", "w67CmMKk", "w75Pwq8=", "wq/DnMKX", "SyhS", "wp1uOA==", "wr3Dt8KG", "DnI2", "OWEf", "w5PDisKX", "wr3CuRE=", "YBJu", "wrxgw58=", "wrEEIQ==", "Uy53", "V2/CjQ==", "ecOjw6Q=", "SMKjw5s=", "X8O5w7Y=", "RsK3w50=", "wpA+wro=", "aynDjQ==", "ccO5w6E=", "ezjCjw==", "BMOPJQ==", "w7FFwq8=", "QsOnw6Y=", "w5VRQQ==", "HmkA", "f8Oewr0=", "dsO7w78=", "w7PDrcKT", "w4vCr3E=", "X8O6w7s=", "CRTDqQ==", "VcO8w54=", "KmjDrA==", "w4dSfQ==", "BG7DpQ==", "bMOvw54=", "bi5F", "VDjDpQ==", "w6HCiFo=", "aMOYCA==", "w5fDqE8=", "CXbCpg==", "FMKwIg==", "w4BxSQ==", "QTbDow==", "J2si", "MsOxwpI=", "IsOdHA==", "wojDlsKP", "Hn44", "bMOQRg==", "dMKCWg==", "w7rDnF4=", "B8K5w58=", "WSjDpg==", "XsO5w5g=", "QTo7", "wqUZwoM=", "ecK1aA==", "esKDUA==", "woFCwrE=", "woISwos=", "dsODEw==", "McOrOQ==", "JVTDmA==", "XcKxbw==", "wqZZBg==", "OsKjFg==", "UQTDkg==", "woh3w4A=", "w5FXwpM=", "wpJAw7w=", "Ongr", "w41zwos=", "N8OGDw==", "w6DDicKj", "UQ0U", "CsKCTw==", "fTnDhA==", "w6TDqHA=", "AloY", "CV4e", "DsKJbQ==", "LyoG", "OFnChA==", "NFsh", "w596fA==", "w6FsYA==", "Pm/Chg==", "wrZ1Ew==", "wprDmcKo", "C3QW", "wo7CqDM=", "woYANg==", "wq3Dl8Ok", "wp7DlcKp", "csKXeA==", "wqVyHA==", "wptxw6k=", "IMOIwpE=", "HcKkw78=", "XzXDsg==", "Q8KAw48=", "QMOOWg==", "V3TClA==", "woY5Pw==", "K2jCng==", "c8OewoY=", "w5zDqVY=", "Al/Cmg==", "w7TDp8Kg", "wpjCoiU=", "G8ONAA==", "w7rCjMKO", "RSjDsg==", "esODbg==", "EWcq", "NsK4BA==", "PcKeEQ==", "GcOpJw==", "cTpO", "wrzDl8Kv", "CcKSw7I=", "fhPDpw==", "wqcfLg==", "B8KiIQ==", "OcKQw78=", "SjHDug==", "w4vDvcKd", "wq8kGQ==", "HH8J", "DVbDsg==", "LXHDrA==", "WCpe", "N8OjGQ==", "MVrDjA==", "ZB/Dpg==", "w7xvwpE=", "WwjDvA==", "wo4cIQ==", "esOvEw==", "wpJRw7Y=", "TRNg", "wrZ0Ag==", "dcOLcQ==", "bsKAw6E=", "wqdoPg==", "XDrCgg==", "wosKPw==", "bwTDvw==", "XQAy", "wpAUwoU=", "dB4t", "wpFRNw==", "UMKwQQ==", "ecOlw48=", "w6TChMKP", "XxFP", "A8K5Pg==", "w5dbfg==", "woDCtcOn", "IE3Cqg==", "JUvCqg==", "HzYw", "ecKEaA==", "fQEi", "fQR3", "J8KsEQ==", "b8Ofw6U=", "MsK6Jg==", "w7bDsMKT", "wqxuwps=", "XxPCrg==", "JcKQbg==", "FsOtAw==", "RcOBw6U=", "YcOxUg==", "EnAz", "ci8a", "VcO9w6E=", "Qj7Dvg==", "YMKEeQ==", "wqLDiMKl", "w5xawoM=", "TMOow6k=", "eRjDpQ==", "DXjCgQ==", "wq87HA==", "w5jCrMKw", "YsKzVw==", "fcOrwq8=", "wpNxw40=", "BgIo", "YcOEw6Q=", "BsKkw7M=", "L1XDiQ==", "DMKeaQ==", "cT3DmA==", "WDtL", "HVQy", "YTzDow==", "TsOZw5A=", "wpLCnSI=", "Ri8m", "w4fDiU0=", "ah5R", "w4TCuEs=", "w6bDusKY", "dgDDow==", "RAx3", "w71XVg==", "X8Obwoo=", "wrfDi8Kd", "ZsO+w5o=", "cB9B", "BH4p", "USBR", "w4bDksKn", "dSXDmQ==", "YMKew4A=", "V8O9BQ==", "wooxGQ==", "VX/Csg==", "XsOEw6Y=", "wrofBg==", "wpUBBw==", "wq87Gg==", "w4HCo0E=", "wpnCrAw=", "asOGwok=", "wqTChyA=", "wr91KA==", "FsKSLg==", "w5LDrMK5", "UxTDqw==", "JCMb", "IlfDmg==", "a8ONYA==", "IMO/wqM=", "OsOMwoI=", "YnM7", "YcOhcA==", "ZgDDhw==", "fcOnwq8=", "QAJu", "METDqw==", "HMKYRQ==", "IsKBw4g=", "wq9Cw5Y=", "WsOZFw==", "wrZkw60=", "aTAu", "bzgc", "RcOPBw==", "wqhlMQ==", "eMOrw48=", "O8Kjw68=", "STbDjA==", "wqvDgsOf", "G8K0bw==", "DsKdfQ==", "w4HCgWY=", "bgHDvw==", "CXPDlg==", "woFJFQ==", "wqDDlcKF", "QADDtg==", "w7tkSQ==", "Vgo3", "BEUK", "wrN2DA==", "wrHDlcKk", "XMOiEQ==", "wq/CnCU=", "QcKUUw==", "ODRV", "wpJuwpc=", "w67DkXY=", "NMOwwr0=", "VD8w", "KG4V", "acOAwqg=", "LMKWKg==", "wrLDmsK7", "a8K3bw==", "w6nDlMKA", "Y8OJw4s=", "w7xjSQ==", "AMKOdg==", "ay9S", "woFUPg==", "DcKVbA==", "Q8ODw4Y=", "w6JkTw==", "wrx5Hg==", "wr/DhsKl", "wo9QMQ==", "bSXDrg==", "eMOrWA==", "GMKpw78=", "w6fDuns=", "wqnDuMKI", "I1rDug==", "IHsb", "wqJMHw==", "OMOdwoM=", "HW4u", "w6JFQQ==", "wrJHEg==", "wpZcw7U=", "wq1tGw==", "wol2wog=", "w6nCu0s=", "wpLDl8KP", "woPCusOl", "wr7CtMOG", "wofDgsO2", "wprCuys=", "cD7Dhg==", "BWMM", "GMKYPA==", "WMOOw44=", "w4VFXA==", "w7DDmk0=", "F8KDOg==", "wo8jCQ==", "bcKEw44=", "aCkH", "cV0v", "aMO9Dg==", "cMOjw5E=", "CiM0", "Sy0W", "dTPCug==", "FsOuwp4=", "BkAs", "ZnkQ", "w7oxw4I=", "WMOPw4w=", "wqvCvyI=", "SRbDow==", "YinCjQ==", "cz4p", "w6PCqsKV", "VgVq", "BCE2", "w5LDrV4=", "TcO2Jw==", "eyRA", "a8Ouw7o=", "J1jDog==", "QcO5w40=", "FkvDjA==", "GMKpLg==", "ZwTDsg==", "wqzCsMOJ", "YS7ClA==", "w4bCuk0=", "ZMOOIA==", "wo4fwpQ=", "S8K6Vg==", "QcObw6U=", "wq9DHQ==", "IXgZ", "FFwc", "wqhvOA==", "wqBnwrw=", "QsOfJg==", "NW8A", "RRPDow==", "VAIr", "D8Kaw4s=", "X8OcGQ==", "JGEU", "eMKTbg==", "Y8OYbA==", "XcKaRQ==", "FMOrAQ==", "fwjCoA==", "wqnDhMK7", "wqkVwq8=", "P8KUfQ==", "Yh7DpA==", "BAsm", "RMK2w50=", "PcOwKg==", "CcKbw6w=", "HsKWTw==", "eyrDmA==", "woDDi8KC", "A2fDjw==", "YRTDlg==", "UsOow64=", "LCsE", "wo4dOg==", "wphxwpE=", "woUcAA==", "wqMfAA==", "TMKAw4U=", "GsKDw7k=", "PTE8", "wrlPGA==", "wqPDn8OT", "ZcOBw60=", "wrjCuMOq", "W8Kmw5k=", "XMOaw7k=", "wqxzwpM=", "fhDCqg==", "QMO+w7E=", "DVgs", "w6lSwrg=", "VMOHw6g=", "P8Oowrg=", "w7zDqHk=", "wq4CAw==", "wqpTDw==", "bDpH", "QcOYw4M=", "SBkv", "worCicOp", "wo0hGQ==", "w5JgWA==", "YQ5g", "AsK+Xg==", "XMOEwoo=", "ZiAN", "IsKsBQ==", "w6PDpVw=", "wrrCjSY=", "TcK+w6M=", "wp/DkMKL", "fhwQ", "ZHcF", "VDXDqw==", "w7rDg8Kg", "w5pywpc=", "UH3Cqg==", "AMOJwpI=", "wpxwwrU=", "SsONwo0=", "Az8p", "U2fCnA==", "wrLDlcKB", "XSlH", "QcOhKA==", "LG7CnQ==", "w6LDlsKm", "w5hkYQ==", "wqvDi8OU", "wo7CqDE=", "fAvCgQ==", "G8Kzw7A=", "YVAg", "wo/CnSY=", "Dk7CgQ==", "RzzCmw==", "P8OdAA==", "wqFcDQ==", "K8KVSA==", "woVawp8=", "JnEi", "w67DmsKc", "w6JRTw==", "DMK9cA==", "aBhR", "Zi4W", "dhzDvw==", "RsO7wq4=", "ecOcw6E=", "JcOmwqY=", "EcKwVg==", "WsKXeg==", "Byo1", "ElYq", "BloJ", "XMO4Ew==", "wo5+w7g=", "Mkk8", "wqAhJw==", "bjjDuw==", "w7bCpsKR", "Z8O7aw==", "d3fCvw==", "wpbDpcOF", "ScK7w7I=", "CkfDjg==", "ecOafA==", "YMOBw4A=", "wo0dwq4=", "dsKWTQ==", "DcKQZA==", "IEvCpw==", "w7fDulQ=", "aXnCkg==", "woMpJg==", "fWQq", "NnPDkQ==", "USBV", "U2gZ", "RsKBZw==", "e8K/cg==", "WMK5w4s=", "wrFww5I=", "w5PDhHk=", "ZsOxwos=", "wp3DisKX", "w7DCmVg=", "w6x4Rg==", "LH4K", "O20W", "ZMOZw7U=", "PMKfaA==", "bRhn", "Izwv", "w4cfwqU=", "w4fCpG0=", "aBvDoA==", "RMKveA==", "QcOxSg==", "V8K7cw==", "J8KeQg==", "w4LDiX0=", "IsKSUQ==", "VQXDkw==", "LXMp", "IsKgw6w=", "TCU4", "ayl1", "w6TDksK+", "Zn0Q", "AHbDug==", "w7JSwpg=", "G8OpwoM=", "fS1h", "wrxxw4s=", "wogKAw==", "wpYvwqA=", "eWXCkw==", "U8Ofw70=", "e2sT", "woUBAw==", "w6LDjmw=", "a8OPw54=", "U8KHbw==", "HTA7", "wonDs8Kk", "BFQG", "w5PDolU=", "ciXDkA==", "NcOSwrg=", "fCTDow==", "woYuwpQ=", "alQl", "S8Kbw5U=", "woRaw7M=", "E34q", "O8KdJg==", "WAHDng==", "w6DCmnA=", "OkYH", "Y8KWRQ==", "w5VNwpk=", "I0HDpg==", "wrQSJA==", "aQ9P", "HcKBw6g=", "eQnDsA==", "wpAcOw==", "w5HDmsKC", "w5tWwrs=", "ecOcIQ==", "JcKvMA==", "bRh5", "cB0F", "VjTDgA==", "wptrw7s=", "WDnDrw==", "Rz09", "wpYdAA==", "wrpUwpM=", "DcKifg==", "wp/DusKm", "wqAoOg==", "a17Cmw==", "J2k1"];
// 解密函数
var $dbsm_0x4638 = function (_0x1e1b14, _0x23b316) {_0x1e1b14 = _0x1e1b14 - 0x0;var _0x4638d3 = $dbsm_0x23b3[_0x1e1b14];if ($dbsm_0x4638['lIzlCZ'] === undefined) {(function () {var _0x4b121c;try {var _0x1d5b59 = Function('return\x20(function()\x20' + '{}.constructor(\x22return\x20this\x22)(\x20)' + ');');_0x4b121c = _0x1d5b59();} catch (_0x4f5869) {_0x4b121c = window;}var _0x55f54d = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';_0x4b121c['atob'] || (_0x4b121c['atob'] = function (_0x2337bc) {var _0x94736f = String(_0x2337bc)['replace'](/=+$/, '');var _0x5e548f = '';for (var _0x588d26 = 0x0, _0x5d3f20, _0x558d8e, _0x49832a = 0x0; _0x558d8e = _0x94736f['charAt'](_0x49832a++); ~_0x558d8e && (_0x5d3f20 = _0x588d26 % 0x4 ? _0x5d3f20 * 0x40 + _0x558d8e : _0x558d8e,_0x588d26++ % 0x4) ? _0x5e548f += String['fromCharCode'](0xff & _0x5d3f20 >> (-0x2 * _0x588d26 & 0x6)) : 0x0) {_0x558d8e = _0x55f54d['indexOf'](_0x558d8e);}return _0x5e548f;});}());var _0x2ef3c5 = function (_0x49a1eb, _0x27f9fb) {var _0x26a837 = [], _0x90ed46 = 0x0, _0x1e184c, _0x229955 = '', _0x28a13b = '';_0x49a1eb = atob(_0x49a1eb);for (var _0x4237c8 = 0x0, _0x18c69a = _0x49a1eb['length']; _0x4237c8 < _0x18c69a; _0x4237c8++) {_0x28a13b += '%' + ('00' + _0x49a1eb['charCodeAt'](_0x4237c8)['toString'](0x10))['slice'](-0x2);}_0x49a1eb = decodeURIComponent(_0x28a13b);var _0x2c4f5b;for (_0x2c4f5b = 0x0; _0x2c4f5b < 0x100; _0x2c4f5b++) {_0x26a837[_0x2c4f5b] = _0x2c4f5b;}for (_0x2c4f5b = 0x0; _0x2c4f5b < 0x100; _0x2c4f5b++) {_0x90ed46 = (_0x90ed46 + _0x26a837[_0x2c4f5b] + _0x27f9fb['charCodeAt'](_0x2c4f5b % _0x27f9fb['length'])) % 0x100;_0x1e184c = _0x26a837[_0x2c4f5b];_0x26a837[_0x2c4f5b] = _0x26a837[_0x90ed46];_0x26a837[_0x90ed46] = _0x1e184c;}_0x2c4f5b = 0x0;_0x90ed46 = 0x0;for (var _0x4fe42c = 0x0; _0x4fe42c < _0x49a1eb['length']; _0x4fe42c++) {_0x2c4f5b = (_0x2c4f5b + 0x1) % 0x100;_0x90ed46 = (_0x90ed46 + _0x26a837[_0x2c4f5b]) % 0x100;_0x1e184c = _0x26a837[_0x2c4f5b];_0x26a837[_0x2c4f5b] = _0x26a837[_0x90ed46];_0x26a837[_0x90ed46] = _0x1e184c;_0x229955 += String['fromCharCode'](_0x49a1eb['charCodeAt'](_0x4fe42c) ^ _0x26a837[(_0x26a837[_0x2c4f5b] + _0x26a837[_0x90ed46]) % 0x100]);}return _0x229955;};$dbsm_0x4638['UYyCMO'] = _0x2ef3c5;$dbsm_0x4638['nMtFyB'] = {};$dbsm_0x4638['lIzlCZ'] = !![];}var _0x57b28f = $dbsm_0x4638['nMtFyB'][_0x1e1b14];if (_0x57b28f === undefined) {if ($dbsm_0x4638['DwWKuR'] === undefined) {var _0x9e4186 = function (_0x3712d5) {this['kHsRXo'] = _0x3712d5;this['nWOEyU'] = [0x1, 0x0, 0x0];this['tpblbK'] = function () {return 'newState';};this['lAcsth'] = '\x5cw+\x20*\x5c(\x5c)\x20*{\x5cw+\x20*';this['foeeRg'] = '[\x27|\x22].+[\x27|\x22];?\x20*}';};_0x9e4186['prototype']['RuyyZP'] = function () {var _0x20d28 = new RegExp(this['lAcsth'] + this['foeeRg']);var _0x5e0e5f = true ? --this['nWOEyU'][0x1] : --this['nWOEyU'][0x0];return this['XVTLWU'](_0x5e0e5f);};_0x9e4186['prototype']['XVTLWU'] = function (_0x3ab8dc) {if (!Boolean(~_0x3ab8dc)) {return _0x3ab8dc;}return this['HxFvMA'](this['kHsRXo']);};_0x9e4186['prototype']['HxFvMA'] = function (_0x13037d) {for (var _0x3bdd37 = 0x0, _0x49b603 = this['nWOEyU']['length']; _0x3bdd37 < _0x49b603; _0x3bdd37++) {this['nWOEyU']['push'](Math['round'](Math['random']()));_0x49b603 = this['nWOEyU']['length'];}return _0x13037d(this['nWOEyU'][0x0]);};new _0x9e4186($dbsm_0x4638)['RuyyZP']();$dbsm_0x4638['DwWKuR'] = !![];}_0x4638d3 = $dbsm_0x4638['UYyCMO'](_0x4638d3, _0x23b316);$dbsm_0x4638['nMtFyB'][_0x1e1b14] = _0x4638d3;} else {_0x4638d3 = _0x57b28f;}return _0x4638d3;
};
// 解密函数还原字符串规则
traverse(ast, {CallExpression(path) {  // 遍历 CallExpression 节点// callee 属性为 Identifier 类型// 且 name 属性为 $dbsm_0x4638 解密函数名if (types.isIdentifier(path.node.callee, {name: '$dbsm_0x4638'})) {console.log('遍历到的节点: ', path + '')// 取出对应的参数// 例: $dbsm_0x4638('\x30\x78\x32\x39', '\x72\x69\x63\x50')let callArg = path.node.arguments;  // 例 ['\x30\x78\x32\x39', '\x72\x69\x63\x50']let arg1 = callArg[0].type;  // 例 '\x30\x78\x32\x39'let arg2 = callArg[1].type;  // 例 '\x72\x69\x63\x50'// 将对应的参数取出后, 拿到 $dbsm_0x4638 解密函数执行let result = $dbsm_0x4638(callArg[0].value, callArg[1].value)// 将对应的节点替换成 解密函数执行后的结果// 例//    将节点:  $dbsm_0x4638('\x30\x78\x33\x66\x36', '\x68\x32\x25\x5e')//    替换成:  "hei"path.replaceWith(types.valueToNode(result));console.log('替换后的节点: ', path + '')console.log('==============================');}}
})///js_code = generator(ast).code  // 将ast节点转换成js代码// 写入(路径记得改)
fs.writeFileSync('New_demo.js', js_code, {encoding: 'utf-8'
})

解析前的代码
在这里插入图片描述
解析后的代码
>

ASCII 编码字符串还原

还原思路在 1. js混淆-源码乱码 中有提到

// ASCII 码还原
traverse(ast, {StringLiteral(path) {if (path.node.extra) {console.log('ASCII码替换前: ', path.node.extra);path.node.extra.raw = `'${path.node.extra.rawValue}'`console.log('ASCII码替换后: ', path.node.extra);console.log('============================================================');}}
})

效果
在这里插入图片描述

字符串相加

demo.js

'a' + 'b' + 'c' + 'd';
'e' + 'f';

AST.js

// 字符串相加
function strConcat(path) {for (let i = 0; i <= 2; i++) {let node = path.node// left 节点为 StringLiteral 类型// right 节点为 StringLiteral 类型// operator 操作符属性为字符串 +if (types.isStringLiteral(node.left) && types.isStringLiteral(node.right) && node.operator === '+') {// 例 'e' + 'f'console.log('字符串相加前: ', path + '');// 例 'e' + 'f'let result = path.node.left.value + path.node.right.value;// 例: 'e' + 'f'// 替换成: 'ef'path.replaceWith(types.valueToNode(result));console.log('字符串相加后:  ', path + '');console.log('============================================================');} else {// 递归是针对多个字符串相加的// 例当前遍历到的节点: 'a' + 'b' + 'c' + 'd'// 这个节点在上面是不会处理的// path 对象的 traverse 方法是从当前节点继续遍历// 传入 strConcat 方法的节点就为:  'a' + 'b' + 'c' + 'd'// 调用过后还是会再次进入到 path.traverse 因为还是会有多个字符串相加// 上一次传入的节点被处理过了// 所以这一次传入的节点代码就为 'ab' + 'c' + 'd'// 一直递归到节点为 'abc' + 'd' 就会停止递归// 'abc' + 'd' 在 for 循环中会二次处理 (可以试着for循环只遍历一次看看效果path.traverse({BinaryExpression(path_) {strConcat(path_)}})}}
}traverse(ast, {BinaryExpression(path) {  // 遍历 BinaryExpression 节点strConcat(path)}
})

效果
在这里插入图片描述

花指令(对象)

demo.js

let obj = {};
obj['StringLiteral'] = 'abc';
obj['BinaryExpression'] = 'abc' + 'def';
obj['funcCallExpression1'] = function (a, b){return a(b);
}
obj['funcCallExpression2'] = function (a){return a();
}
obj['funcBinaryExpression'] = function(a, b){return a + b
}let c = obj;
let d = c['StringLiteral'];
let e = c['BinaryExpression'];
function demo(){}
let f = c['funcCallExpression1'](demo, '123');
let g = c['funcCallExpression2'](demo);
let h = c['funcBinaryExpression']('1', '2');

AST.js

// 花指令
traverse(ast, {VariableDeclarator(path){  // 遍历 VariableDeclarator 节点if (types.isObjectExpression(path.node.init)){  // init 类型为 ObjectExpression 类型let objName = path.node.id.name;  // 获取对应的标识符let objBinding = path.scope.getBinding(objName);  // 获取标识符对应的引用let objRefer = objBinding.referencePaths;  // 获取标识符引用对应的数组let newObj = {}// 将给对象属性赋值的所有变量存入 newObjfor (const refer in objRefer){  // refer 为索引值从 0 开始// objRefer[refer] 为 obj// objRefer[refer].parentPath 为 obj['str']// objRefer[refer].parentPath.parentPath 为 obj['str'] = 'abc'let grandPath = objRefer[refer].parentPath.parentPath;  // 获取该节点的整段代码// 该节点的类型为 AssignmentExpression 类型// 节点中 left 属性的类型为 MemberExpression 类型if (grandPath.isAssignmentExpression() && grandPath.get('left').isMemberExpression()){// obj['str'] 中的 str 字符串let key = grandPath.node.left.property.value;  // 获取 .property.value 的属性,作为新声明对象中的keynewObj[key] = grandPath.node.right;  // right为该属性对应的 node 节点,直接存入 newObj 对象即可}}for (const refer in objRefer.reverse()){let grandPath = objRefer[refer].parentPath;if (grandPath.isVariableDeclarator()){  // 该节点的类型应为 VariableDeclarator// 例: c = objlet identName = grandPath.node.id.name;  // 获取标识符中对应的 name 属性 (例中的 c)// 例:// let d = c['StringLiteral'];// let e = c['BinaryExpression'];// let f = c['funcCallExpression1'](demo, '123');// let g = c['funcCallExpression2'](demo);// let h = c['funcBinaryExpression']('1' + '2');let identBinding = grandPath.scope.getBinding(identName);  // 获取标识符 c 对应的引用// 例:// [c, c, c, c, c]let identRefer = identBinding.referencePaths;  // 获取标识符引用对应的数组// 字符串花指令for (const idenKey in identRefer) {// identRefer[idenKey].parentPath// c['StringLiteral']// c['BinaryExpression']// c['funcCallExpression1']// c['funcCallExpression2']// c['funcBinaryExpression']let key = identRefer[idenKey].parentPath.node.property.value;  // 获取对应的属性值// 获取 newObj[key]  // obj[属性值]// newObj[key] 的属性值为 StringLiteral 或 BinaryExpression 节点// StringLiteral 为字符串 'abc';// BinaryExpression 为二项式 'abc' + 'def';if (types.isStringLiteral(newObj[key]) || types.isBinaryExpression(newObj[key])){  // 还原字符串console.log('花指令字符串替换前: ', identRefer[idenKey].parentPath + '')identRefer[idenKey].parentPath.replaceWith(newObj[key])  // 获取 obj 中对应的 StringLiteral 节点console.log('花指令字符串替换后: ', identRefer[idenKey].parentPath + '')console.log('====================================')}}// 数组翻转,从后向前遍历for (const idenKey in identRefer.reverse()) {// MemberExpression// 为 let d = c['StringLiteral']; 中的 c['StringLiteral']if (identRefer[idenKey].parentPath.isMemberExpression()){// 获取对应调用的属性值 c['StringLiteral'] 中的 'StringLiteral'let key = identRefer[idenKey].parentPath.node.property.value;// 如果 newObj 对应属性值为 FunctionExpression 类型if (types.isFunctionExpression(newObj[key])){/*function (){...}*/// 拿到 return 语句let retState = newObj[key].body.body[0].argument;// 二元运算还原// 例: return a + bif (types.isBinaryExpression(retState)){let operator = retState.operator;  // 拿到操作符 例: +// 拿到参数数组// c['funcBinaryExpression']('1', '2'); 中的 ['1', '2']let Arg = identRefer[idenKey].parentPath.parentPath.node.arguments;console.log('花指令二元替换前:  ', identRefer[idenKey].parentPath.parentPath + '')// replaceWith 将当前的节点替换// c['funcBinaryExpression']('1', '2');// 替换成// '1' + '2'identRefer[idenKey].parentPath.parentPath.replaceWith(types.binaryExpression(operator, Arg[0], Arg[1]));console.log('花指令二元替换后:  ', identRefer[idenKey].parentPath.parentPath + '')console.log('=========================')}// 函数调用还原// 例: return a(b) / return a()// 这两个的差别只有调用的参数,一个对应调用的参数为 2, 一个调用对应的参数为 1// CallExpression// 例: return a(b)if (types.isCallExpression(retState)){// 获取该节点对应的参数// 例: c['funcCallExpression1'](demo, '123');// 中的// demo, '123'let Arg = identRefer[idenKey].parentPath.parentPath.node.arguments;console.log('花指令函数调用替换前:  ', identRefer[idenKey].parentPath.parentPath + '')// c['funcCallExpression'](demo, '123');// 替换成// demo('123');identRefer[idenKey].parentPath.parentPath.replaceWith(types.callExpression(types.identifier(Arg[0].name), Arg.slice(1)));console.log('花指令函数调用替换后:  ', identRefer[idenKey].parentPath.parentPath + '')console.log('=========================')}}}}}}// path.stop()}}
})

还原前

在这里插入图片描述

还原后

在这里插入图片描述

剔除无用代码

虚假 if

demo.js

if ('a' === 'a'){console.log("'a' === 'a' true");
}else{console.log("'a' === 'a' false");
}if ('a' !== 'a'){console.log("'a' !== 'a' true");
}else{console.log("'a' !== 'a' false");
}'a' === 'a' ? console.log("'a' === 'a' true") : console.log("'a' === 'a' false")
'a' !== 'a' ? console.log("'a' !== 'a' true") : console.log("'a' !== 'a' false")

AST.js

// 虚假 if
traverse(ast, {// IfStatement 为if判断语句// ConditionalExpression 为三元表达式"IfStatement|ConditionalExpression"(path){// 该节点中的判断条件应该为 二元表达式// left 节点应该为 StringLiteral 类型// right 节点应该为 StringLiteral 类型if(path.get('test').isBinaryExpression() && path.get('test.left').isStringLiteral() && path.get('test.right').isStringLiteral()){// 取出判断条件中对应的值// 例:  if ('a' === 'a') {  console.log("'a' === 'a' true");} else {  console.log("'a' === 'a' false");}let operator = path.node.test.operator;  // 取出操作符 例: ===let leftString = path.node.test.left.value;  // 左边的字符串 例: 'a'let rightString = path.node.test.right.value;  // 右边的字符串 例: === 'a'// 生成 eval 可判断的字符串let vmRun = `"${leftString}"  ${operator} "${rightString}"`;  // 例: 'a' === 'a'let result = eval(vmRun);console.log('虚假 if:  ' + (path + '').replaceAll('\n', ''))// 取出 if 与 else 中的代码块// path.node.consequent.body 为 if(){}else{}; 形式取值// path.node.consequent.arguments 为 statement ? true : false; 形式取值let ifTrue = path.node.consequent.body || path.node.consequent.arguments;let elFalse = path.node.alternate.body || path.node.alternate.arguments;// 判断 result 的执行结果,替换对应的代码块 if 或 elseresult ? path.replaceWithMultiple(ifTrue) : path.replaceWithMultiple(elFalse)}}
})

剔除无引用代码

// 剔除无引用代码
const refObj = {}
traverse(ast, {Identifier(path) {let name = path.node.name;if (!refObj[name]) {refObj[name] = '1';let binding = path.scope.getBinding(name);let refPath = binding && binding.referencePaths;if (refPath && refPath.length === 0) {path.parentPath.parentPath.isVariableDeclaration() && (console.log('删除的无用代码:  ', path.parentPath + ''), path.parentPath.remove())}}}
})

剔除无引用的对象

// 无引用的对象
traverse(ast, {VariableDeclarator(path) {  // 遍历 VariableDeclarator 节点if (types.isObjectExpression(path.node.init)) {  // init 类型为 ObjectExpression 类型let objName = path.node.id.name;  // 获取对应的标识符let objBinding = path.scope.getBinding(objName);  // 获取标识符对应的引用let objRefer = objBinding && objBinding.referencePaths;  // 获取标识符引用对应的数组let quoteObj = false;for (const index in objRefer) {let grandPath = objRefer[index].parentPath.parentPath;if (grandPath.isAssignmentExpression() && grandPath.get('left').isMemberExpression()) {if (grandPath.get('left.object').isIdentifier() && grandPath.node.left.object.name === objName) {console.log(grandPath + '');console.log('==============================')} else {quoteObj = true}}}if (!quoteObj) {for (const index in objRefer) {let grandPath = objRefer[index].parentPath.parentPath;grandPath.remove();}}}}
})

数值还原

// 数值还原
traverse(ast, {NumericLiteral(path){console.log('替换前: ', path.node.extra);delete path.node.extra.raw;console.log('替换后: ', path.node.extra);console.log('==============================');}
})

switch 还原

// 还原 switch
traverse(ast, {WhileStatement(path){if (path.node.test.prefix && path.get('body').isBlockStatement() && types.isSwitchStatement(path.node.body.body[0])){// 获取同级节点let sibling = path.getSibling(0)let whileIdx = (sibling.node.declarations[0].init.callee.object.value).split('|')let idxObj = {}let caseIdx = path.node.body.body[0].cases;for (const index in caseIdx){let key = caseIdx[index].test.value;idxObj[key] = caseIdx[index].consequent[0];}let newArray = []for (const index in whileIdx){newArray.push(idxObj[whileIdx[index]])}path.replaceWithMultiple(newArray);// 删除同级节点while(path.key--){path.getSibling(path.key).remove();}}}
})

还原前
在这里插入图片描述

还原后
在这里插入图片描述

完整的 AST 代码

代码

// 安装 babel 库:  npm install @babel/core
const fs = require('fs')const traverse = require('@babel/traverse').default  // 用于遍历 AST 节点
const types = require('@babel/types')  // 用于判断, 生成 AST 节点const parser = require('@babel/parser')  // 将js代码解析成ast节点
const generator = require('@babel/generator').default  // 将ast节点转换成js代码// 读取(路径记得改)
const ast_code = fs.readFileSync('demo.js', {encoding: 'utf-8'
})let ast = parser.parse(ast_code)  // 将js代码解析成ast语法树// 这里插入解析规则
///// 解密函数中需要的 atob 函数
global['atob'] = require('atob');  // npm install atob
// 解密函数依赖的大数组
var $dbsm_0x23b3 = ["QjjDhA==", "IyQb", "552u776q5L6D", "eCvDoA==", "EHwT", "wpdVw6I=", "RArDvA==", "Hk8D", "MUvCnA==", "wotlw5k=", "w7xTwrU=", "wrLCvT0=", "w5LCvUc=", "w6hIwrY=", "w716Rw==", "L8OzwpI=", "MlMA", "Gm8r", "WcKVw44=", "W8KKw5s=", "w6bCgUE=", "TSnDpg==", "aEXCuw==", "HMOzwrc=", "wqs3Bg==", "KHsW", "AcOtwp4=", "N8KeIA==", "cifCig==", "wrBZw7M=", "AMKtw4g=", "FMOkwqA=", "WwEa", "DjzDqA==", "wo7CnAs=", "wpdoAQ==", "JsOfwp0=", "J8KRKA==", "ZsOCw58=", "wojCiAQ=", "w7vCuMKR", "ATY3", "ZyfCvQ==", "dCJD", "UMKpVg==", "O2US", "wqE3LA==", "SMOtwqk=", "w5PCh8Ki", "bMKyaA==", "S8OjEw==", "AcKGw68=", "wpVFw5M=", "fDvDpw==", "w7Brwqk=", "dGYb", "eC45", "AsOGwrE=", "w7fDhcKz", "YATDlA==", "DsK6w6A=", "wrNLw7U=", "biAN", "TxVF", "VzJ2", "wr3CrRc=", "wr0WEQ==", "YAvDrw==", "wqtZNg==", "K0QC", "Y8KBw6c=", "Q8KEw6E=", "wrUhKQ==", "CXfDjA==", "G34/", "esOcTQ==", "wpFiDA==", "w4xCaQ==", "Blo7", "w6vDvcKT", "eyFl", "BE8K", "w6HCvUs=", "wplqw6M=", "wqdOw5Y=", "wqzDr8KW", "XsKdcw==", "VMKsag==", "ecO9w58=", "EkcB", "wpJIw5U=", "JFrDiA==", "YsO7cg==", "eTvCiA==", "wojCuxc=", "WyXDmw==", "MUrDtg==", "w5XDhcKw", "fMKLcw==", "eMOhw5w=", "EGnCjA==", "RcKTYg==", "OALDvQ==", "HlE/", "Q8KGag==", "wpQpFA==", "wqg5wqw=", "ZsOqw4A=", "wp1Ewpk=", "wpkPwro=", "UT9O", "XsOmw7g=", "CFkm", "W0gI", "P8Ouwrw=", "eEMQ", "L8KSw7k=", "ecOvw4Y=", "WT9O", "J8KYfw==", "BiEH", "w7VnwpM=", "w6dxbg==", "wo/Ci8Os", "wqgpAg==", "wozCm8OB", "clHCjA==", "QsOsw6Y=", "woZew44=", "Zz7DnA==", "RgzDrg==", "XMKAVw==", "SwBb", "VMKCSg==", "Ryp1", "wr9Mw44=", "w4rDqMK7", "UMOiw6E=", "w6fDo1U=", "VMOEw4c=", "EcKew4c=", "c8KRZQ==", "WsOOUQ==", "wodyLA==", "e8KMUg==", "w5TDln0=", "GcKbw4s=", "BMK0w7Y=", "wpIewoU=", "R8Kcw6k=", "wobDuMOi", "BsO/wp4=", "VcOnw6w=", "w5t0wok=", "wqgPwpA=", "woTCu8Or", "fg3DvQ==", "L8KEw6g=", "wphswpI=", "woYgIg==", "AXgq", "VTLCqg==", "wrRww4Q=", "wqM1Ig==", "YCzDjQ==", "EVkx", "PWsV", "JWbDjw==", "DF4M", "WcObw54=", "DMKXw6w=", "EcKmOA==", "WsOJw58=", "ajsY", "SsK1w4Q=", "w4zDqMK0", "Gics", "UTkL", "w754wrA=", "IBw2", "wopkDA==", "NFEb", "EFHDig==", "W8Okw40=", "C8KpVg==", "EmnDsQ==", "VhvDmA==", "wqTCoMOV", "fcOfw6A=", "JsKkNw==", "ecOjKg==", "aSTDsA==", "woYfOg==", "YcOyYA==", "fMOtw4E=", "eMOSw5A=", "w7jCn8KA", "LGI2", "asO0Ow==", "f2cW", "egvDuA==", "GcOeGQ==", "w4NYQw==", "IMKvw68=", "wrfDpsO6", "BcKjJA==", "w6PDu2g=", "ayTDrA==", "B0kt", "QsKTVg==", "wpvCuMO1", "YsOHw6M=", "B1XCuA==", "B8Kjw5w=", "Q8Oqw6g=", "RMOAw4c=", "w4/DssK0", "w4rDm8KQ", "ScOwQg==", "YsOGw5s=", "RjbDjQ==", "SCLDpg==", "VcOVMQ==", "KnHCgQ==", "JMONwrU=", "WcO/Cw==", "YcKuRQ==", "wr0MCw==", "WAHDnw==", "esKuUg==", "wp8mNA==", "MMOAEw==", "bcOBw4w=", "w5LCl8K/", "KXk3", "agpl", "wprChSg=", "w5BmYw==", "S2zCrg==", "BXIv", "EMOUwpA=", "WcKvVg==", "WsKkw4I=", "w69iwqQ=", "e8KYVw==", "Y8Ojw6s=", "KUUk", "LcOYwq0=", "Xj/DvQ==", "RiXDkg==", "wrbDiMOj", "Ujd6", "cAc+", "dzt2", "QsO9w6w=", "Ghg3", "ccKkcA==", "fRvDkA==", "KcK4Og==", "H30u", "PMKyw4Y=", "YyrDtw==", "wpDCiMOh", "wqwowoc=", "wojCjDQ=", "wqHCj8OU", "w7HCm8KR", "XsOVw7Q=", "w47Cp8Kj", "w6LCnMKo", "GsKMbw==", "w5J0wrU=", "RCnDuA==", "wpfCgjE=", "wrMnBw==", "w7bDqsK/", "KEM4", "a8OKwrw=", "wpBlw5Q=", "MTAo", "X8K2w5I=", "WsOvFQ==", "Yz7DkQ==", "W8Ocw54=", "ahtQ", "D2vDrg==", "VsKcw4o=", "Fy/CkQ==", "JnAI", "MMOswrA=", "w4zDt8KI", "wrDCksOj", "GBcc", "fcO9Sg==", "w4HDgXY=", "MsKeHA==", "ccOBw4o=", "QsOgw4M=", "Q8OjBg==", "EMK5FQ==", "R8OCw6o=", "XS9D", "d8KfcA==", "wpbCmSE=", "w4XChn8=", "aMKieA==", "woVhGQ==", "wo7CnsOK", "AXwd", "dCAI", "worDhsOC", "V8Krw4A=", "VxHCvA==", "woFywrg=", "w4ZRaA==", "VMO5w6Q=", "wp1zHg==", "wqw/wqo=", "BMKRw58=", "wpxjw7U=", "McKEw4o=", "YyIF", "fkME", "wp1xw6o=", "Sg80", "HMKbAQ==", "HHoX", "MsK7Cg==", "woZWCw==", "GsOKwrE=", "P8KPGg==", "bBDDhw==", "ewLDng==", "TSMk", "wrbCrT4=", "w7tkRg==", "DDQv", "wrdpLw==", "wonDmsKK", "Tx8o", "WMODw7I=", "MXgT", "w6PCrUw=", "wobCg8OR", "Z8Odw6U=", "w55LwrA=", "O8ORwqU=", "w5vDo10=", "wq3Cl8OT", "asKMUQ==", "woBpPg==", "SnPCrA==", "wo7Dn8KG", "wqVtw54=", "wo9WNA==", "QMObNw==", "TMKAw4Y=", "eHEn", "w5rDqcKk", "wqRlw68=", "CxYO", "WcK2VA==", "wpgrAw==", "wpHCgw4=", "wrHCklU=", "BkIZ", "woh4wqM=", "wpBICg==", "AcORGg==", "wpd0NQ==", "w4HDqsKa", "YcKvew==", "wpvCusOs", "K8K5JA==", "w7LCrGU=", "XkUT", "XMOow6s=", "w7/DqcKj", "NsOdwqQ=", "VcOsw7Q=", "eXED", "McKbdA==", "AHXCow==", "K8KeQg==", "ZgMB", "Hm4g", "f8Oqwow=", "AHPDpA==", "wq4Mwq0=", "WsKeYg==", "fDjCog==", "wpY/PQ==", "V8K9cg==", "OlAN", "esO8Xw==", "GsKaJA==", "WgjDnQ==", "DW7CrA==", "f8K1Qg==", "eSw0", "RAIx", "Cls9", "FMOYwqM=", "w4bCvVE=", "wovDkMKK", "WsK/Tw==", "QRrDgw==", "wpV9w4o=", "wrXCmxA=", "wpXChik=", "wq5kw7g=", "wo5jPA==", "w5VgZQ==", "wr1Cw4o=", "wpBYw60=", "woVOwpw=", "wpB2Cg==", "cBlA", "wo52Cg==", "QcO/w58=", "w65UwrM=", "fyfCng==", "w6TCp2s=", "wrRWJQ==", "w7bCv8KW", "XsKyeQ==", "MWbDiQ==", "w4jDscK1", "d8K1w4U=", "C34+", "wprDt8O9", "VsKlw7E=", "w4JdfQ==", "wos1Jg==", "PE7DuA==", "w4bDnsKM", "w5XDq8KA", "JTIy", "w5LDpMKu", "YArDsQ==", "K8K9IQ==", "DsKmw7E=", "BMKxw7A=", "wrvDncKg", "dzrChQ==", "G1nCjg==", "YEYA", "OsKzJg==", "wrfCugs=", "XlvCkA==", "fcKDw54=", "e8OMw40=", "wpBDw68=", "w45CwoY=", "WsONwpw=", "BFDCiQ==", "w7VidA==", "Aloq", "w73Cq8KT", "IkE4", "wqN0Nw==", "dBLDmw==", "wqlRw44=", "w7lleQ==", "C1TCgQ==", "PsKPJQ==", "VcK0bg==", "XcOBwo4=", "VMOjZQ==", "w7pjXg==", "wrBvFw==", "cARj", "w4JSaQ==", "MsK4w4Y=", "acOeeQ==", "AsOQIQ==", "wqUDBQ==", "X1Zb", "RMKKaA==", "w6fDs8KB", "HsKzdw==", "V8OJLA==", "XMOFwqo=", "V8Kybw==", "w5zDhG4=", "wrFHNQ==", "RcOhw6s=", "w6Vhbg==", "XcOow48=", "w5bCi24=", "NkfDgw==", "AcOyHA==", "XUzClw==", "w5XCgGY=", "w5rDhVA=", "a1c3", "WnzCsw==", "wrvDncK4", "w7pUwqk=", "QT1j", "DmLCuA==", "w69tVA==", "w6bCvMK+", "cVUo", "dcO8wqc=", "cBlK", "w5zDhWc=", "wpt+w6w=", "w6lFwrI=", "wojDiMOS", "XcOZw78=", "UwhO", "wotmw4M=", "RC4Y", "w77CjU0=", "S8O3w6U=", "PGAG", "WsKowq8=", "wqTDmsOo", "Hlo8", "I8OuwqQ=", "c8OAKA==", "cl7Cmw==", "V3PCvA==", "DnM2", "wqQTGQ==", "WWYV", "wozDosOV", "w7fDisKb", "csO+w4A=", "IsKiPw==", "w75iQA==", "Ww7CgA==", "wqtrLA==", "fsKtw6c=", "DsKbw5M=", "w5fDgMKO", "wrcaIQ==", "S1c5", "wrMaOQ==", "AcKIcA==", "Cjww", "w6VWYA==", "OQom", "ZxjDjQ==", "wrMoNw==", "VQXDmA==", "d8KeYQ==", "BEs8", "J0k9", "wpEeEQ==", "wqAHFQ==", "w6/DicKx", "ScOiCg==", "YxXCtg==", "dsOiw4k=", "THjCqQ==", "HMK+AA==", "wpQhHw==", "wr7CvcOq", "K0bDiw==", "eMOAcg==", "w60rdg==", "L1IC", "woNlw60=", "K8KDw4k=", "wrpFDg==", "wpFEMw==", "w6fCrGw=", "wo0mCA==", "cUTCtQ==", "w7LCqMKX", "W8OiwoQ=", "QAvDqQ==", "AD03", "aDfDiQ==", "UTHDpQ==", "ZhMa", "w6bDrMKs", "AkvCuw==", "wo8yBQ==", "wo4IPQ==", "M3QK", "TwrDnw==", "wqFcDw==", "e8O7bA==", "PkHDlg==", "esOBwqk=", "eRFw", "ZyvCnw==", "w7PDtcKx", "wpQ1woA=", "WwFc", "XRsF", "BMOCPQ==", "SHHCjA==", "XcOew5w=", "wqhaKA==", "YynCvg==", "XS3Chg==", "BFI0", "wr9HDA==", "wpx7w5o=", "w6DDmHU=", "bA84", "I3AA", "w7jCn2s=", "BWPClw==", "wpbDt8O1", "wpsKYw==", "wq9jw5I=", "woFQwp4=", "wpI9Mw==", "B8KwEQ==", "DmYq", "CcKbAQ==", "TS49", "w6bDvWU=", "YsOVNw==", "dMKBRQ==", "NXg8", "wrBJwoI=", "KsKAYQ==", "EcKNdQ==", "ecO7OA==", "wrV6w7I=", "WMOSw6Y=", "wqV6wqI=", "VcKyUA==", "fcO4Sg==", "IXQl", "Z8KaXw==", "VnvCnQ==", "wr9qOg==", "w6PDiGs=", "QD0a", "wrzCm8OQ", "w6LCp1w=", "bMK+w6A=", "w7PDn24=", "T2LClg==", "woBJw7c=", "SiPDjQ==", "wqbChTI=", "Wj3Dpg==", "fxgU", "YhzCuA==", "ETsw", "W8OdCA==", "GcOxIg==", "Kxkw", "B2zCuA==", "OBER", "Cl4R", "wrLDpMK8", "wq/CnsOZ", "w5XDv8Kw", "dysc", "Y8KjVQ==", "fcOvw40=", "CWjDug==", "bMObNg==", "ScOEw4c=", "w6RTwqM=", "wpJLEw==", "BTw5", "ScKDw4c=", "XMKbw5o=", "TxjDhw==", "w5pOew==", "wpJawp0=", "ZsKwQQ==", "FGMO", "GMKRw7o=", "QMO+OA==", "wrtaMQ==", "TMOUMA==", "J3jDuA==", "D8OnwqA=", "w7zCgcKv", "VnLCmw==", "Z8OJw4I=", "bADDng==", "ccKCZg==", "wrIUJA==", "XCHDow==", "w6DCsV8=", "ZsKafw==", "w5J7fg==", "M8OMwps=", "w7DDt8KG", "W8OYXw==", "EHDDhw==", "w63ChsKU", "O8Kiw4k=", "wrlxDA==", "wrnCkcON", "wqFfHg==", "wovDsMKh", "w67CmMKk", "w75Pwq8=", "wq/DnMKX", "SyhS", "wp1uOA==", "wr3Dt8KG", "DnI2", "OWEf", "w5PDisKX", "wr3CuRE=", "YBJu", "wrxgw58=", "wrEEIQ==", "Uy53", "V2/CjQ==", "ecOjw6Q=", "SMKjw5s=", "X8O5w7Y=", "RsK3w50=", "wpA+wro=", "aynDjQ==", "ccO5w6E=", "ezjCjw==", "BMOPJQ==", "w7FFwq8=", "QsOnw6Y=", "w5VRQQ==", "HmkA", "f8Oewr0=", "dsO7w78=", "w7PDrcKT", "w4vCr3E=", "X8O6w7s=", "CRTDqQ==", "VcO8w54=", "KmjDrA==", "w4dSfQ==", "BG7DpQ==", "bMOvw54=", "bi5F", "VDjDpQ==", "w6HCiFo=", "aMOYCA==", "w5fDqE8=", "CXbCpg==", "FMKwIg==", "w4BxSQ==", "QTbDow==", "J2si", "MsOxwpI=", "IsOdHA==", "wojDlsKP", "Hn44", "bMOQRg==", "dMKCWg==", "w7rDnF4=", "B8K5w58=", "WSjDpg==", "XsO5w5g=", "QTo7", "wqUZwoM=", "ecK1aA==", "esKDUA==", "woFCwrE=", "woISwos=", "dsODEw==", "McOrOQ==", "JVTDmA==", "XcKxbw==", "wqZZBg==", "OsKjFg==", "UQTDkg==", "woh3w4A=", "w5FXwpM=", "wpJAw7w=", "Ongr", "w41zwos=", "N8OGDw==", "w6DDicKj", "UQ0U", "CsKCTw==", "fTnDhA==", "w6TDqHA=", "AloY", "CV4e", "DsKJbQ==", "LyoG", "OFnChA==", "NFsh", "w596fA==", "w6FsYA==", "Pm/Chg==", "wrZ1Ew==", "wprDmcKo", "C3QW", "wo7CqDM=", "woYANg==", "wq3Dl8Ok", "wp7DlcKp", "csKXeA==", "wqVyHA==", "wptxw6k=", "IMOIwpE=", "HcKkw78=", "XzXDsg==", "Q8KAw48=", "QMOOWg==", "V3TClA==", "woY5Pw==", "K2jCng==", "c8OewoY=", "w5zDqVY=", "Al/Cmg==", "w7TDp8Kg", "wpjCoiU=", "G8ONAA==", "w7rCjMKO", "RSjDsg==", "esODbg==", "EWcq", "NsK4BA==", "PcKeEQ==", "GcOpJw==", "cTpO", "wrzDl8Kv", "CcKSw7I=", "fhPDpw==", "wqcfLg==", "B8KiIQ==", "OcKQw78=", "SjHDug==", "w4vDvcKd", "wq8kGQ==", "HH8J", "DVbDsg==", "LXHDrA==", "WCpe", "N8OjGQ==", "MVrDjA==", "ZB/Dpg==", "w7xvwpE=", "WwjDvA==", "wo4cIQ==", "esOvEw==", "wpJRw7Y=", "TRNg", "wrZ0Ag==", "dcOLcQ==", "bsKAw6E=", "wqdoPg==", "XDrCgg==", "wosKPw==", "bwTDvw==", "XQAy", "wpAUwoU=", "dB4t", "wpFRNw==", "UMKwQQ==", "ecOlw48=", "w6TChMKP", "XxFP", "A8K5Pg==", "w5dbfg==", "woDCtcOn", "IE3Cqg==", "JUvCqg==", "HzYw", "ecKEaA==", "fQEi", "fQR3", "J8KsEQ==", "b8Ofw6U=", "MsK6Jg==", "w7bDsMKT", "wqxuwps=", "XxPCrg==", "JcKQbg==", "FsOtAw==", "RcOBw6U=", "YcOxUg==", "EnAz", "ci8a", "VcO9w6E=", "Qj7Dvg==", "YMKEeQ==", "wqLDiMKl", "w5xawoM=", "TMOow6k=", "eRjDpQ==", "DXjCgQ==", "wq87HA==", "w5jCrMKw", "YsKzVw==", "fcOrwq8=", "wpNxw40=", "BgIo", "YcOEw6Q=", "BsKkw7M=", "L1XDiQ==", "DMKeaQ==", "cT3DmA==", "WDtL", "HVQy", "YTzDow==", "TsOZw5A=", "wpLCnSI=", "Ri8m", "w4fDiU0=", "ah5R", "w4TCuEs=", "w6bDusKY", "dgDDow==", "RAx3", "w71XVg==", "X8Obwoo=", "wrfDi8Kd", "ZsO+w5o=", "cB9B", "BH4p", "USBR", "w4bDksKn", "dSXDmQ==", "YMKew4A=", "V8O9BQ==", "wooxGQ==", "VX/Csg==", "XsOEw6Y=", "wrofBg==", "wpUBBw==", "wq87Gg==", "w4HCo0E=", "wpnCrAw=", "asOGwok=", "wqTChyA=", "wr91KA==", "FsKSLg==", "w5LDrMK5", "UxTDqw==", "JCMb", "IlfDmg==", "a8ONYA==", "IMO/wqM=", "OsOMwoI=", "YnM7", "YcOhcA==", "ZgDDhw==", "fcOnwq8=", "QAJu", "METDqw==", "HMKYRQ==", "IsKBw4g=", "wq9Cw5Y=", "WsOZFw==", "wrZkw60=", "aTAu", "bzgc", "RcOPBw==", "wqhlMQ==", "eMOrw48=", "O8Kjw68=", "STbDjA==", "wqvDgsOf", "G8K0bw==", "DsKdfQ==", "w4HCgWY=", "bgHDvw==", "CXPDlg==", "woFJFQ==", "wqDDlcKF", "QADDtg==", "w7tkSQ==", "Vgo3", "BEUK", "wrN2DA==", "wrHDlcKk", "XMOiEQ==", "wq/CnCU=", "QcKUUw==", "ODRV", "wpJuwpc=", "w67DkXY=", "NMOwwr0=", "VD8w", "KG4V", "acOAwqg=", "LMKWKg==", "wrLDmsK7", "a8K3bw==", "w6nDlMKA", "Y8OJw4s=", "w7xjSQ==", "AMKOdg==", "ay9S", "woFUPg==", "DcKVbA==", "Q8ODw4Y=", "w6JkTw==", "wrx5Hg==", "wr/DhsKl", "wo9QMQ==", "bSXDrg==", "eMOrWA==", "GMKpw78=", "w6fDuns=", "wqnDuMKI", "I1rDug==", "IHsb", "wqJMHw==", "OMOdwoM=", "HW4u", "w6JFQQ==", "wrJHEg==", "wpZcw7U=", "wq1tGw==", "wol2wog=", "w6nCu0s=", "wpLDl8KP", "woPCusOl", "wr7CtMOG", "wofDgsO2", "wprCuys=", "cD7Dhg==", "BWMM", "GMKYPA==", "WMOOw44=", "w4VFXA==", "w7DDmk0=", "F8KDOg==", "wo8jCQ==", "bcKEw44=", "aCkH", "cV0v", "aMO9Dg==", "cMOjw5E=", "CiM0", "Sy0W", "dTPCug==", "FsOuwp4=", "BkAs", "ZnkQ", "w7oxw4I=", "WMOPw4w=", "wqvCvyI=", "SRbDow==", "YinCjQ==", "cz4p", "w6PCqsKV", "VgVq", "BCE2", "w5LDrV4=", "TcO2Jw==", "eyRA", "a8Ouw7o=", "J1jDog==", "QcO5w40=", "FkvDjA==", "GMKpLg==", "ZwTDsg==", "wqzCsMOJ", "YS7ClA==", "w4bCuk0=", "ZMOOIA==", "wo4fwpQ=", "S8K6Vg==", "QcObw6U=", "wq9DHQ==", "IXgZ", "FFwc", "wqhvOA==", "wqBnwrw=", "QsOfJg==", "NW8A", "RRPDow==", "VAIr", "D8Kaw4s=", "X8OcGQ==", "JGEU", "eMKTbg==", "Y8OYbA==", "XcKaRQ==", "FMOrAQ==", "fwjCoA==", "wqnDhMK7", "wqkVwq8=", "P8KUfQ==", "Yh7DpA==", "BAsm", "RMK2w50=", "PcOwKg==", "CcKbw6w=", "HsKWTw==", "eyrDmA==", "woDDi8KC", "A2fDjw==", "YRTDlg==", "UsOow64=", "LCsE", "wo4dOg==", "wphxwpE=", "woUcAA==", "wqMfAA==", "TMKAw4U=", "GsKDw7k=", "PTE8", "wrlPGA==", "wqPDn8OT", "ZcOBw60=", "wrjCuMOq", "W8Kmw5k=", "XMOaw7k=", "wqxzwpM=", "fhDCqg==", "QMO+w7E=", "DVgs", "w6lSwrg=", "VMOHw6g=", "P8Oowrg=", "w7zDqHk=", "wq4CAw==", "wqpTDw==", "bDpH", "QcOYw4M=", "SBkv", "worCicOp", "wo0hGQ==", "w5JgWA==", "YQ5g", "AsK+Xg==", "XMOEwoo=", "ZiAN", "IsKsBQ==", "w6PDpVw=", "wrrCjSY=", "TcK+w6M=", "wp/DkMKL", "fhwQ", "ZHcF", "VDXDqw==", "w7rDg8Kg", "w5pywpc=", "UH3Cqg==", "AMOJwpI=", "wpxwwrU=", "SsONwo0=", "Az8p", "U2fCnA==", "wrLDlcKB", "XSlH", "QcOhKA==", "LG7CnQ==", "w6LDlsKm", "w5hkYQ==", "wqvDi8OU", "wo7CqDE=", "fAvCgQ==", "G8Kzw7A=", "YVAg", "wo/CnSY=", "Dk7CgQ==", "RzzCmw==", "P8OdAA==", "wqFcDQ==", "K8KVSA==", "woVawp8=", "JnEi", "w67DmsKc", "w6JRTw==", "DMK9cA==", "aBhR", "Zi4W", "dhzDvw==", "RsO7wq4=", "ecOcw6E=", "JcOmwqY=", "EcKwVg==", "WsKXeg==", "Byo1", "ElYq", "BloJ", "XMO4Ew==", "wo5+w7g=", "Mkk8", "wqAhJw==", "bjjDuw==", "w7bCpsKR", "Z8O7aw==", "d3fCvw==", "wpbDpcOF", "ScK7w7I=", "CkfDjg==", "ecOafA==", "YMOBw4A=", "wo0dwq4=", "dsKWTQ==", "DcKQZA==", "IEvCpw==", "w7fDulQ=", "aXnCkg==", "woMpJg==", "fWQq", "NnPDkQ==", "USBV", "U2gZ", "RsKBZw==", "e8K/cg==", "WMK5w4s=", "wrFww5I=", "w5PDhHk=", "ZsOxwos=", "wp3DisKX", "w7DCmVg=", "w6x4Rg==", "LH4K", "O20W", "ZMOZw7U=", "PMKfaA==", "bRhn", "Izwv", "w4cfwqU=", "w4fCpG0=", "aBvDoA==", "RMKveA==", "QcOxSg==", "V8K7cw==", "J8KeQg==", "w4LDiX0=", "IsKSUQ==", "VQXDkw==", "LXMp", "IsKgw6w=", "TCU4", "ayl1", "w6TDksK+", "Zn0Q", "AHbDug==", "w7JSwpg=", "G8OpwoM=", "fS1h", "wrxxw4s=", "wogKAw==", "wpYvwqA=", "eWXCkw==", "U8Ofw70=", "e2sT", "woUBAw==", "w6LDjmw=", "a8OPw54=", "U8KHbw==", "HTA7", "wonDs8Kk", "BFQG", "w5PDolU=", "ciXDkA==", "NcOSwrg=", "fCTDow==", "woYuwpQ=", "alQl", "S8Kbw5U=", "woRaw7M=", "E34q", "O8KdJg==", "WAHDng==", "w6DCmnA=", "OkYH", "Y8KWRQ==", "w5VNwpk=", "I0HDpg==", "wrQSJA==", "aQ9P", "HcKBw6g=", "eQnDsA==", "wpAcOw==", "w5HDmsKC", "w5tWwrs=", "ecOcIQ==", "JcKvMA==", "bRh5", "cB0F", "VjTDgA==", "wptrw7s=", "WDnDrw==", "Rz09", "wpYdAA==", "wrpUwpM=", "DcKifg==", "wp/DusKm", "wqAoOg==", "a17Cmw==", "J2k1"];
// 解密函数
var $dbsm_0x4638 = function (_0x1e1b14, _0x23b316) {_0x1e1b14 = _0x1e1b14 - 0x0;var _0x4638d3 = $dbsm_0x23b3[_0x1e1b14];if ($dbsm_0x4638['lIzlCZ'] === undefined) {(function () {var _0x4b121c;try {var _0x1d5b59 = Function('return\x20(function()\x20' + '{}.constructor(\x22return\x20this\x22)(\x20)' + ');');_0x4b121c = _0x1d5b59();} catch (_0x4f5869) {_0x4b121c = window;}var _0x55f54d = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';_0x4b121c['atob'] || (_0x4b121c['atob'] = function (_0x2337bc) {var _0x94736f = String(_0x2337bc)['replace'](/=+$/, '');var _0x5e548f = '';for (var _0x588d26 = 0x0, _0x5d3f20, _0x558d8e, _0x49832a = 0x0; _0x558d8e = _0x94736f['charAt'](_0x49832a++); ~_0x558d8e && (_0x5d3f20 = _0x588d26 % 0x4 ? _0x5d3f20 * 0x40 + _0x558d8e : _0x558d8e,_0x588d26++ % 0x4) ? _0x5e548f += String['fromCharCode'](0xff & _0x5d3f20 >> (-0x2 * _0x588d26 & 0x6)) : 0x0) {_0x558d8e = _0x55f54d['indexOf'](_0x558d8e);}return _0x5e548f;});}());var _0x2ef3c5 = function (_0x49a1eb, _0x27f9fb) {var _0x26a837 = [], _0x90ed46 = 0x0, _0x1e184c, _0x229955 = '', _0x28a13b = '';_0x49a1eb = atob(_0x49a1eb);for (var _0x4237c8 = 0x0, _0x18c69a = _0x49a1eb['length']; _0x4237c8 < _0x18c69a; _0x4237c8++) {_0x28a13b += '%' + ('00' + _0x49a1eb['charCodeAt'](_0x4237c8)['toString'](0x10))['slice'](-0x2);}_0x49a1eb = decodeURIComponent(_0x28a13b);var _0x2c4f5b;for (_0x2c4f5b = 0x0; _0x2c4f5b < 0x100; _0x2c4f5b++) {_0x26a837[_0x2c4f5b] = _0x2c4f5b;}for (_0x2c4f5b = 0x0; _0x2c4f5b < 0x100; _0x2c4f5b++) {_0x90ed46 = (_0x90ed46 + _0x26a837[_0x2c4f5b] + _0x27f9fb['charCodeAt'](_0x2c4f5b % _0x27f9fb['length'])) % 0x100;_0x1e184c = _0x26a837[_0x2c4f5b];_0x26a837[_0x2c4f5b] = _0x26a837[_0x90ed46];_0x26a837[_0x90ed46] = _0x1e184c;}_0x2c4f5b = 0x0;_0x90ed46 = 0x0;for (var _0x4fe42c = 0x0; _0x4fe42c < _0x49a1eb['length']; _0x4fe42c++) {_0x2c4f5b = (_0x2c4f5b + 0x1) % 0x100;_0x90ed46 = (_0x90ed46 + _0x26a837[_0x2c4f5b]) % 0x100;_0x1e184c = _0x26a837[_0x2c4f5b];_0x26a837[_0x2c4f5b] = _0x26a837[_0x90ed46];_0x26a837[_0x90ed46] = _0x1e184c;_0x229955 += String['fromCharCode'](_0x49a1eb['charCodeAt'](_0x4fe42c) ^ _0x26a837[(_0x26a837[_0x2c4f5b] + _0x26a837[_0x90ed46]) % 0x100]);}return _0x229955;};$dbsm_0x4638['UYyCMO'] = _0x2ef3c5;$dbsm_0x4638['nMtFyB'] = {};$dbsm_0x4638['lIzlCZ'] = !![];}var _0x57b28f = $dbsm_0x4638['nMtFyB'][_0x1e1b14];if (_0x57b28f === undefined) {if ($dbsm_0x4638['DwWKuR'] === undefined) {var _0x9e4186 = function (_0x3712d5) {this['kHsRXo'] = _0x3712d5;this['nWOEyU'] = [0x1, 0x0, 0x0];this['tpblbK'] = function () {return 'newState';};this['lAcsth'] = '\x5cw+\x20*\x5c(\x5c)\x20*{\x5cw+\x20*';this['foeeRg'] = '[\x27|\x22].+[\x27|\x22];?\x20*}';};_0x9e4186['prototype']['RuyyZP'] = function () {var _0x20d28 = new RegExp(this['lAcsth'] + this['foeeRg']);var _0x5e0e5f = true ? --this['nWOEyU'][0x1] : --this['nWOEyU'][0x0];return this['XVTLWU'](_0x5e0e5f);};_0x9e4186['prototype']['XVTLWU'] = function (_0x3ab8dc) {if (!Boolean(~_0x3ab8dc)) {return _0x3ab8dc;}return this['HxFvMA'](this['kHsRXo']);};_0x9e4186['prototype']['HxFvMA'] = function (_0x13037d) {for (var _0x3bdd37 = 0x0, _0x49b603 = this['nWOEyU']['length']; _0x3bdd37 < _0x49b603; _0x3bdd37++) {this['nWOEyU']['push'](Math['round'](Math['random']()));_0x49b603 = this['nWOEyU']['length'];}return _0x13037d(this['nWOEyU'][0x0]);};new _0x9e4186($dbsm_0x4638)['RuyyZP']();$dbsm_0x4638['DwWKuR'] = !![];}_0x4638d3 = $dbsm_0x4638['UYyCMO'](_0x4638d3, _0x23b316);$dbsm_0x4638['nMtFyB'][_0x1e1b14] = _0x4638d3;} else {_0x4638d3 = _0x57b28f;}return _0x4638d3;
};
// 解密函数还原字符串规则
traverse(ast, {CallExpression(path) {  // 遍历 CallExpression 节点// callee 属性为 Identifier 类型// 且 name 属性为 $dbsm_0x4638 解密函数名if (types.isIdentifier(path.node.callee, {name: '$dbsm_0x4638'})) {// 取出对应的参数// 例: $dbsm_0x4638('\x30\x78\x32\x39', '\x72\x69\x63\x50')let callArg = path.node.arguments;  // 例 ['\x30\x78\x32\x39', '\x72\x69\x63\x50']let arg1 = callArg[0].type;  // 例 '\x30\x78\x32\x39'let arg2 = callArg[1].type;  // 例 '\x72\x69\x63\x50'// 将对应的参数取出后, 拿到 $dbsm_0x4638 解密函数执行let result = $dbsm_0x4638(callArg[0].value, callArg[1].value)// 将对应的节点替换成 解密函数执行后的结果// 例//    将节点:  $dbsm_0x4638('\x30\x78\x33\x66\x36', '\x68\x32\x25\x5e')//    替换成:  "hei"console.log('解密函数执行前的节点: ', path + '')path.replaceWith(types.valueToNode(result));console.log('解密函数还原后的节点: ', path + '')console.log('==============================');}}
})// ASCII 码还原
traverse(ast, {StringLiteral(path) {if (path.node.extra) {console.log('ASCII码替换前: ', path.node.extra);path.node.extra.raw = `'${path.node.extra.rawValue}'`console.log('ASCII码替换后: ', path.node.extra);console.log('============================================================');}}
})// 字符串相加
function strConcat(path) {for (let i = 0; i <= 2; i++) {let node = path.node// left 节点为 StringLiteral 类型// right 节点为 StringLiteral 类型// operator 操作符属性为字符串 +if (types.isStringLiteral(node.left) && types.isStringLiteral(node.right) && node.operator === '+') {// 例 'e' + 'f'console.log('字符串相加前: ', path + '');// 例 'e' + 'f'let result = path.node.left.value + path.node.right.value;// 例: 'e' + 'f'// 替换成: 'ef'path.replaceWith(types.valueToNode(result));console.log('字符串相加后:  ', path + '');console.log('============================================================');} else {// 递归是针对多个字符串相加的// 例当前遍历到的节点: 'a' + 'b' + 'c' + 'd'// 这个节点在上面是不会处理的// path 对象的 traverse 方法是从当前节点继续遍历// 传入 strConcat 方法的节点就为:  'a' + 'b' + 'c' + 'd'// 调用过后还是会再次进入到 path.traverse 因为还是会有多个字符串相加// 上一次传入的节点被处理过了// 所以这一次传入的节点代码就为 'ab' + 'c' + 'd'// 一直递归到节点为 'abc' + 'd' 就会停止递归// 'abc' + 'd' 在 for 循环中会二次处理 (可以试着for循环只遍历一次看看效果path.traverse({BinaryExpression(path_) {strConcat(path_)}})}}
}traverse(ast, {BinaryExpression(path) {  // 遍历 BinaryExpression 节点strConcat(path)}
})// 花指令
traverse(ast, {VariableDeclarator(path){  // 遍历 VariableDeclarator 节点if (types.isObjectExpression(path.node.init)){  // init 类型为 ObjectExpression 类型let objName = path.node.id.name;  // 获取对应的标识符let objBinding = path.scope.getBinding(objName);  // 获取标识符对应的引用let objRefer = objBinding.referencePaths;  // 获取标识符引用对应的数组let newObj = {}// 将给对象属性赋值的所有变量存入 newObjfor (const refer in objRefer){  // refer 为索引值从 0 开始// objRefer[refer] 为 obj// objRefer[refer].parentPath 为 obj['str']// objRefer[refer].parentPath.parentPath 为 obj['str'] = 'abc'let grandPath = objRefer[refer].parentPath.parentPath;  // 获取该节点的整段代码// 该节点的类型为 AssignmentExpression 类型// 节点中 left 属性的类型为 MemberExpression 类型if (grandPath.isAssignmentExpression() && grandPath.get('left').isMemberExpression()){// obj['str'] 中的 str 字符串let key = grandPath.node.left.property.value;  // 获取 .property.value 的属性,作为新声明对象中的keynewObj[key] = grandPath.node.right;  // right为该属性对应的 node 节点,直接存入 newObj 对象即可}}for (const refer in objRefer.reverse()){let grandPath = objRefer[refer].parentPath;if (grandPath.isVariableDeclarator()){  // 该节点的类型应为 VariableDeclarator// 例: c = objlet identName = grandPath.node.id.name;  // 获取标识符中对应的 name 属性 (例中的 c)// 例:// let d = c['StringLiteral'];// let e = c['BinaryExpression'];// let f = c['funcCallExpression1'](demo, '123');// let g = c['funcCallExpression2'](demo);// let h = c['funcBinaryExpression']('1' + '2');let identBinding = grandPath.scope.getBinding(identName);  // 获取标识符 c 对应的引用// 例:// [c, c, c, c, c]let identRefer = identBinding.referencePaths;  // 获取标识符引用对应的数组// 字符串花指令for (const idenKey in identRefer) {// identRefer[idenKey].parentPath// c['StringLiteral']// c['BinaryExpression']// c['funcCallExpression1']// c['funcCallExpression2']// c['funcBinaryExpression']let key = identRefer[idenKey].parentPath.node.property.value;  // 获取对应的属性值// 获取 newObj[key]  // obj[属性值]// newObj[key] 的属性值为 StringLiteral 或 BinaryExpression 节点// StringLiteral 为字符串 'abc';// BinaryExpression 为二项式 'abc' + 'def';if (types.isStringLiteral(newObj[key]) || types.isBinaryExpression(newObj[key])){  // 还原字符串console.log('花指令字符串替换前: ', identRefer[idenKey].parentPath + '')identRefer[idenKey].parentPath.replaceWith(newObj[key])  // 获取 obj 中对应的 StringLiteral 节点console.log('花指令字符串替换后: ', identRefer[idenKey].parentPath + '')console.log('====================================')}}// 数组翻转,从后向前遍历for (const idenKey in identRefer.reverse()) {// MemberExpression// 为 let d = c['StringLiteral']; 中的 c['StringLiteral']if (identRefer[idenKey].parentPath.isMemberExpression()){// 获取对应调用的属性值 c['StringLiteral'] 中的 'StringLiteral'let key = identRefer[idenKey].parentPath.node.property.value;// 如果 newObj 对应属性值为 FunctionExpression 类型if (types.isFunctionExpression(newObj[key])){/*function (){...}*/// 拿到 return 语句let retState = newObj[key].body.body[0].argument;// 二元运算还原// 例: return a + bif (types.isBinaryExpression(retState)){let operator = retState.operator;  // 拿到操作符 例: +// 拿到参数数组// c['funcBinaryExpression']('1', '2'); 中的 ['1', '2']let Arg = identRefer[idenKey].parentPath.parentPath.node.arguments;console.log('花指令二元替换前:  ', identRefer[idenKey].parentPath.parentPath + '')// replaceWith 将当前的节点替换// c['funcBinaryExpression']('1', '2');// 替换成// '1' + '2'identRefer[idenKey].parentPath.parentPath.replaceWith(types.binaryExpression(operator, Arg[0], Arg[1]));console.log('花指令二元替换后:  ', identRefer[idenKey].parentPath.parentPath + '')console.log('=========================')}// 函数调用还原// 例: return a(b) / return a()// 这两个的差别只有调用的参数,一个对应调用的参数为 2, 一个调用对应的参数为 1// CallExpression// 例: return a(b)if (types.isCallExpression(retState)){// 获取该节点对应的参数// 例: c['funcCallExpression1'](demo, '123');// 中的// demo, '123'let Arg = identRefer[idenKey].parentPath.parentPath.node.arguments;console.log('花指令函数调用替换前:  ', identRefer[idenKey].parentPath.parentPath + '')// c['funcCallExpression'](demo, '123');// 替换成// demo('123');identRefer[idenKey].parentPath.parentPath.replaceWith(types.callExpression(types.identifier(Arg[0].name), Arg.slice(1)));console.log('花指令函数调用替换后:  ', identRefer[idenKey].parentPath.parentPath + '')console.log('=========================')}}}}}}// path.stop()}}
})// 虚假 if
traverse(ast, {// IfStatement 为if判断语句// ConditionalExpression 为三元表达式"IfStatement|ConditionalExpression"(path){// 该节点中的判断条件应该为 二元表达式// left 节点应该为 StringLiteral 类型// right 节点应该为 StringLiteral 类型if(path.get('test').isBinaryExpression() && path.get('test.left').isStringLiteral() && path.get('test.right').isStringLiteral()){// 取出判断条件中对应的值// 例:  if ('a' === 'a') {  console.log("'a' === 'a' true");} else {  console.log("'a' === 'a' false");}let operator = path.node.test.operator;  // 取出操作符 例: ===let leftString = path.node.test.left.value;  // 左边的字符串 例: 'a'let rightString = path.node.test.right.value;  // 右边的字符串 例: === 'a'// 生成 eval 可判断的字符串let vmRun = `"${leftString}"  ${operator} "${rightString}"`;  // 例: 'a' === 'a'let result = eval(vmRun);console.log('虚假 if:  ' + (path + '').replaceAll('\n', ''))// 取出 if 与 else 中的代码块// path.node.consequent.body 为 if(){}else{}; 形式取值// path.node.consequent.arguments 为 statement ? true : false; 形式取值let ifTrue = path.node.consequent.body || path.node.consequent.arguments;let elFalse = path.node.alternate.body || path.node.alternate.arguments;// 判断 result 的执行结果,替换对应的代码块 if 或 elseresult ? path.replaceWithMultiple(ifTrue) : path.replaceWithMultiple(elFalse)}}
})// 剔除无引用代码
const refObj = {}
traverse(ast, {Identifier(path) {let name = path.node.name;if (!refObj[name]) {refObj[name] = '1';let binding = path.scope.getBinding(name);let refPath = binding && binding.referencePaths;if (refPath && refPath.length === 0) {path.parentPath.parentPath.isVariableDeclaration() && (console.log('删除的无用代码:  ', path.parentPath + ''), path.parentPath.remove())}}}
})// 无引用的对象
traverse(ast, {VariableDeclarator(path) {  // 遍历 VariableDeclarator 节点if (types.isObjectExpression(path.node.init)) {  // init 类型为 ObjectExpression 类型let objName = path.node.id.name;  // 获取对应的标识符let objBinding = path.scope.getBinding(objName);  // 获取标识符对应的引用let objRefer = objBinding && objBinding.referencePaths;  // 获取标识符引用对应的数组let quoteObj = false;for (const index in objRefer) {let grandPath = objRefer[index].parentPath.parentPath;if (grandPath.isAssignmentExpression() && grandPath.get('left').isMemberExpression()) {if (grandPath.get('left.object').isIdentifier() && grandPath.node.left.object.name === objName) {console.log(grandPath + '');console.log('==============================')} else {quoteObj = true}}}if (!quoteObj) {for (const index in objRefer) {let grandPath = objRefer[index].parentPath.parentPath;grandPath.remove();}}}}
})// 数值还原
traverse(ast, {NumericLiteral(path){console.log('替换前: ', path.node.extra);delete path.node.extra.raw;console.log('替换后: ', path.node.extra);console.log('==============================');}
})// 还原 switch
traverse(ast, {WhileStatement(path){if (path.node.test.prefix && path.get('body').isBlockStatement() && types.isSwitchStatement(path.node.body.body[0])){// 获取同级节点let sibling = path.getSibling(1)let whileIdx = (sibling.node.declarations[0].init.callee.object.value).split('|')let idxObj = {}let caseIdx = path.node.body.body[0].cases;for (const index in caseIdx){let key = caseIdx[index].test.value;idxObj[key] = caseIdx[index].consequent[0];}let newArray = []for (const index in whileIdx){newArray.push(idxObj[whileIdx[index]])}path.replaceWithMultiple(newArray);// 删除同级节点while(path.key--){console.log('还原switch删除的节点:  ', path.getSibling(path.key) + '');path.getSibling(path.key).remove();}}}
})
///js_code = generator(ast, {compact: false,  // 是否压缩,默认 false
}).code  // 将ast节点转换成js代码// 写入(路径记得改)
fs.writeFileSync('New_demo.js', js_code, {encoding: 'utf-8',
})

还原前的代码量 在这里插入图片描述

还原后的代码量在这里插入图片描述

注意

转换好的代码直接放浏览器上会卡死,因为有格式化检测

方法1: 在编译成 js 代码时开启压缩 compact: true

js_code = generator(ast, {compact: true,  // 是否压缩,默认 false
}).code  // 将ast节点转换成js代码

方法2: 全局搜索 test,将格式化检测的位置全部改成 true
在这里插入图片描述

AST转换后的代码还是会有debugger
这里是生成 debugger 的位置 $dbsm_0x36da24 函数时生成 debugger 的
在这里插入图片描述
将 debugger 字符串删除即可
在这里插入图片描述

还原加密

将处理好的代码替换到 2.html 文件中
在 document[‘cookie’] 处打上断点
在这里插入图片描述
刷新页面开始调试
在这里插入图片描述
查看上一层堆栈
传进来的 _0x29c654 参数是 Date[“parse”](new Date()); 生成的
在这里插入图片描述
回到加密点 _0x2fdc55() 方法返回空字符串(不用管)
在这里插入图片描述

_0x691b6d() 方法返回的是加密值, 所以只要扣这个方法就可以了
在这里插入图片描述
点击 vm 进入这个方法
在这里插入图片描述
在这里插入图片描述
因为 _0x4a2ede, _0x47e4dd 永远都是undefined,所以 return 可以改写成
return _0x4a2ede ? _0x47e4dd ? _0x42d816(_0x4a2ede, _0x2de515) : y(_0x4a2ede, _0x2de515) : _0x47e4dd ? _0x2985eb(_0x2de515) : _0x396668(_0x2de515);
结果是一样的
在这里插入图片描述
再接着往上 缺啥补啥就可以了

补完运行时会报 qz is not defined(这是一个条件判断)
在这里插入图片描述
浏览器中的 qz 是一个 大数组 是执行 setInterval 后生成的 所以只要将 if 代码块中的代码放出来就可以了
在这里插入图片描述

扣完以后校验一下是否正确即可
在这里插入图片描述

请求代码

python

import requests
import execjs
import timedef call_js(file_name, func_name, *args):with open(file_name, mode='r', encoding='utf-8') as f:js_code = execjs.compile(f.read())return js_code.call(func_name, *args)headers = {"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36",
}
cookies = {"sessionid": "你的sessionid"
}def get_data(page):url = "https://match.yuanrenxue.cn/api/match/2"time_ = int(str(int(time.time() * 1000))[:10] + '000')cookies['m'] = f"{call_js('2.js', '_0x691b6d', time_)}|{time_}"print(cookies)params = {"page": f'{page}'}response = requests.get(url, headers=headers, cookies=cookies, params=params)print(response.json())if __name__ == '__main__':get_data(1)

javascript

function _0x691b6d(_0x2de515, _0x4a2ede, _0x47e4dd) {return _0x396668(_0x2de515);
}function _0x396668(_0xa25649) {return _0xef0b5b(_0x2985eb(_0xa25649));
}function _0x2985eb(_0x2f966f) {return _0x513ef6(_0x130879(_0x2f966f));
}function _0x130879(_0x1b540c) {var _0x553c57 = {};return unescape(encodeURIComponent(_0x1b540c));
}function _0x513ef6(_0x2957b6) {var _0x4c198e = {};return _0x1fd78f(_0x1e5972(_0x32960f(_0x2957b6), 8 * _0x2957b6["length"]));
}function _0xef0b5b(_0x10bf06) {var _0x2c2190,_0x20ca0c,_0x18d0e1 = "0123456789abcdef",_0xedd57d = '';for (_0x20ca0c = 0; _0x20ca0c < _0x10bf06["length"]; _0x20ca0c += 1) _0x2c2190 = _0x10bf06["charCodeAt"](_0x20ca0c), _0xedd57d += _0x18d0e1["charAt"](_0x2c2190 >>> 4 & 15) + _0x18d0e1["charAt"](15 & _0x2c2190);return _0xedd57d;
}function _0x1e5972(_0x132f3d, _0x23ca08) {var _0x323bcd = {};_0x132f3d[_0x23ca08 >> 5] |= 128 << _0x23ca08 % 32, _0x132f3d[14 + (_0x23ca08 + 64 >>> 9 << 4)] = _0x23ca08;var _0x1ee0c6,_0x1e8f34,_0x429ecb,_0x5c3723,_0xde6a8e,_0x4f8eee = 1732584193,_0x12b681 = -271733879,_0x34e741 = -1732584194,_0x4aa794 = 271733878;for (_0x1ee0c6 = 0; _0x1ee0c6 < _0x132f3d["length"]; _0x1ee0c6 += 16) _0x1e8f34 = _0x4f8eee, _0x429ecb = _0x12b681, _0x5c3723 = _0x34e741, _0xde6a8e = _0x4aa794, _0x4f8eee = _0x5655af(_0x4f8eee, _0x12b681, _0x34e741, _0x4aa794, _0x132f3d[_0x1ee0c6], 7, -680876936), _0x4aa794 = _0x5655af(_0x4aa794, _0x4f8eee, _0x12b681, _0x34e741, _0x132f3d[_0x1ee0c6 + 1], 12, -389564586), _0x34e741 = _0x5655af(_0x34e741, _0x4aa794, _0x4f8eee, _0x12b681, _0x132f3d[_0x1ee0c6 + 2], 17, 606105819), _0x12b681 = _0x5655af(_0x12b681, _0x34e741, _0x4aa794, _0x4f8eee, _0x132f3d[_0x1ee0c6 + 3], 22, -1044525330), _0x4f8eee = _0x5655af(_0x4f8eee, _0x12b681, _0x34e741, _0x4aa794, _0x132f3d[_0x1ee0c6 + 4], 7, -176418897), _0x4aa794 = _0x5655af(_0x4aa794, _0x4f8eee, _0x12b681, _0x34e741, _0x132f3d[_0x1ee0c6 + 5], 12, 1200080426), _0x34e741 = _0x5655af(_0x34e741, _0x4aa794, _0x4f8eee, _0x12b681, _0x132f3d[_0x1ee0c6 + 6], 17, -1473231341), _0x12b681 = _0x5655af(_0x12b681, _0x34e741, _0x4aa794, _0x4f8eee, _0x132f3d[_0x1ee0c6 + 7], 22, -45705983), _0x4f8eee = _0x5655af(_0x4f8eee, _0x12b681, _0x34e741, _0x4aa794, _0x132f3d[_0x1ee0c6 + 8], 7, 1770010416), _0x4aa794 = _0x5655af(_0x4aa794, _0x4f8eee, _0x12b681, _0x34e741, _0x132f3d[_0x1ee0c6 + 9], 12, -1958414417), _0x34e741 = _0x5655af(_0x34e741, _0x4aa794, _0x4f8eee, _0x12b681, _0x132f3d[_0x1ee0c6 + 10], 17, -42063), _0x12b681 = _0x5655af(_0x12b681, _0x34e741, _0x4aa794, _0x4f8eee, _0x132f3d[_0x1ee0c6 + 11], 22, -1990404162), _0x4f8eee = _0x5655af(_0x4f8eee, _0x12b681, _0x34e741, _0x4aa794, _0x132f3d[_0x1ee0c6 + 12], 7, 1804603682), _0x4aa794 = _0x5655af(_0x4aa794, _0x4f8eee, _0x12b681, _0x34e741, _0x132f3d[_0x1ee0c6 + 13], 12, -40341101), _0x34e741 = _0x5655af(_0x34e741, _0x4aa794, _0x4f8eee, _0x12b681, _0x132f3d[_0x1ee0c6 + 14], 17, -1502882290), _0x12b681 = _0x5655af(_0x12b681, _0x34e741, _0x4aa794, _0x4f8eee, _0x132f3d[_0x1ee0c6 + 15], 22, 1236535329), _0x4f8eee = _0xafe18(_0x4f8eee, _0x12b681, _0x34e741, _0x4aa794, _0x132f3d[_0x1ee0c6 + 1], 5, -165796510), _0x4aa794 = _0xafe18(_0x4aa794, _0x4f8eee, _0x12b681, _0x34e741, _0x132f3d[_0x1ee0c6 + 6], 9, -1069501632), _0x34e741 = _0xafe18(_0x34e741, _0x4aa794, _0x4f8eee, _0x12b681, _0x132f3d[_0x1ee0c6 + 11], 14, 643717713), _0x12b681 = _0xafe18(_0x12b681, _0x34e741, _0x4aa794, _0x4f8eee, _0x132f3d[_0x1ee0c6], 20, -373897302), _0x4f8eee = _0xafe18(_0x4f8eee, _0x12b681, _0x34e741, _0x4aa794, _0x132f3d[_0x1ee0c6 + 5], 5, -701558691), _0x4aa794 = _0xafe18(_0x4aa794, _0x4f8eee, _0x12b681, _0x34e741, _0x132f3d[_0x1ee0c6 + 10], 9, 38016083), _0x34e741 = _0xafe18(_0x34e741, _0x4aa794, _0x4f8eee, _0x12b681, _0x132f3d[_0x1ee0c6 + 15], 14, -660478335), _0x12b681 = _0xafe18(_0x12b681, _0x34e741, _0x4aa794, _0x4f8eee, _0x132f3d[_0x1ee0c6 + 4], 20, -405537848), _0x4f8eee = _0xafe18(_0x4f8eee, _0x12b681, _0x34e741, _0x4aa794, _0x132f3d[_0x1ee0c6 + 9], 5, 568446438), _0x4aa794 = _0xafe18(_0x4aa794, _0x4f8eee, _0x12b681, _0x34e741, _0x132f3d[_0x1ee0c6 + 14], 9, -1019803690), _0x34e741 = _0xafe18(_0x34e741, _0x4aa794, _0x4f8eee, _0x12b681, _0x132f3d[_0x1ee0c6 + 3], 14, -187363961), _0x12b681 = _0xafe18(_0x12b681, _0x34e741, _0x4aa794, _0x4f8eee, _0x132f3d[_0x1ee0c6 + 8], 20, 1163531501), _0x4f8eee = _0xafe18(_0x4f8eee, _0x12b681, _0x34e741, _0x4aa794, _0x132f3d[_0x1ee0c6 + 13], 5, -1444681467), _0x4aa794 = _0xafe18(_0x4aa794, _0x4f8eee, _0x12b681, _0x34e741, _0x132f3d[_0x1ee0c6 + 2], 9, -51403784), _0x34e741 = _0xafe18(_0x34e741, _0x4aa794, _0x4f8eee, _0x12b681, _0x132f3d[_0x1ee0c6 + 7], 14, 1735328473), _0x12b681 = _0xafe18(_0x12b681, _0x34e741, _0x4aa794, _0x4f8eee, _0x132f3d[_0x1ee0c6 + 12], 20, -1926607734), _0x4f8eee = _0x57cdb6(_0x4f8eee, _0x12b681, _0x34e741, _0x4aa794, _0x132f3d[_0x1ee0c6 + 5], 4, -378558), _0x4aa794 = _0x57cdb6(_0x4aa794, _0x4f8eee, _0x12b681, _0x34e741, _0x132f3d[_0x1ee0c6 + 8], 11, -2022574463), _0x34e741 = _0x57cdb6(_0x34e741, _0x4aa794, _0x4f8eee, _0x12b681, _0x132f3d[_0x1ee0c6 + 11], 16, 1839030562), _0x12b681 = _0x57cdb6(_0x12b681, _0x34e741, _0x4aa794, _0x4f8eee, _0x132f3d[_0x1ee0c6 + 14], 23, -35309556), _0x4f8eee = _0x57cdb6(_0x4f8eee, _0x12b681, _0x34e741, _0x4aa794, _0x132f3d[_0x1ee0c6 + 1], 4, -1530992060), _0x4aa794 = _0x57cdb6(_0x4aa794, _0x4f8eee, _0x12b681, _0x34e741, _0x132f3d[_0x1ee0c6 + 4], 11, 1272893353), _0x34e741 = _0x57cdb6(_0x34e741, _0x4aa794, _0x4f8eee, _0x12b681, _0x132f3d[_0x1ee0c6 + 7], 16, -155497632), _0x12b681 = _0x57cdb6(_0x12b681, _0x34e741, _0x4aa794, _0x4f8eee, _0x132f3d[_0x1ee0c6 + 10], 23, -1094730640), _0x4f8eee = _0x57cdb6(_0x4f8eee, _0x12b681, _0x34e741, _0x4aa794, _0x132f3d[_0x1ee0c6 + 13], 4, 681279174), _0x4aa794 = _0x57cdb6(_0x4aa794, _0x4f8eee, _0x12b681, _0x34e741, _0x132f3d[_0x1ee0c6], 11, -358537222), _0x34e741 = _0x57cdb6(_0x34e741, _0x4aa794, _0x4f8eee, _0x12b681, _0x132f3d[_0x1ee0c6 + 3], 16, -722521979), _0x12b681 = _0x57cdb6(_0x12b681, _0x34e741, _0x4aa794, _0x4f8eee, _0x132f3d[_0x1ee0c6 + 6], 23, 76029189), _0x4f8eee = _0x57cdb6(_0x4f8eee, _0x12b681, _0x34e741, _0x4aa794, _0x132f3d[_0x1ee0c6 + 9], 4, -640364487), _0x4aa794 = _0x57cdb6(_0x4aa794, _0x4f8eee, _0x12b681, _0x34e741, _0x132f3d[_0x1ee0c6 + 12], 11, -421815835), _0x34e741 = _0x57cdb6(_0x34e741, _0x4aa794, _0x4f8eee, _0x12b681, _0x132f3d[_0x1ee0c6 + 15], 16, 530742520), _0x12b681 = _0x57cdb6(_0x12b681, _0x34e741, _0x4aa794, _0x4f8eee, _0x132f3d[_0x1ee0c6 + 2], 23, -995338651), _0x4f8eee = _0x2ba84c(_0x4f8eee, _0x12b681, _0x34e741, _0x4aa794, _0x132f3d[_0x1ee0c6], 6, -198630844), _0x4aa794 = _0x2ba84c(_0x4aa794, _0x4f8eee, _0x12b681, _0x34e741, _0x132f3d[_0x1ee0c6 + 7], 10, 1126891415), _0x34e741 = _0x2ba84c(_0x34e741, _0x4aa794, _0x4f8eee, _0x12b681, _0x132f3d[_0x1ee0c6 + 14], 15, -1416354905), _0x12b681 = _0x2ba84c(_0x12b681, _0x34e741, _0x4aa794, _0x4f8eee, _0x132f3d[_0x1ee0c6 + 5], 21, -57434055), _0x4f8eee = _0x2ba84c(_0x4f8eee, _0x12b681, _0x34e741, _0x4aa794, _0x132f3d[_0x1ee0c6 + 12], 6, 1700485571), _0x4aa794 = _0x2ba84c(_0x4aa794, _0x4f8eee, _0x12b681, _0x34e741, _0x132f3d[_0x1ee0c6 + 3], 10, -1894986606), _0x34e741 = _0x2ba84c(_0x34e741, _0x4aa794, _0x4f8eee, _0x12b681, _0x132f3d[_0x1ee0c6 + 10], 15, -1051523), _0x12b681 = _0x2ba84c(_0x12b681, _0x34e741, _0x4aa794, _0x4f8eee, _0x132f3d[_0x1ee0c6 + 1], 21, -2054922799), _0x4f8eee = _0x2ba84c(_0x4f8eee, _0x12b681, _0x34e741, _0x4aa794, _0x132f3d[_0x1ee0c6 + 8], 6, 1873313359), _0x4aa794 = _0x2ba84c(_0x4aa794, _0x4f8eee, _0x12b681, _0x34e741, _0x132f3d[_0x1ee0c6 + 15], 10, -30611744), _0x34e741 = _0x2ba84c(_0x34e741, _0x4aa794, _0x4f8eee, _0x12b681, _0x132f3d[_0x1ee0c6 + 6], 15, -1560198380), _0x12b681 = _0x2ba84c(_0x12b681, _0x34e741, _0x4aa794, _0x4f8eee, _0x132f3d[_0x1ee0c6 + 13], 21, 1309151649), _0x4f8eee = _0x2ba84c(_0x4f8eee, _0x12b681, _0x34e741, _0x4aa794, _0x132f3d[_0x1ee0c6 + 4], 6, -145523070), _0x4aa794 = _0x2ba84c(_0x4aa794, _0x4f8eee, _0x12b681, _0x34e741, _0x132f3d[_0x1ee0c6 + 11], 10, -1120210379), _0x34e741 = _0x2ba84c(_0x34e741, _0x4aa794, _0x4f8eee, _0x12b681, _0x132f3d[_0x1ee0c6 + 2], 15, 718787259), _0x12b681 = _0x2ba84c(_0x12b681, _0x34e741, _0x4aa794, _0x4f8eee, _0x132f3d[_0x1ee0c6 + 9], 21, -343485441), _0x4f8eee = _0x564a36(_0x4f8eee, _0x1e8f34), _0x12b681 = _0x564a36(_0x12b681, _0x429ecb), _0x34e741 = _0x564a36(_0x34e741, _0x5c3723), _0x4aa794 = _0x564a36(_0x4aa794, _0xde6a8e);return [_0x4f8eee, _0x12b681, _0x34e741, _0x4aa794];
}function _0xafe18(_0x59972b, _0x357d2b, _0x37f1e6, _0x40c0ec, _0x457a54, _0x27a208, _0x1291f9) {return _0x93484(_0x357d2b & _0x40c0ec | _0x37f1e6 & ~_0x40c0ec, _0x59972b, _0x357d2b, _0x457a54, _0x27a208, _0x1291f9);
}function _0x2ba84c(_0x25c369, _0x2fa4cf, _0x10bc95, _0x133659, _0x3e51d8, _0x4a9786, _0x5ad3d9) {return _0x93484(_0x10bc95 ^ (_0x2fa4cf | ~_0x133659), _0x25c369, _0x2fa4cf, _0x3e51d8, _0x4a9786, _0x5ad3d9);
}function _0x57cdb6(_0x24e055, _0x43d7e3, _0x11af5a, _0xde9c8, _0x3f9877, _0x3e6fd3, _0x45d799) {return _0x93484(_0x43d7e3 ^ _0x11af5a ^ _0xde9c8, _0x24e055, _0x43d7e3, _0x3f9877, _0x3e6fd3, _0x45d799);
}function _0x3243aa(_0xdd939c, _0x39e4e0) {return _0xdd939c << _0x39e4e0 | _0xdd939c >>> 32 - _0x39e4e0;
}function _0x564a36(_0x3c4e40, _0x45890c) {var _0x1e7f33 = {};var _0x474c37 = (65535 & _0x3c4e40) + (65535 & _0x45890c);return (_0x3c4e40 >> 16) + (_0x45890c >> 16) + (_0x474c37 >> 16) << 16 | 65535 & _0x474c37;
}function _0x93484(_0x1f657e, _0x172cfb, _0x14882e, _0x31dde3, _0x16e397, _0x330a90) {return _0x564a36(_0x3243aa(_0x564a36(_0x564a36(_0x172cfb, _0x1f657e), _0x564a36(_0x31dde3, _0x330a90)), _0x16e397), _0x14882e);
}function _0x5655af(_0x5ec922, _0x49f6b4, _0x357fa0, _0x1558be, _0x3b2d74, _0x5bb480, _0x36aa69) {return _0x93484(_0x49f6b4 & _0x357fa0 | ~_0x49f6b4 & _0x1558be, _0x5ec922, _0x49f6b4, _0x3b2d74, _0x5bb480, _0x36aa69);
}function _0x32960f(_0x2752b7) {var _0x1e1be5,_0x5928bd = [];for (_0x5928bd[(_0x2752b7["length"] >> 2) - 1] = void 0, _0x1e1be5 = 0; _0x1e1be5 < _0x5928bd["length"]; _0x1e1be5 += 1) _0x5928bd[_0x1e1be5] = 0;var _0x2e5130 = 8 * _0x2752b7["length"];for (_0x1e1be5 = 0; _0x1e1be5 < _0x2e5130; _0x1e1be5 += 8) _0x5928bd[_0x1e1be5 >> 5] |= (255 & _0x2752b7["charCodeAt"](_0x1e1be5 / 8)) << _0x1e1be5 % 32;return _0x5928bd;
}function _0x1fd78f(_0x461924) {var _0x51955d,_0x47ef66 = '',_0x264aa7 = 32 * _0x461924["length"];for (_0x51955d = 0; _0x51955d < _0x264aa7; _0x51955d += 8) _0x47ef66 += String["fromCharCode"](_0x461924[_0x51955d >> 5] >>> _0x51955d % 32 & 255);return _0x47ef66;
}// console.log(_0x691b6d(1723380724000));
// '75bcb82b08198abbec49a4248c6aae02|1723380724000'

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/396554.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

pygame小游戏

代码存在一些bug&#xff0c;感兴趣可自行修改&#xff0c;游戏运行后玩法与吃金币游戏类似。&#xff08;代码及结果比较粗糙&#xff0c;仅供参考&#xff09; 注&#xff1a;&#xff08;图片、音乐、音效文件老是上传上传不上&#xff0c;想要可私&#xff0c;也可以自己找…

如何在银河麒麟操作系统上搭建 Electron (含 Electron 打包指南)

本次教程所用版本 Eletron版本&#xff1a;31.3.1 Electron-packager版本&#xff1a;17.1.2 VScode版本&#xff1a;1.92.0 Node版本&#xff1a;18.19.0 npm版本&#xff1a;10.2.3 前言&#xff1a; 随着跨平台应用开发的需求日益增长&#xff0c;Electron 和 Qt 成为…

Midjourney入门-提示词基础撰写与公式

​ 前言 在前几篇教程里我们已经可以初步使用Midjourney进行出图了。 包括也了解了Midjourney的指令与参数。 但如果你想用Midjourney去生成各种各样高质量的图片&#xff0c; 并且生成的图片是你想要的画面内容&#xff0c;也就是更好控制生成图片的画面内容与风格&#xf…

书生大模型实战营闯关记录----第八关:书生大模型全链路开源开放体系

书生大模型全链路开源开放体系 一、概述 书生大模型&#xff0c;即InternLM系列模型&#xff0c;是由上海人工智能实验室书生团队开发的一系列大语言模型。这些模型以其强大的功能而著称&#xff0c;涵盖了从基础的语言理解到复杂的数学解题和图文创作等多个领域。 发展历程…

【每日面经】快手面经

ConcurrentHashMap和HashMap的区别&#xff1f;使用场景&#xff1f; 线程安全性 concurrentHashMap是线程安全的&#xff0c;HashMap不是线程安全的锁机制 ConcurrentHashMap采用的是分段锁&#xff08;Sagment&#xff09;机制&#xff0c;降低所得粒度提高了并发性能 Curr…

4章4节:临床数据科学中如何用R来进行缺失值的处理

在临床科研中,由于失访、无应答或记录不清等各种原因,经常会遇到数据缺失的问题。本文将深入探讨医学科研中数据缺失的成因、分类、影响以及应对方法,结合R语言的实际应用,为医学研究人员提供全面的解决方案。 一、认识缺失数据 其实,很多医学的纵向研究因获取数据资料时…

38.【C语言】指针(重难点)(C)

目录: 8.const 修饰指针 *修饰普通变量 *修饰指针变量 9.指针运算 *指针或-整数 *指针-指针 *指针关系运算 往期推荐 承接上篇37.【C语言】指针&#xff08;重难点&#xff09;&#xff08;B&#xff09; 8.const 修饰指针 const 全称 constant adj.不变的 *修饰普通变量 #…

java.lang.NoClassDefFoundError: ch/qos/logback/core/util/StatusPrinter2

1、问题 SpringBoot升级报错&#xff1a; Exception in thread "main" java.lang.NoClassDefFoundError: ch/qos/logback/core/util/StatusPrinter2 类找不到&#xff1a; Caused by: java.lang.ClassNotFoundException: ch.qos.logback.core.util.StatusPrinter22、…

HDFS写入数据的流程图

1.客户端向namenode发送请求&#xff0c;请示写入数据 2.namenode接受请求后&#xff0c;判断这个用户是否有写入权限&#xff0c;如果不具备直接报错&#xff1b;如果有写入权限&#xff0c;接着判断在要写入的目录下是否已经存在这个文件&#xff0c;如果存在&#xff0c;直…

PHP语言特性漏洞汇总【万字详解】

文章目录 任意文件下载PHP弱类型比较字符比较绕过代码示例过程 SHA1比较绕过MD5比较绕过SESSION比较绕过STRCMP比较绕过科学计算法绕过概念复现复现2 json_decode&#xff08;&#xff09;绕过概念源码分析 ereg绕过概念复现复现2 array_search强相等绕过概念复现 文件包含生成…

螺旋矩阵 | LeetCode-59 | LeetCode-54 | 分类讨论

&#x1f64b;大家好&#xff01;我是毛毛张! &#x1f308;个人首页&#xff1a; 神马都会亿点点的毛毛张 &#x1f383;分类不好&#xff0c;这道题就做不出来&#xff01;&#x1f388; &#x1f4cc;LeetCode链接&#xff1a;59. 螺旋矩阵 II &#x1f4cc;LeetCode链接…

Mac平台M1PRO芯片MiniCPM-V-2.6网页部署跑通

Mac平台M1PRO芯片MiniCPM-V-2.6网页部署跑通 契机 ⚙ 2.6的小钢炮可以输入视频了&#xff0c;我必须拉到本地跑跑。主要解决2.6版本默认绑定flash_atten问题&#xff0c;pip install flash_attn也无法安装&#xff0c;因为强制依赖cuda。主要解决的就是这个问题&#xff0c;还…

移动端上拉分页加载更多(h5,小程序)

1.h5,使用原生方式监听页面滚动上拉分页加载更多 <template><div></div> </template><script> export default {data() {return {loadflag: true,maxpages: 0, //最大页码currentpage: 0, //当前页listData: [],config: {page: 1,pageSize: 15,…

Netty技术全解析:DelimiterBasedFrameDecoder类深度解析

❃博主首页 &#xff1a; 「码到三十五」 &#xff0c;同名公众号 :「码到三十五」&#xff0c;wx号 : 「liwu0213」 ☠博主专栏 &#xff1a; <mysql高手> <elasticsearch高手> <源码解读> <java核心> <面试攻关> ♝博主的话 &#xff1a…

Java中等题-交错字符串(力扣)

给定三个字符串 s1、s2、s3&#xff0c;请你帮忙验证 s3 是否是由 s1 和 s2 交错 组成的。 两个字符串 s 和 t 交错 的定义与过程如下&#xff0c;其中每个字符串都会被分割成若干 非空 子字符串 &#xff1a; s s1 s2 ... snt t1 t2 ... tm|n - m| < 1交错 是…

AI入门指南(二):算法、训练、模型、大模型是什么?

文章目录 一、前言二、算法是什么&#xff1f;概念实际应用 三、训练是什么&#xff1f;概念实际应用 四、模型是什么&#xff1f;概念实际应用小结 五、大模型是什么&#xff1f;概念大模型和小模型有什么区别&#xff1f;大模型分类实际应用 六、总结七、参考资料 一、前言 …

37.【C语言】指针(重难点)(B)

目录&#xff1a; 5.疑问解答&#xff1a;指针的解引用 6.指针或-整数 7.特殊类型*void指针 承接上篇19.【C语言】指针&#xff08;重难点&#xff09;&#xff08;A&#xff09; 5.疑问解答&#xff1a;指针的解引用 观察下列代码产生的现象 #include <stdio.h> int …

代码随想录算法训练营day39||动态规划07:多重背包+打家劫舍

多重背包理论 描述&#xff1a; 有N种物品和一个容量为V 的背包。 第i种物品最多有Mi件可用&#xff0c;每件耗费的空间是Ci &#xff0c;价值是Wi 。 求解将哪些物品装入背包可使这些物品的耗费的空间 总和不超过背包容量&#xff0c;且价值总和最大。 本质&#xff1a; …

yolov8旋转目标检测部署教程(附代码c++/python)

为了编写一个详细的YOLOv8旋转目标检测ONNX部署教程&#xff0c;我们需要考虑几个关键点&#xff1a;模型转换为ONNX格式、ONNX模型的部署以及后处理逻辑。由于YOLOv8本身还未发布&#xff0c;我们将基于现有的知识和技术来进行推断。 以下是部署YOLOv8旋转目标检测模型到ONNX…

【经验分享】ShardingSphere+Springboot-03 : COMPLEX_INLINE 复杂行表达式分片算法

文章目录 3.3 复杂分片算法3.3.1 COMPLEX_INLINE 复杂行表达式分片算法 3.3 复杂分片算法 3.3.1 COMPLEX_INLINE 复杂行表达式分片算法 复合分片比较灵活&#xff0c;适合于分片的字段比较多&#xff0c;分片比较复杂的场景&#xff0c;使用这种分片的话必须对自己的业务比较…