-
-
[原创]akamai参数简单分析---mst
-
发表于: 22小时前 150
-
作者声明:文章仅供学习交流与参考!严禁用于任何商业与非法用途!否则由此产生的一切后果均与作者无关!如有侵权,请联系作者本人进行删除!
1、参数分析小笔记
mst:
kevl: 1, 第三次请求中数值会变
mevl: 32,第三次请求中数值会变
devl和dmvl: 0, 第三次请求中数值会变和dme、doe有关联sts:时间戳
tovl:等于ajr的totVel
kc: 0, 第三次请求为1
mc:0, 第三次请求中为鼠标轨迹组数
ww8:0, 第三次请求中数值会变
jsrf1和jsrf2:通过时间戳计算得到的长度为2的数组delt和ssts:ajr生成逻辑中deltaTimestamp
dvc: vmp中(参数1是delt,参数2是ajr,参数3是请求轮次(0、1、2),参数4是tovl)
2、mst参数分析
mst需要关注的就dd2、jsrf1、jsrf2、dvc,其中的难点就是dvc的jsvmp。

把代码还原一下,也可以直接在作用域里面找一下,快速定位生成位置。

jsrf1、jsrf2就是通过计算时间戳得到,跟进XP2函数,连混淆都没有,直接复制就可以了。


var SWT = function (zYT) {
var Y4 = zYT[0] - zYT[1];
var RmT = zYT[2] - zYT[3];
var A4 = zYT[4] - zYT[5];
var SKT = S6["Math"]["sqrt"](Y4 * Y4 + RmT * RmT + A4 * A4);
return S6["Math"]["floor"](SKT);
};
var M6T = function (YpT) {
var ck = S6["Math"]["floor"](S6["Math"]["random"]() * 100000 + 10000);
var cmT = S6["String"](YpT * ck);
var pmT = 0;
var zTT = [];
var vJT = cmT["length"] >= 18 ? true : false;
while (zTT["length"] < 6) {
zTT["push"](S6["parseInt"](cmT["slice"](pmT, pmT + 2), 10));
pmT = vJT ? pmT + 3 : pmT + 2;
}
var lCT = SWT(zTT);
return [ck, lCT];
};继续找dd2,简单还原下

parseInt(parseInt(S6.window.bmak.startTs / 23, 10) / (2016 * 2016), 10)
3、dvc里面的vmp参数分析
首先是插桩点:
1、while里面的epcode。
2、get和set方法。
3、String.fromCharCode方法。
4、this中变量的赋值、push操作。
5、算术运算(加减乘除求余)、位运算(与或非异或左移右移)位置。
打印好日志保存到本地分析,从后往前看。
最终结果是"acigcf9aYkakYf" + "acsw1v"得到,先分析"acigcf9aYkakYf"。

"acigcf9aYkakYf"的生成:每一个字符的添加都是["a","c","d","9","f","h","i","k","l","7","p","q","s","1","v","w","x","y","B","2"]数组的索引值,索引值又与那个疑似时间戳的里面得到。整体逻辑就是,遍历"01761530890985",取值作为索引去获取数组中的值。

"acsw1v"的生成,往上找一下’v',可以看到v来源于这个22数组。

往上找17,看到17 = 2366799 % 22。继续搜索2366799,我这里少打了减法的运算日志,但是可以看出2366799 = 2366910 - 111, 2366910 = 3315 * 714。其中减法运算的结果是要加绝对值Math.abs的。


向上找3315,可以看到3315 = 3264 | 51,3264 = 102 << 5,51 = 102 >> 1。

102 = "f".charCodeAt(),22数组对应索引5就是f,刚好v值的生成就是第6个。102 >> 1的1来源11010101000010110110011011011001的索引5,102 << 5里面的5是固定的。


向上找714,714 = 816 - 102, 816 = 102 << 3,3 = 3*1。 其中的102、1和前面一样。

搜索11010101000010110110011011011001的生成位置,从这个日志可以看出这是通过Number转的二进制字符串,使用toString(2)。


继续找3574294233,发现3574294233 = 181556985 + 3392737248,3392737248 = -902230048 >>> 0, 181556985 = 181556985 >>> 0。


分析-902230048和181556985的生成。整理下生成逻辑,发现是循环"01761530890982) Chrome/141.0.0.0 Safari/537.360",charCodeAt转十进制整数,上一次结果和固定数值33相乘,再和前面转码结果进行异或运算,-902230048和181556985生成都是一个逻辑。


大致流程基本上都走完了,还有一个22数组的生成,是根据固定数值"a3cd9efghiYjklm7opqrs1uvwQxyBz2"和前面的二进制字符串生成的。
4、vmp流程小结
- 初始数值:浏览器的ua、"a3cd9efghiYjklm7opqrs1uvwQxyBz2"、时间戳。传入参数分别对应delt、ajr、请求轮次、tovl。
- 预处理:算法会先把收集到的信息做两步处理,目的是把字符串类的信息转化为数值,方便后续运算:
- 将 “浏览器标识 + 时间戳 + 部分自定义参数”、“时间间隔 + 业务标识 + 固定 0” 这两组拼接后的字符串,分别通过一套哈希规则(类似给字符串算一个唯一数字)生成两个核心数值;
- 把这两个数值相加后转成二进制,同时单独把第一组的哈希值也转成二进制,得到两个二进制字符串(相当于生成了两组 “数字密钥”)。
- 筛选 “字符池”:用第二步生成的二进制字符串作为筛选规则,从预设的固定字符串里挑出一部分字符,组成一个 “可用字符池”:
- 规则很简单,要么字符位置的二进制位是 1,要么位置是 3 的倍数,满足其一就入选;
- 这个字符池是后续生成最终字符串的唯一来源。
- 生成最终字符串(分两段拼接):基于筛选好的字符池,用两种不同规则生成两段字符串,最后拼在一起就是最终结果:
- 第一段(简单规则):把 “自定义参数 + 加 3 后的时间戳” 拼接成字符串,每个字符直接当索引,从字符池里取对应位置的字符,拼起来;
- 第二段(复杂规则):取字符池前 6 个字符,每个字符先转成编码值,再做一系列位运算、算术运算(移位、乘减、取绝对值等),运算结果取余后再当索引,从字符池里重新取字符,拼成 6 位字符串;
- 最终结果 = 第一段字符串 + 第二段字符串。