某夕夕anti_content算法分析

Author Avatar
Tisoz 8月 22, 2022
  • 在其它设备中阅读本文章

image-20220821222635939

  • 代码中大量报错 , 按照顺序处理

403错误 , 未授权

  • 调整至fiddler工具中
  • 采集真实小程序中产生的token信息 , 并中转拦截处理

image-20220821223347276

  • 拦截授权请求后 , 业务接口可以正常访问

image-20220821223421840

  • 余下报错为初始化过程中 , wss初始化链接数过多 , 堆栈定位一下

  • 寻找r.MaxWebsocketConnect 参数初始化时引用的对象 , 并修改
  • app.js中修改调试器的全局参数__devtoolsConfig.setting.MaxWebsocketConnect = 5

image-20220821223708037

  • 此时已成功没有错误 , 429状态码为风控引起的返回状态码 , 忽略即可

anti_content算法

  • 随便定位一条带有anti_content的请求
  • https://xcxapp.pinduoduo.com/backend/conf/startup_v2

image-20220821223922053

  • 放眼望去 , 只有这么几条参数值得关注
  • 两条token大概率由授权请求返回的 , 不是我们关注的重心
  • xcx_hash看上去大概率为签名 , 最后一步看即可 , 接下来分析anti_content
  • 查看堆栈

image-20220821224114975

  • 直接忽略asdebug与waservice的堆栈 , 这是工具自身的引用栈 , 与业务代码无关 , 直接从41.js分析即可

image-20220821224252006

  • 确认引用了anti_content后 , 往上追溯至没有异步的地方或生成的地方

image-20220821224903896

  • 业务代码并没有严重的混淆 , 所以很轻松定位到了生成的位置 , 不过参数传入为boolean , 难道不应该为对象吗
  • 进入此函数 , 并打印传入参数

image-20220821225157248

  • 调试信息都不是想像中的亚子 , 那是不是找错链接了呢 , 尝试寻找其他较长的anti_content
  • 尝试调试了其他链接的anti_content后 ,长度不一致 , 问题不在外部函数 , 那么就需要深入anticontent函数了
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
function g(t) {
for (var e = t || {}, n = e.systemInfoAsync, a = e.fingerprintAsync, r = n || function() {
try {
return wx && wx.getSystemInfoSync ? wx.getSystemInfoSync() : {};
} catch (t) {
return {};
}
}(), i = a || function() {
try {
if (!wx || !wx.getStorageSync) return "";
var t = wx.getStorageSync("e488cb9fe650282");
if (!t || !t.data) return "";
var e = JSON.parse(t.data);
return e && e.a || "";
} catch (t) {
return "";
}
}() || l, h = r.model, u = r.pixelRatio, f = r.version, c = r.system, d = r.platform, _ = r.fontSizeSetting, p = r.SDKVersion, g = [].concat(v.packN(), A.packN(h), b.packN(), y.packN(), O.packN(), w.packN(), k.packN(), S.packN(), m.packN(), x.packN(), C.packN(u), z.packN(f), H.packN(c), E.packN(d), T.packN(_), D.packN(p), N.packN(i)), I = g.length.toString(2).split(""), M = 0; I.length < 16; M += 1) I.unshift("0");
I = I.join("");
var B = [];
0 === g.length ? B.push(0, 0) : g.length > 0 && g.length <= 255 ? B.push(0, g.length) : g.length > 255 && B.push(parseInt(I.substring(0, 8), 2), parseInt(I.substring(8, 16), 2)),
g = [].concat([ 3 ], [ 3, 0, 0 ], B, g);
var R = o.default.deflate(g), j = [].map.call(R, function(t) {
return String.fromCharCode(t);
});
return "3ak" + s.default.encode(j.join(""), s.default.budget);
}
  • 稍微深入后 , 即可发现anti_content的生成位置

image-20220821230035634

  • 最后一句encode的函数 , 粗略看上去像是类似base64的编码算法 , 直接调用即可
  • 看看encode前调用了哪些参数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
[
{
"data": 0
},
{
"data": "iPhone 5"
},
{
"data": [
"pages/index/index"
]
},
{
"data": 13
},
{
"data": [
83,
251,
218,
43
]
},
{
"data": "1451015129656341-1661093800919"
},
{
"data": "1001"
},
{
"data": ""
},
{
"data": 1661093800858
},
{
"data": 325444
},
{
"data": 2
},
{
"data": "8.0.5"
},
{
"data": "iOS 10.0.1"
},
{
"data": "devtools"
},
{
"data": 16
},
{
"data": "2.24.7"
},
{
"data": "uybW3WN48WL3SblRjUYCZeT4q0lDWdkx"
}
]
  • 到此为止 , 调用了哪些环境信息就可以知道了
  • 关于wss中请求的内容 , 有时间再讲一期 , 难度都不高

侵权说明

此分析仅供学习参考 , 并不提供源码以及代码指导 , 如有侵权 , 联系邮箱admin@tisoz.com删除

This blog is under a CC BY-NC-SA 3.0 Unported License
本文链接:http://www.tisoz.com/2022/08/22/%E6%9F%90%E5%A4%95%E5%A4%95anti_content%E7%AE%97%E6%B3%95%E5%88%86%E6%9E%90/