目标网址:aHR0cHM6Ly95LnFxLmNvbS9uL3J5cXEvdG9wbGlzdC80
观前提示:
本文章仅供学习交流,切勿用于非法通途,如有侵犯贵司请及时联系删除
0x1 加密点位置
首先来到排行榜页面刷新
F12抓包过滤sign
字段即可
全局搜索sign
得出的结果并不多
随便找找下下断就能找到正确加密位置
0x2 扣代码
进入o
方法看到一些奇怪的代码
根据我的经验所得 这是一个jsvmp
不管那么多 先找到头和尾 扣出来放node里面运行先
要注意的是 这里的n(110)
其实就是window 手动赋值即可
微改完运行 根据node运行的报错来补环境
补window
补完window运行发现没有多的报错 此时我眉头稍微一紧 发现事情并不简单
方法运行完后即可运行_getSecuritySign
来计算sign
先跑个值和网页对比看看
node
web
果然 tx就是狡猾 不过这样才好玩
0x3 找坑
通过单步调试观察代码的运行逻辑 可以找到循环位置
在这个位置插桩是最适合不过的了 然后继续往上看
在解释代码里面大量出现i
字眼 想必这里就是模拟堆栈的 知道了这些信息 我们手动把循环位置魔改一下
for (var h = !1; !h;){ var xxx=n[t++]; console.log(i) h = d[xxx](); }
然后运行看输出即可
输出内容很多 耐心观察
window
navigator
这里拿到了navigator.userAgemt
而上面还出现了/Headless/i
和test
字眼
可以确定这里是判断你的ua是否为无头浏览器
location
这里拿了location.host
而后面出现了indexOf
和qq.com
可以判断这里是判断host是否为qq.com
再往后就没有看到其他环境检测的输出了
根据上述信息 简单补个环境
window=global; navigator={ userAgent:'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.82 Safari/537.36' } location={ host:'y.qq.com' }
补完对比一下输出值
node
web
一模一样了 是不是很简单
对比一下从jsvmp还原的代码
(function () { var v0, v1, v2, v3, v4, v5, v6, v7; v0 = [window]; v1 = [{}]; v2 = []; v3 = []; v4 = []; v5 = []; v6 = []; v7 = []; function func_17() { var v0, v1, v2, v3, v4, v5, v6, v7, v8; v0 = [window]; v1 = [arguments]; v2 = [func_17]; v3 = [func_135]; v4 = []; v5 = []; v6 = []; v7 = []; v8 = []; v9 = window["define"]; v9 = typeof v9; v9 = v9 === "function"; if (v9) { v9 = window["define"]["amd"]; if (v9) { v9 = window["define"](v3[0]); return void 0; } v9 = v3[0]([]); return void 0; } if (v9) { v9 = window["define"](v3[0]); return void 0; } v9 = v3[0]([]); return void 0; } function func_135() { var v0, v1, v2, v3, v4, v5, v6, v7, v8, v9; v0 = [window]; v1 = [arguments]; v2 = [func_135]; v3 = []; v4 = []; v5 = []; v6 = []; v7 = []; v8 = []; v9 = []; function func_158() { var v0, v1, v2, v3, v4, v5, v6, v7; v0 = [window]; v1 = [arguments]; v2 = [func_158]; v3 = []; v4 = []; v5 = []; v6 = []; v7 = []; v8 = window["global"]; v8 = typeof v8; v8 = v8 === "undefined"; v8 = !v8; if (v8) { v8 = window["global"]; return v8; } v8 = window["window"]; v8 = typeof v8; v8 = v8 === "undefined"; v8 = !v8; if (v8) { v8 = window["window"]; return v8; } v8 = window["self"]; v8 = typeof v8; v8 = v8 === "undefined"; v8 = !v8; if (v8) { v8 = window["self"]; return v8; } return void 0; } v11 = func_158([]); v8[0] = v11; function func_354() { var v354_0, v354_1, v354_2, v354_3, v354_4, v354_5, v354_6, v354_7, v354_8, v354_9, v354_10, v354_11, v354_12, v354_13, v354_14, v354_15, v354_16, v354_17, v354_18, v354_19, v354_20, v354_21, v354_22, v354_23, v354_24, v354_25, v354_26, v354_27, v354_28, v354_29, v354_30, v354_31, v354_32, v354_33; v354_0 = [window]; v354_1 = [arguments]; v354_2 = [func_354]; v354_3 = [arguments[0]]; v354_33 = [window]; v354_4 = []; v354_5 = []; v354_6 = []; v354_7 = []; v354_8 = []; v354_9 = []; v354_10 = []; v354_11 = []; v354_12 = []; v354_13 = []; v354_14 = []; v354_15 = []; v354_16 = []; v354_17 = []; v354_18 = []; v354_19 = []; v354_20 = []; v354_21 = []; v354_22 = []; v354_23 = []; v354_24 = []; v354_25 = []; v354_26 = []; v354_27 = []; v354_28 = []; v354_29 = []; v354_30 = []; v354_31 = []; v354_32 = []; v354_35 = window["Object"]; v354_35 = new (Function["bind"]["apply"](v354_35, null))(); v354_35["0"] = 0; v354_35["1"] = 1; v354_35["2"] = 2; v354_35["3"] = 3; v354_35["4"] = 4; v354_35["5"] = 5; v354_35["6"] = 6; v354_35["7"] = 7; v354_35["8"] = 8; v354_35["9"] = 9; v354_35["A"] = 10; v354_35["B"] = 11; v354_35["C"] = 12; v354_35["D"] = 13; v354_35["E"] = 14; v354_35["F"] = 15; v354_9[0] = v354_35; v354_10[0] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; v354_35 = window["__sign_hash_20200305"]; if (v354_35) { v354_36 = window["__sign_hash_20200305"](v354_3[0]); v354_35 = v354_36["toUpperCase"]([]); v354_11[0] = v354_35; v354_35 = window["window"]; v354_35 = typeof v354_35; v354_35 = v354_35 === "object"; if (v354_35) { v354_35 = window["navigator"]; v354_35 = typeof v354_35; v354_35 = v354_35 === "object"; if (v354_35) { v354_35 = window["location"]; v354_35 = typeof v354_35; v354_35 = v354_35 === "object"; v354_12[0] = v354_35; if (v354_12[0]) { v354_35 = window["RegExp"]; v354_35 = v354_35("Headless", "i"); v354_36 = window["navigator"]["userAgent"]; v354_35 = v354_35["test"](v354_36); v354_13[0] = v354_35; /*后面计算代码省略*/ } } } } } v9[0] = func_354; v11["_getSecuritySign"] = v9[0]; return void 0; } v8 = func_17(func_135); console.log(window._getSecuritySign) })()
从代码中可以清晰的见到检测环境的代码 但是并不参与计算 但是为什么会计算出来的结果不一样呢?
在继续观察了还原出来的代码后可以看到
function func_1338() { var v1338_0, v1338_1, v1338_2, v1338_3, v1338_4, v1338_5, v1338_6, v1338_7, v1338_8, v1338_9, v1338_10; v1338_0 = [window]; v1338_1 = [arguments]; v1338_2 = [func_1338]; v1338_3 = [arguments[0]]; v1338_9 = [v354_11[0]]; v1338_10 = [v354_14[0]]; v1338_4 = []; v1338_5 = []; v1338_6 = []; v1338_7 = []; v1338_8 = []; if (v1338_10[0]) { v1338_11 = v354_11[0][v1338_3[0]]; return v1338_11; } v1338_12 = v1338_3[0] + 1; v1338_11 = v354_11[0][v1338_12]; return v1338_11; }
通过v354_14[0]
的布尔值来决定走不同的分支而得出不同的结果
如果不是还原出来的话 单纯插桩可能并不能很好的找出坑人的点 但是 插桩对于补环境来说 完全够用了 自己写一个解释器来还原jsvmp对于大部分人来说费力不讨好 太耗时了 研究的话就还行
如果有兴趣的话可以去学习渔哥文章 https://blog.csdn.net/zjq592767809/article/details/124066638
知乎的jsvmp流程不长 代码简单 是学习的好网站
感谢各位大佬观看
共同进步 共同学习
如有错误 还请大佬们指出
[完]