目标网址: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流程不长 代码简单 是学习的好网站
感谢各位大佬观看
共同进步 共同学习
如有错误 还请大佬们指出
[完]
长按点击关注
逆向lin狗
原文始发于微信公众号(逆向lin狗):[2022-5-21]某音乐sign分析
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论