网易易盾分析与还原
版本介绍
- version=2.25.0
流程分析
第一步
-
https://c.dun.163.com/api/v2/getconf? 获取dt值 referer=https://dun.163.com/trial/jigsaw 固定 zoneId= id=07e2387ab53a4d6f930b8d9a9be71bdf 根据版本给值 ipv6=false 固定 runEnv=10 固定 iv=3 固定 type=2 固定 loadVersion=2.3.0 版本号 callback=__JSONP_wyuv1bg_0 固定 返回值: __JSONP_wyuv1bg_0({"data":{"dt":"PGJnPDj/HwBARxBAQVPUj+2LkyZp58nJ","ac":{"enable":1,"bid":"07e2387ab53a4d6f930b8d9a9be71bdf","pn":"YD20160637306799","token":"9ca17ae2e6fecda16ae2e6eeb5cb528ab69db8ea65bcaeaf9ad05b9c94a3a3c434898987d2b25ef4b2a983bb2af0feacc3b92ae2f4ee95a132e29aa3b1cd72abae8cd1d44eb0b7bb82f55bb08fa3afd437fffeb3"},"imageServer":["necaptcha.nosdn.127.net","necaptcha1.nosdn.127.net"],"zoneId":"CN31","resources":["/2.25.0/core-optimi.v2.25.0.min.js"],"apiServer":["c.dun.163.com","c.dun.163yun.com"],"theme":"light","audio":true,"customStyles":true,"smart":false,"staticServers":["cstaticdun.126.net","cstaticdun1.126.net"]},"error":0,"msg":"ok"}); dt: 后面都会用到
第二步
-
https://ac.dun.163.com/v3/d 获取actoken加密参数 d=太长了 加密值 v=af2952a4 看了好几遍,好像是固定的 cb=__wmjsonp_f5fc9a8 可以写死 返回值: __wmjsonp_f5fc9a8([200,1700464525546,"D5fLyoxVoKBBUBBURVLBj6nKxzbVFb2V","+7h9O3wMQPRAUBUQURLQj6ia1mbQAazB",null,"59gaxKuwElCTCSDGAb3uYItaXHOi2fhaVBCvdZjEBpF2fSi26c44ot2Cm+/5wt6SHOh3Q5WDuoMKffn5jEJSs2wSJjQ+Zl/wD5+D5KaLakP3rq16AVKlU6RX+oQtel/tZWI="]) 其中 D5fLyoxVoKBBUBBURVLBj6nKxzbVFb2V: acotoken加密会用到
第三步
-
https://c.dun.163.com/api/v3/get?referer=https://dun.163.com/trial/jigsaw 获取图片链接 zoneId=CN31 dt=PGJnPDj/HwBARxBAQVPUj+2LkyZp58nJ 第一步返回 acToken= 加密值 id=07e2387ab53a4d6f930b8d9a9be71bdf 根据版本给值 fp= 加密值 https=true type=2 version=2.25.0 版本 dpr=1.25 dev=1 cb= 加密值 ipv6=false runEnv=10 group= scene= lang=zh-CN sdkVersion=undefined iv=3 width=320 audio=false sizeType=10 smsVersion=v3 token= callback=__JSONP_v8gzn9e_0 写死也可以 返回值: __JSONP_v8gzn9e_0({"data":{"bg":["https://necaptcha.nosdn.127.net/cbb0cc9ff4e04f90ba5500b6e4f63f26.jpg","https://necaptcha1.nosdn.127.net/cbb0cc9ff4e04f90ba5500b6e4f63f26.jpg"],"front":["https://necaptcha.nosdn.127.net/21d34a3c29f44bdebcf809cbd82ef7c0.png","https://necaptcha1.nosdn.127.net/21d34a3c29f44bdebcf809cbd82ef7c0.png"],"token":"371b72e7f70d479b82b21ab55dd69686","type":2,"zoneId":"CN31"},"error":0,"msg":"ok"});
第四步
-
https://c.dun.163.com/api/v3/check?referer=https://dun.163.com/trial/jigsaw zoneId=CN31 dt=PGJnPDj/HwBARxBAQVPUj+2LkyZp58nJ 第一步获取 id=07e2387ab53a4d6f930b8d9a9be71bdf 版本给值 token=371b72e7f70d479b82b21ab55dd69686 图片token acToken=undefined data= 太长了 加密值 width=320 type=2 version=2.25.0 版本号 cb= 加密值 extraData= bf=0 runEnv=10 sdkVersion=undefined iv=3 callback=__JSONP_1ytknx9_1 返回值: __JSONP_1ytknx9_1({"data":{"result":true,"zoneId":"CN31","token":"371b72e7f70d479b82b21ab55dd69686","validate":"8gxMgwjCs36ABQyKiWXApPYj4qmeePZtNacdk+33/pWyyVk9xmp6Fe6etQ75HC/G/p4SqUksSPlt8+SstaDC3Eve43eTujSRtRjRkjwxQHo22s8Buz9c9VbbYx4NxnBvEQgjlpdU0Dw2z2f/exbmvgzIJMUOfhFE2Y46I27iaOc="},"error":0,"msg":"ok"});
算法分析
d字段 watchman.min.js
window.navigator
window.screen
window.storage
window.document
canvas
检测的环境挺多的,但是感觉对d值的校验不严,只要能出值就可以获得返回值
actoken字段 watchman.min.js
整个函数拿下来,然后把函数导出,ec函数多加一个形参并把它赋值给g变量,p直接写死1。图三就补那些环境就好了,调用方式也在上面。
fp字段 core-optimi.v2.25.0.min.js
检测一堆环境,最难的是canvas检测,它先是把要检测的模块放到vN里,然后去canvas中对应模块的color
轨迹 core-optimi.v2.25.0.min.js
通过跟栈就能找到data字段的加密位置, data字段包含滑块轨迹,这里先看滑块轨迹
通过跟栈,跟到
var V = w['sample'](this[AP(0x713)], C);
this[AP(0x71d)]({
'data': JSON[AP(0x41b)]({
'd': D(V[AP(0x2c2)](':')),
'm': '',
'p': q0,
'f': D(T(U, q1[AP(0x2c2)](','))),
'ext': D(T(U, this['mouseDownCounts'] + ',' + this[AP(0x713)]['length']))
})
})
this[AP(0x713)]就是滑动的轨迹了.
而w['sample'](this[AP(0x713)], C) 就是取 this[AP(0x713)] 的50条数据.
可以看到,代码都被混淆过了.直接在 core-optimi.v2.25.0.min.js 文件中搜索 0x713 一共有15条,都打上断点,滑动滑块,就可以知道 this[AP(0x713)] 在哪里被赋值了.
具体代码:
var q3 = this['$store'][AB(0x119)][AB(0x3a9)]
, q4 = [Math['round'](U['dragX'] < 0x0 ? 0x0 : U[AB(0x35b)]),
Math[AB(0x28a)](U[AB(0x426)] - U['startY']), w[AB(0x386)]() - U[AB(0x6de)]];
this['atomTraceData'][AB(0x10b)](q4);
var q5 = T(q3, q4 + '');
this[AB(0x713)][AB(0x10b)](q5),
AB(0x11c) === U[AB(0x1a3)] && this[AB(0x435)](Z),
AB(0x101) === U[AB(0x1a3)] && this[AB(0x370)](Z);
这里利用插桩
window.myMap = new Map(); 这句放在 core-optimi.v2.25.0.min.js 文件的开始位置
window.myMap.set(q5, q4); 这句放在 var q5 = T(q3, q4 + ''); 的下面
for (var key in V) {
console.log(V[key], window.myMap.get(V[key]))
} 这句放在 var V = w['sample'](this[AP(0x713)], C); 的下面
最后输出
rOA/04NgiA33 (3) [4, 1, 213]
rOA/04NUip33 (3) [4, 1, 221]
r/A/04NU/p33 (3) [5, 1, 225]
reA/04NUxp33 (3) [6, 1, 229]
rwA/04N0iA33 (3) [7, 1, 233]
\OA/04Niip33 (3) [8, 1, 241]
viijiIIU/gp3 (3) [10, 1, 245]
viXjiIIU/gZ3 (3) [11, 1, 248]
vizjiIIU/vi3 (3) [12, 1, 251]
vipjiIIU/vp3 (3) [14, 1, 255]
viqjiIIU/4X3 (3) [16, 1, 260]
viqjiIIU/4z3 (3) [16, 1, 263]
vicjiIIU/4j3 (3) [18, 1, 266]
viZjiIIU/EX3 (3) [19, 1, 270]
vAijiIIU/EZ3 (3) [20, 1, 278]
vAXjiIIUxgz3 (3) [21, 1, 283]
vAzjiIIUxgZ3 (3) [22, 1, 288]
vApjiIIUxvX3 (3) [24, 1, 290]
vApjiIIUxvp3 (3) [24, 1, 295]
vAqjiIIUxvZ3 (3) [26, 1, 298]
vAjjiII0igp3 (3) [27, 1, 305]
vAcjiII0igq3 (3) [28, 1, 307]
vAcjiII0ivi3 (3) [28, 1, 311]
vcijiII0ivr3 (3) [30, 1, 314]
vcXjiII0ivZ3 (3) [31, 1, 318]
vczjiII0i4r3 (3) [32, 1, 324]
vcNjiII0i4q3 (3) [33, 1, 327]
vcrjiII0iEi3 (3) [35, 1, 331]
vcqjiII0iEp3 (3) [36, 1, 335]
vccjiII0iEZ3 (3) [38, 1, 338]
rpijiII0/gz3 (3) [40, 1, 343]
rpXjiII0/gj3 (3) [41, 1, 346]
rpNjiII0/vN3 (3) [43, 1, 352]
rppjiII0/vr3 (3) [44, 1, 354]
rpqjiII0/vc3 (3) [46, 1, 359]
rpcjiII0/4z3 (3) [48, 1, 363]
riijiII0/4j3 (3) [50, 1, 366]
rizjiII0/EN3 (3) [52, 1, 372]
riNjiII0/Er3 (3) [53, 1, 374]
rirjiII0/Ec3 (3) [55, 1, 379]
riqjiII0xgN3 (3) [56, 1, 382]
rijjiII0xgq3 (3) [57, 1, 387]
riZjiII0xvi3 (3) [59, 1, 391]
rAijiII0xvr3 (3) [60, 1, 394]
rAzjiIIiigX3 (3) [62, 1, 400]
rApjiIIiigN3 (3) [64, 1, 402]
rArjiIIiigq3 (3) [65, 1, 407]
rAjjiIIiivX3 (3) [67, 1, 410]
rAcjiIIiivp3 (3) [68, 1, 415]
rcijiIIiivc3 (3) [70, 1, 419]
rczjiIIii4N3 (3) [72, 1, 422]
rcNjiIIii4p3 (3) [73, 1, 425]
rcrjiIIii4c3 (3) [75, 1, 429]
rcjjiIIiiEz3 (3) [77, 1, 433]
rcZjiIIiiEj3 (3) [79, 1, 436]
\pijiIIi/gi3 (3) [80, 1, 441]
\pzjiIIi/gr3 (3) [82, 1, 444]
\ppjiIIi/vi3 (3) [84, 1, 451]
\prjiIIi/vz3 (3) [85, 1, 453]
\pjjiZIi/vq3 (3) [87, 0, 457]
\pZjiZIi/4N3 (3) [89, 0, 462]
\iXjiZIi/4r3 (3) [91, 0, 464]
\izjiZIi/EX3 (3) [92, 0, 470]
\iNjiZIi/EN3 (3) [93, 0, 472]
\iqj0Eiq/gu2 (3) [96, -1, 478]
\ijj0Eiq/g4P (3) [97, -1, 481]
\iZj0Eiq/g46 (3) [99, -1, 484]
viii0ZAg0gvGii33 (3) [100, -1, 490]
viix0ZAg0gvGic33 (3) [102, -1, 492]
vii10ZAg0gvGxi33 (3) [103, -1, 498]
viiX0ZAg0gOpip33 (3) [104, -1, 521]
多试几次就可以分析出规律来了
分析了一下可以得出
x坐标:x的增量只有1-3 而且增量为1和2的居多 为3的最少 这种情况不就是循环递增吗 到时候1和2的情况我们就给他随机取两值,
3的情况就它出现的概率小点1/10就差不多了.
y坐标:纵坐标的值一直为0是过不了的,所以要有浮动,观察数据大概设计前80个轨迹的y值是不变的(其实y值只要变一次就可以了).
我们用 Number.isInteger(slide_track.length / l) l的值初始为50,一到50我们就
_y -= 1;
l += (slide_track.length / 10) * 10;
完整代码:
if(Number.isInteger(slide_track.length / l)){
_y -= 1;
l += (slide_track.length / 10) * 10;
}
这里注意
缺口x坐标为94的轨迹:
/OWOPAq81i33 (3) [4, 0, 184]
/wWOPAr11c33 (3) [7, 0, 206]
x/WOPAr/1i33 (3) [9, 0, 224]
iiu+rea/1ii3 (3) [11, 0, 240]
iiO+rea/1pi3 (3) [13, 0, 250]
ii7+rea/1ci3 (3) [15, 0, 260]
ii/+rea/1AX3 (3) [17, 0, 271]
iiD+rea/1Aq3 (3) [19, 0, 276]
iAu+rea/iiq3 (3) [21, 0, 286]
iAv+PcqRxcZ1 (3) [22, -1, 292]
iA7+PcqRxAiX (3) [25, -1, 305]
iA/+PcqRxAXg (3) [27, -1, 314]
iAD+PcqRxAzg (3) [29, -1, 324]
icu+PcqRxAz7 (3) [31, -1, 328]
icO+PcqRxANU (3) [33, -1, 337]
ic7+PcqRxApg (3) [35, -1, 344]
ic/+PcqRxAr/ (3) [37, -1, 350]
icD+PcqRxAqi (3) [39, -1, 361]
/pu+PcqRxAqz (3) [41, -1, 369]
/pO+PcqRxAjg (3) [43, -1, 374]
/pg+PcqRxAc0 (3) [46, -1, 386]
/pL+PcqRxAZg (3) [48, -1, 394]
/i9+PcqR1iig (3) [50, -1, 404]
/iv+PcqR1ii7 (3) [52, -1, 408]
/i++PcqR1iX0 (3) [54, -1, 416]
/ig+PcqR1iz0 (3) [56, -1, 426]
/iL+PcqR1iN0 (3) [58, -1, 436]
/A9+PcqR1ip0 (3) [60, -1, 446]
/Av+PcqR1irz (3) [62, -1, 459]
/A++PcqR1iqX (3) [64, -1, 465]
/A/+PcqR1ij0 (3) [67, -1, 476]
/AD+PcqR1ic7 (3) [69, -1, 488]
/cu+PcqR1pig (3) [71, -1, 504]
/cO+PcqR1pzi (3) [73, -1, 521]
/c7+PcqR1ppg (3) [75, -1, 544]
/c/+PcqR1pqg (3) [77, -1, 564]
/cD+PcqR1pc/ (3) [79, -1, 580]
xpu+PcqR1ci1 (3) [81, -1, 602]
xpO+PcqR1czX (3) [83, -1, 625]
xp7+PcqR1cN7 (3) [85, -1, 638]
xpL+PcqR1cq1 (3) [88, -1, 662]
xi9+PcqR1ccx (3) [90, -1, 683]
xiv+PcqR1cZ7 (3) [92, -1, 698]
xi++PcqR1Aiz (3) [94, -1, 709]
xig+PcqR1ANi (3) [96, -1, 731]
xiL+PcqR1ArU (3) [98, -1, 757]
ii9OPeSxgij7/i33 (3) [100, -1, 780]
ii9PPeSxgic7ip33 (3) [102, -1, 885]
ii9nPeS/giZ71i33 (3) [103, -2, 988]
ii9rPeS/giX//iq3 (3) [105, -2, 1006]
可以看到它的最后一个x坐标是105, 但是在网页上它的坐标应该是94(下方有图), 这里注意用截图工具识别时, 电脑的缩放比例一定要是100%不然320 * 160的图片, 你量起来就不是320 * 160例如我自己的电脑本身的缩放是125%, 我量出来的结果是400 * 200所以卡了两小时.
总结
我觉得轨迹检测不严格,倒是fp值检测最为严格,fp不补完整,通过率非常低。
2023-12-10 完结
ge1" style=“zoom:400%;” />
全部轨迹:95
左移:'84.5px'
全部轨迹 - ddddocr:8
ddddocr - 左移:2.5
ddddocr:99
全部轨迹:108
左移:97.5
全部轨迹 - ddddocr:9
ddddocr - 左移:1.5
ddddocr:248
全部轨迹:256
左移:'245.5px
全部轨迹 - ddddocr:12
ddddocr - 左移:2.5
ddddocr:252
全部轨迹:261
左移:'249.5px'
全部轨迹 - ddddocr:9
ddddocr - 左移:2.5
ddddocr:84
全部轨迹:92
左移:'81.5px'
全部轨迹 - ddddocr:8
ddddocr - 左移:2.5
ddddocr:232
全部轨迹:240
左移:'229.5px'
全部轨迹 - ddddocr:8
ddddocr - 左移:2.5
总结
我觉得轨迹检测不严格,倒是fp值检测最为严格,fp不补完整,通过率非常低。
2023-12-10 完结