网易易盾滑动验证码破解(下篇)

网易易盾滑动验证码破解(下篇)

接着上篇文章,我们在这篇文章中将会介绍,如何获取验证码和token,然后计算验证码缺口距离以及模拟轨迹生成等操作。

获取验证码

先看下获取验证码的请求(get请求):

url=https://c.dun.163.com/api/v2/get?,参数如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
id: 07e2387ab53a4d6f930b8d9a9be71bdf
fp: hiXxMilwZwpb4+sPEBt7K4oMVlNDs1S7S/gSM+3CXwzXT61XEHUGWJ+KRpmQIBeAAaIce9YQE4koUZTctLkYBUU8TKdailKmA4yQBLqLOX/kBhCCeWYo4n6f3hVt91ql4g\52gzqt/95LLSwJLciW6C8pXVTxGxc0HmqhNP/pqrGca+6:1597838263871
https: true
type: 2
version: 2.14.0
dpr: 1
dev: 1
cb: CZU+qZFVc/pqC0dVRuPJJAvHF6vHAvfOaReW7FqVZrpR4cdM9avS/c\qJlBrAeKA
ipv6: false
runEnv: 10
group:
scene:
width: 320
token:
referer: https://dun.163.com/trial/jigsaw
callback: __JSONP_bzmv2ur_0

需要动态变化的参数只有fp参数和cb参数,这里cb参数生成方式其实与我们上篇中的cb是一样的,所以重点是fp参数,也就是fingerprint(指纹)。

fingerprint指纹

在寻找fp参数的时候,我是定位到了这个位置(当然也不是一下就找到了,当时还在利用fp参数一直调试找调用栈,至今利用那种方法也没弄清怎么定位到这里,也是一些碰巧的发现让我定位到这里,对于新手你顶多多花点时间反正总是可以找到):

fingerprint就是window.gdxidpyhxde的值,我在代码里找了很久没找到在哪里给window.gdxidpyhxde进行的赋值,身边的大佬告诉我这种window对象要用Hook(钩子)来获取,并且要借助一个名叫油猴插件的工具来完成,这里有一篇介绍这个的文章,大家可以参考下。

安装完插件,按照教程上的操作,添加脚本,编译以下内容:

保存并启用脚本后,然后刷新网页,就能够捕获到window.gdxidpyhxde赋值的地方:

这里有一个有意思的地方需要絮叨絮叨,顺着调用栈可以找到P方法,P方法的参数传进来就是fp,继续查看调用栈发现是Y()方法生成了fp,Y里面又调用了X,X方法时这样的:

1
2
3
4
5
6
7
8
9
10
11
function X(e) {
for (var n = (G[u[160]] || l[0]).split(s[78]), i = t[9]; i < n.length; i++) {
var r = n[i].indexOf(u[10]);
if (r >= t[9]) {
var o = n[i].substring(r + t[535], n[i].length);
if (n[i].substring(t[9], r) == e)
return window.decodeURIComponent(o)
}
}
return null
}

如果仔细观察,会发现G[u[160]]实际上是这样的值:

1
__snaker__captcha=oRtq9nvAm0QouuvG; _qddac=3-3-1.1.5i4x48.kd9xulyf; _9755xjdesxxd_=32; __root_domain_v=.163.com; _qddaz=QD.jdy8os.x4rgyl.kd5r5e86; YD20160637306799%3AWM_NI=OI%2B1pcpJjmLWcaLwLFnU7l6Alay87tDl4%2B6%2F4pS4A0beBJoX90bwRdW8WMIzxsaQQDfRrXvTbwsEBjnY7hYtxa1sFTgrCD0ytgx5kixGZsS3rL%2BBjh0sLh5NsKYTSsgAVkw%3D; YD20160637306799%3AWM_TID=y1dRdZ6v4M5FBBVEBEY%2BGoL66uK9h7Y1; YD20160637306799%3AWM_NIKE=9ca17ae2e6ffcda170e2e6eed7ed3ba5ae9cd8fc33ad9e8fa2d45e879a8bbbf144b891fa97b55cfcb4babbef2af0fea7c3b92a8d97e5d2f369b496a68ecf5da1bf8498cf4eae8bf98db54bb0bfb7d9b68088b4fcccb525f8b09dd5c43ca2bb8eabee54fbf0ae98d17095e899aecc72bcadafb2d450a68ebeb9f560a2a9bda6c162ae87f989dc80bcbfff94c560a5ae8da5b373b8b9b8d6ea63bc999694d239b294e5a3e964f4ad8489b846b19597b5d279a59f9a8cf637e2a3; Hm_lvt_4671c5d502135636b837050ec6d716ce=1595489168,1596182503; _qdda=3-1.1; _qddab=3-5i4x48.kd9xulyf; _qddamta_2852175932=3-0; gdxidpyhxdE=0Mvsl573PzyW0pM%2BnVVaI7IjUXbqquQxvm6KroZg4tRV%2B70uYeaA1Q5E0wwZhn0%2FDy%5CuDA2Zte8Mm%2FvlnuKOi%2B%5CzTwEDaqsydVaPNLhAJR17o0vNtHQlCvCf87C5dJ1RlKuOebbgKIWVTVJORAIaQQtrbzdDp62IePWDwDSB%2B%2F88CE7Q%3A1596184305983; Hm_lpvt_4671c5d502135636b837050ec6d716ce=1596184180

其实就是cookie,这样就有一个问题,我们本身是获取不到cookie的,这里生成fp居然需要cookie,有点不对劲,其实这里面的逻辑是这样的:因为我们现在操作的页面(在浏览器中)是有cookie的(并且cookie在有效期内),所以生成fp参数的直接利用cookie就可以了,如果我们尝试着清掉cookie以及缓存,再刷新页面,会得到这样的结果:

发现调用栈这边比刚才多了一个W,实际上这才是我们要找的fp参数生成的地方。

有大佬是把W方法更外层一整个方法扣出来,然后自己找了一些DOM对象(这个操作做不来,我选择放弃)。

继续在W()内部研究一会可以发现,h = h + u[7] + p这是fp最后生成的代码

u[7]是冒号,p是一个时间戳,所以fp得格式是这样的:

1
60G6u4NNUxBAYgIk2G3wXUckAQ8GEBbbS+U4acoYQs+4ggT3XQRUYRmQQKMdcBvMjM6rrsw8ofKOp7BN3V0nLJjSt5ngLhQ3bkJ38ahyUvzM9R2M+Jbb8IHeUeWjBR3StpJBowR8kbcSs/od47bPIzD+klY46HTmNlm1/yLDqjiLZ+Jv:1611914097232

这里把W()方法抠出来,并做一定的调整,在运行的时候缺啥补啥就好了,我这里没细扣,用的同事的

fingerprint的生成方法:

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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
var host = "dun.163.com"
var u = ["5","6","InactiveCaptionText","7","WEBZEN Browser Extension","8","9",":","DivX Browser Plug-In",";","=","Uplay PC","canvas exception","A","B","C","D","E","微软雅黑","F","Harrington","G","H","I","J","Gnome Shell Integration","K","L","M","N","O","P","Q","R","S","Niagara Solid","T","SefClient Plugin","U","V","1111","W","X","Y","Z","Goudy Old Style","\\","Roblox Launcher Plugin","Microsoft Office 2013","QQMusic","a","Eurostile","b","rmocx.RealPlayer G2 Control.1","c","Scripting.Dictionary","d","仿宋","e","f","g","h","Ma-Config.com plugin","i","1010","Casual","j","k","l","m","n","o","p","1008","ct","doNotTrack","q","setTimeout","丽宋 Pro","r","Gisha","getTimezoneOffset","s","1005","1004","t","u","1003","v","1001","w","x","drawArrays","y","z","{","}","~","font","1009","=null; path=/; expires=","Shell.UIHelper","toDataURL","WindowText","language","do","丽黑 Pro","HighlightText","div","MenuText","AOL Media Playback Plugin","Citrix online plug-in","ec","Desdemona","InactiveBorder","RealPlayer","HELLO",", 'code':","em","npTongbuAddin","createElement","phantom","MS PMincho","楷体","eval","ex","DivX VOD Helper Plug-in","新细明体","QuickTimeCheckObject.QuickTimeCheck.1","FlyOrDie Games Plugin","attachShader","PlayOn Plug-in","getTime","1.01","Broadway","fp","Alawar NPAPI utils","Forte","hashCode","方正姚体","ESN Sonar API","HPDetect","Bitdefender QuickScan","IE Tab plugin","',","ButtonFace","cpuClass","Century Gothic","Online Storage plug-in","Safer Update","Msxml2.DOMDocument","Engravers MT","Silverlight Plug-In","Google Gears 0.5.33.0","Citrix ICA Client","alphabetic","VDownloader","华文楷体","attrVertex","宋体","cookie","%22","%26","Centaur","4game","Rockwell","LogMeIn Plugin 1.0.0.961","Octoshape Streaming Services","toGMTString","th=/","SumatraPDF Browser Plugin","PDF.PdfCtrl","fillStyle","je","Adobe Ming Std","TorchHelper","Franklin Gothic Heavy","华文仿宋","Harmony Plug-In","Gigi","v1.1","Kino MT","SimHei","AliSSOLogin plugin","RealPlayer.RealPlayer(tm) ActiveX Control (32-bit)","Yandex PDF Viewer","Citrix Receiver Plug-in","mai","top","AcroPDF.PDF","canvas api exception","InactiveCaption","Menu","precision mediump float; varying vec2 varyinTexCoordinate; void main() { gl_FragColor = vec4(varyinTexCoordinate, 0, 1); }","QQ2013 Firefox Plugin","Google Update","华文彩云","eMusicPlugin DLM6","Web Components","Babylon ToolBar","Coowon Update"]
var t = [66,60,79,60,7,17,33,96,68,0,2,1423857449,-2,3,-3,3432918353,1555261956,4,2847714899,-4,5,-5,2714866558,1281953886,6,-6,198958881,1141124467,2970347812,-7,7,3110523913,8,-8,2428444049,-9,9,10,-10,-11,11,2563907772,-12,12,13,2282248934,-13,2154129355,-14,14,15,-15,16,-16,17,-17,-18,18,19,-19,20,-20,21,-21,-22,22,-23,23,24,-24,25,-25,-26,26,27,-27,28,-28,29,-29,30,-30,31,-31,33,-33,-32,32,-34,-35,34,35,37,-37,36,-36,38,39,-39,-38,40,41,-41,-40,42,-43,-42,43,45,-45,-44,44,47,-46,-47,46,48,-49,-48,49,-50,51,-51,50,570562233,53,-52,52,-53,-54,-55,55,54,503444072,57,-56,-57,56,59,58,-59,-58,60,61,-61,-60,62,63,-63,-62,-64,711928724,-66,67,-65,65,-67,66,64,-71,-69,69,68,70,-68,-70,71,-72,3686517206,-74,-73,73,75,74,-75,72,-79,76,79,78,-78,-76,77,-77,3554079995,-81,81,-82,-83,80,-80,82,83,-84,84,85,-86,-87,86,-85,87,90,-88,-89,-90,88,89,91,-91,94,92,95,-94,93,-93,-95,-92,-98,97,98,-97,-99,96,99,-96,-100,3272380065,102,-102,-101,-103,103,100,101,-107,-104,105,104,106,-106,-105,107,109,-109,-108,-111,110,-110,111,108,251722036,115,-115,112,-114,-112,113,114,-113,-117,119,-116,-119,117,-118,118,116,123,-120,122,-121,120,-122,-123,121,125,127,3412177804,-127,126,-126,124,-125,-124,-128,128,-129,1843258603,3803740692,984961486,3939845945,4195302755,4066508878,255,1706088902,256,1969922972,365,2097651377,376229701,853044451,752459403,1000,426522225,3772115230,615818150,3904427059,4167216745,4027552580,3654703836,1886057615,879679996,3518719985,3244367275,2013776290,3373015174,1759359992,285281116,1622183637,1006888145,10000,1231636301,83908371,1090812512,2463272603,1373503546,2596254646,2321926636,1504918807,2181625025,2882616665,2747007092,3009837614,3138078467,397917763,81470997,829329135,2657392035,956543938,2517215374,2262029012,40735498,2394877945,3266489909,702138776,2808555105,2936675148,1258607687,1131014506,3218104598,3082640443,1404277552,565507253,534414190,1541320221,1913087877,2053790376,1789927666,3965973030,3826175755,4107580753,4240017532,1658658271,3579855332,3708648649,3453421203,3317316542,1873836001,1742555852,461845907,3608007406,1996959894,3747672003,3485111705,2137656763,3352799412,213261112,3993919788,1.01,3865271297,4139329115,4275313526,282753626,1068828381,2768942443,2909243462,936918000,3183342108,27492,141376813,3050360625,654459306,2617837225,1454621731,2489596804,2227061214,1591671054,2362670323,4294967295,1308918612,2246822507,795835527,1181335161,414664567,4279200368,1661365465,1037604311,4150417245,3887607047,1802195444,4023717930,2075208622,1943803523,901097722,628085408,755167117,3322730930,3462522015,3736837829,3604390888,2366115317,0.4,2238001368,2512341634,2647816111,-0.2,314042704,1510334235,900000,58964,1382605366,31158534,450548861,3020668471,1119000684,3160834842,2898065728,1256170817,2765210733,3060149565,3188396048,2932959818,124634137,2797360999,366619977,62317068,-0.26,1202900863,498536548,1340076626,2405801727,2265490386,1594198024,1466479909,2547177864,249268274,2680153253,2125561021,3294710456,855842277,3423369109,0.732134444,3705015759,3569037538,1994146192,1711684554,1852507879,997073096,733239954,4251122042,601450431,4111451223,167816743,3855990285,3988292384,3369554304,3233442989,3495958263,3624741850,65535,453092731,-0.9,2094854071,1957810842,325883990,4057260610,1684777152,4189708143,3915621685,162941995,1812370925,3775830040,783551873,3134207493,1172266101,2998733608,2724688242,1303535960,2852801631,112637215,1567103746,651767980,1426400815,906185462,2211677639,1047427035,2344532202,2607071920,2466906013,225274430,544179635,2176718541,2312317920,1483230225,1342533948,2567524794,2439277719,1088359270,671266974,1219638859,840000,953729732,3099436303,2966460450,817233897,2685067896,2825379669,4089016648,4224994405,3943577151,3814918930,476864866,1634467795,335633487,1762050814,1,2044508324,-1,3401237130,3268935591,3524101629,3663771856,1907459465]
var e = ["InfoText","rmocx.RealPlayer G2 Control","iMesh plugin","RealDownloader Plugin","Symantec PKI Client","_phantom","GDL Object Web Plug-in 16.00","webgl","华文宋体","screen","body","TRIANGLE_STRIP","n=","TlwgMono","':'","LogMeIn Plugin 1.0.0.935","function","context.hashCode","ArchiCAD","VERTEX_SHADER","Ubuntu","Facebook Plugin","ActiveCaption","细明体","Malgun Gothic","News Gothic MT","CaptionText","aZbY0cXdW1eVf2Ug3Th4SiR5jQk6PlO7mNn8MoL9pKqJrIsHtGuFvEwDxCyBzA","DejaVu LGC Sans Mono","Copperplate Gothic Light","Segoe Print","Sawasdee","Bauhaus 93","Chalkduster","Abadi MT Condensed Light","Lucida Bright","Wide Latin","font detect error","Kozuka Gothic Pr6N","Html5 location provider","DivX Plus Web Player","Vladimir Script","File Downloader Plug-in","ob","Adodb.Stream","Menlo","callPhantom","Wolfram Mathematica","CatalinaGroup Update","Eras Bold ITC","DevalVRXCtrl.DevalVRXCtrl.1","华文细黑","addBehavior","pa","Bitstream Vera Serif","(function(){return 123;})();","pi","Tencent FTN plug-in","removeChild","Folx 3 Browser Plugin","useProgram","hostname","phantom.injectJs","ShockwaveFlash.ShockwaveFlash","rgba(102, 204, 0, 0.7)","AdblockPlugin","Background","AgControl.AgControl","PhotoCenterPlugin1.1.2.2","GungSeo","s=","decodeURI","方正舒体","华文新魏","123","webgl exception","re","WMPlayer.OCX","72px","AppWorkspace","Highlight","document","Yandex Media Plugin","ESN Launch Mozilla Plugin","70px 'Arial'","injectJs","Loma","BitCometAgent","Calibri","Bookman Old Style","sessionStorage","Utopia","compileShader","escape","Scrollbar","Window","隶书","Kaspersky Password Manager","MingLiU-ExtB","get system colors exception","Skype.Detection","FileLab plugin","npAPI Plugin","not_exist_host","2d","ActiveXObject","Dotum","PDF-XChange Viewer","PMingLiU","colorDepth","Nokia Suite Enabler Plugin","RealVideo.RealVideo(tm) ActiveX Control (32-bit)","Magneto","AdobeExManCCDetect","_9755xjdesxxd_","Gabriola","Playbill","navigator","Rachana","Tw Cen MT Condensed Extra Bold","QQMiniDL Plugin","#f60","fillRect"]
var l = ["","GrayText","parent","幼圆","plugins","AdobeExManDetect","0010","Google Earth Plugin","Veetle TV Core","0007","0004","0002","0003","0000","0001","Unity Player","Skype Web Plugin","WebKit-integrierte PDF","gdxidpyhxdE","Bell MT","0008","getSupportedExtensions","setTime","0009","SafeSearch","\"","$","Univers","%","&","'","1110","get plugin string exception","ThreeDShadow","+",",","-","Arab","苹果丽细宋",".","FUZEShare","/","0","1","2","3","4","仿宋_GB2312"]
var s = ["=null; path=/; domain=", "Default Browser Helper", "French Script MT", "标楷体", "encodeURI", "Umpush", "icp", "华文琥珀", "createProgram", "monospace", "ButtonShadow", "Bodoni MT", "STATIC_DRAW", "黑体", "downloadUpdater", "Aliedit Plug-In", "PDF integrado do WebKit", "uniformOffset", "encodeURIComponent", "Picasa", "Adobe Fangsong Std", "bindBuffer", "AVG SiteSafety plugin", "Orbit Downloader", "color", "hidden", "localStorage", "Google Talk Effects Plugin", "indexedDB", "Lucida Fax", "AmazonMP3DownloaderPlugin", "createBuffer", "Castellar", "linkProgram", "Californian FB", "ThreeDHighlight", "createShader", "Gulim", "NyxLauncher", "YouTube Plug-in", "楷体_GB2312", "SWCtl.SWCtl", "Google Earth Plug-in", "QQDownload Plugin", "Norton Identity Safe", "parseInt", "Simple Pass", "Colonna MT", "zako", "getUniformLocation", "shaderSource", "Downloaders plugin", "location", "Heroes & Generals live", "window", "Showcard Gothic", "微软正黑体", "华文行楷", "Ginger", "RockMelt Update", "WindowFrame", "enableVertexAttribArray", "KacstOne", "attribute vec2 attrVertex; varying vec2 varyinTexCoordinate; uniform vec2 uniformOffset; void main() { varyinTexCoordinate = attrVertex + uniformOffset; gl_Position = vec4(attrVertex, 0, 1); }", "Perpetua", "openDatabase", "canvas", "iGetterScriptablePlugin", "Informal Roman", "Nitro PDF Plug-In", "Msxml2.XMLHTTP", "华文黑体", "NPLastPass", "ThreeDFace", "LastPass", "::", "parseFloat", "华文隶书", "; ", "getAttribLocation", "{'name':", "Nyala", "not_exist_hostname", "\\'", "GFACE Plugin", "undefined", "新宋体", "\\.", "Matura MT Script Capitals", "Arial Black", "FangSong", "mwC nkbafjord phsgly exvt zqiu, ὠ tphst/:/uhbgtic.mo/levva", "Braggadocio", "Harmony Firefox Plugin", "Palace Script MT", "Native Client", "userAgent", "QuickTime.QuickTime", "experimental-webgl", "ARRAY_BUFFER", "苹果丽中黑", "Alipay Security Control 3", "Script MT Bold", ", 'browserProp':", "TDCCtl.TDCCtl", "self", "InfoBackground", "Pando Web Plugin", "Haettenschweiler", "span", "ActiveBorder", "ThreeDLightShadow", "0202", "0203", "0200", "0201", "WPI Detector 1.4", "; expires=", "ThreeDDarkShadow", "Exif Everywhere", "Battlelog Game Launcher", "Impact", "VLC Multimedia Plugin", "Adobe Hebrew", "BlueStacks Install Detector", "wwwmmmmmmmmmmlli", "history", "sans-serif", "14731255234d414cF91356d684E4E8F5F56c8f1bc", "Papyrus", "ButtonText", "0211", "AppUp", "Parom.TV player plugin", "DealPlyLive Update", "Lohit Gujarati", "FRAGMENT_SHADER", "Agency FB", "MacromediaFlashPaper.MacromediaFlashPaper", "###", "WordCaptureX", "getComputedStyle", "platform", "0105", "Arabic Typesetting", "0106", "0103", "华文中宋", "0104", "0101", "0102", "0100", "0107", "ButtonHighlight", "vertexAttribPointer", "0108", "textBaseline", "#069", "doubleTwist Web Plugin", "unescape", "Thunder DapCtrl NPAPI Plugin", "Batang", "DFKai-SB", "Snap ITC", "Date", "MinibarPlugin", "decodeURIComponent", "NPPlayerShell", "MS Reference Sans Serif", "Hiragino Sans GB", "serif", "getContext", "uniform2f", "MoolBoran"]

var Q = t[10]
, Z = t[10]
, ee = [l[42], l[43], l[44], l[45], l[46], u[0], u[1], u[3], u[5], u[6], u[50], u[52], u[54], u[56], u[58], u[59]]
, te = [t[9], t[371], t[377], t[515], t[442], t[310], t[488], t[337], t[455], t[536], t[304], t[454], t[489], t[457], t[408], t[34], t[448], t[357], t[527], t[395], t[432], t[287], t[360], t[504], t[484], t[486], t[469], t[327], t[533], t[405], t[291], t[420], t[467], t[23], t[363], t[496], t[319], t[347], t[540], t[384], t[413], t[434], t[168], t[436], t[300], t[494], t[462], t[330], t[501], t[325], t[475], t[349], t[352], t[393], t[373], t[522], t[518], t[452], t[416], t[28], t[401], t[513], t[313], t[439], t[464], t[431], t[41], t[410], t[542], t[499], t[456], t[306], t[314], t[250], t[339], t[491], t[374], t[389], t[516], t[379], t[409], t[531], t[422], t[292], t[490], t[480], t[329], t[471], t[294], t[426], t[506], t[361], t[362], t[444], t[397], t[528], t[497], t[289], t[331], t[463], t[437], t[406], t[438], t[184], t[348], t[311], t[385], t[541], t[27], t[459], t[498], t[364], t[514], t[391], t[440], t[315], t[453], t[510], t[31], t[417], t[396], t[344], t[523], t[375], t[328], t[492], t[350], t[476], t[474], t[326], t[445], t[483], t[290], t[424], t[335], t[412], t[530], t[394], t[509], t[356], t[359], t[508], t[472], t[298], t[308], t[451], t[133], t[534], t[407], t[47], t[303], t[466], t[381], t[512], t[382], t[368], t[487], t[342], t[334], t[318], t[419], t[22], t[521], t[449], t[312], t[443], t[383], t[519], t[478], t[346], t[503], t[323], t[372], t[526], t[336], t[402], t[277], t[435], t[414], t[430], t[460], t[333], t[124], t[502], t[366], t[495], t[468], t[16], t[539], t[390], t[301], t[354], t[507], t[358], t[296], t[341], t[392], t[529], t[355], t[322], t[423], t[288], t[411], t[376], t[324], t[473], t[482], t[26], t[340], t[485], t[316], t[353], t[511], t[380], t[367], t[403], t[45], t[404], t[465], t[317], t[450], t[307], t[532], t[299], t[525], t[370], t[399], t[338], t[345], t[477], t[321], t[505], t[441], t[309], t[517], t[386], t[18], t[418], t[447], t[524], t[387], t[538], t[351], t[305], t[493], t[365], t[11], t[470], t[332], t[458], t[500], t[151], t[433], t[226], t[427], t[415]]
, ne = [t[35], t[193], t[120], t[138], t[251], t[227], t[134], t[275], t[209], t[51], t[50], t[10], t[167], t[217], t[176], t[96], t[135], t[117], t[177], t[72], t[259], t[142], t[201], t[36], t[234], t[42], t[159], t[225], t[147], t[104], t[56], t[76], t[268], t[39], t[84], t[108], t[178], t[210], t[92], t[218], t[17], t[139], t[219], t[194], t[220], t[202], t[211], t[235], t[46], t[203], t[179], t[204], t[260], t[152], t[44], t[21], t[78], t[261], t[19], t[185], t[74], t[100], t[140], t[105], t[195], t[116], t[169], t[242], t[150], t[73], t[153], t[85], t[252], t[9], t[93], t[228], t[205], t[118], t[276], t[196], t[101], t[236], t[12], t[269], t[106], t[253], t[212], t[186], t[83], t[154], t[229], t[48], t[155], t[119], t[156], t[254], t[230], t[197], t[59], t[237], t[157], t[170], t[88], t[180], t[109], t[75], t[243], t[244], t[112], t[143], t[198], t[107], t[129], t[70], t[158], t[89], t[110], t[125], t[255], t[94], t[171], t[206], t[187], t[121], t[86], t[97], t[188], t[189], t[199], t[245], t[43], t[141], t[231], t[181], t[113], t[278], t[90], t[535], t[221], t[49], t[136], t[246], t[238], t[213], t[126], t[40], t[256], t[60], t[239], t[172], t[146], t[160], t[98], t[130], t[262], t[279], t[257], t[267], t[37], t[182], t[270], t[33], t[173], t[62], t[214], t[54], t[144], t[63], t[240], t[280], t[57], t[281], t[55], t[127], t[38], t[183], t[69], t[64], t[271], t[215], t[71], t[222], t[247], t[65], t[66], t[161], t[282], t[284], t[114], t[99], t[537], t[13], t[61], t[232], t[162], t[233], t[20], t[263], t[272], t[111], t[122], t[95], t[102], t[68], t[190], t[80], t[191], t[148], t[103], t[216], t[207], t[25], t[128], t[283], t[149], t[77], t[248], t[58], t[123], t[249], t[163], t[164], t[79], t[174], t[223], t[208], t[145], t[165], t[166], t[264], t[14], t[192], t[200], t[29], t[87], t[131], t[82], t[273], t[274], t[241], t[258], t[115], t[81], t[265], t[132], t[67], t[266], t[53], t[30], t[24], t[91], t[52], t[224], t[137], t[175], t[32]]
, ie = t[158]
, re = t[158]
, oe = t[17]
, ae = t[17]
, se = s[128]
, le = l[18]
, ue = e[114]
, fe = t[87]
, ce = e[27]
, je = ce.length
, de = t[428]
, he = t[520]
, pe = !1
, ye = !1

function a(e, n, i) {
var r, o = [l[44], l[46], l[42], u[50], u[43], u[22], u[63], u[32], u[91], u[27], u[46], u[44], u[86], u[59], u[39], u[68], u[60], u[5], u[82], u[31], u[28], u[33], u[1], u[56], u[21], u[67], u[42], u[88], u[30], l[41], u[15], u[52], u[90], u[6], u[41], u[16], u[66], l[43], u[17], u[36], u[93], u[23], u[34], u[54], u[69], u[58], u[71], u[24], u[94], l[45], u[3], u[76], u[85], u[61], u[14], u[79], u[38], l[34], u[26], u[29], u[13], u[0], u[72], u[70]], a = u[19], s = [];
if (i == t[535])
i = e[n],
r = t[9],
s.push(o[i >>> t[10] & t[147]]),
s.push(o[(i << t[17] & t[116]) + (r >>> t[17] & t[50])]),
s.push(a),
s.push(a);
else if (i == t[10])
i = e[n],
r = e[n + t[535]],
e = t[9],
s.push(o[i >>> t[10] & t[147]]),
s.push(o[(i << t[17] & t[116]) + (r >>> t[17] & t[50])]),
s.push(o[(r << t[10] & t[142]) + (e >>> t[24] & t[13])]),
s.push(a);
else {
if (i != t[13])
throw Error(u[64]);
i = e[n],
r = e[n + t[535]],
e = e[n + t[10]],
s.push(o[i >>> t[10] & t[147]]),
s.push(o[(i << t[17] & t[116]) + (r >>> t[17] & t[50])]),
s.push(o[(r << t[10] & t[142]) + (e >>> t[24] & t[13])]),
s.push(o[e & t[147]])
}
return s.join(l[0])
}

function i(e) {
if (null == e)
return null;
for (var n = [], i = t[9], r = e.length; i < r; i++) {
var o = e[i];
n[i] = ne[(o >>> t[17] & t[50]) * t[52] + (o & t[50])]
}
return n
}

function g(e, t) {
return b(e + t)
}

function c(e, n, i, r, o) {
if (null != e && e.length != t[9]) {
if (null == i)
throw Error(u[84]);
if (e.length < o)
throw Error(u[87]);
for (var a = t[9]; a < o; a++)
i[r + a] = e[n + a]
}
}

function v(e, t) {
return e = b(e),
t = b(t),
b(e ^ t)
}

function y(e, n) {
if (null == e || null == n || e.length != n.length)
return e;
for (var i = [], r = t[9], o = e.length; r < o; r++)
i[r] = v(e[r], n[r]);
return i
}

function r(e) {
var n = [];
if (null == e || void 0 == e || e.length == t[9])
return f(re);
if (e.length >= re) {
var n = t[9]
, i = [];
if (null != e && e.length != t[9]) {
if (e.length < re)
throw Error(u[87]);
for (var r = t[9]; r < re; r++)
i[r] = e[n + r]
}
return i
}
for (i = t[9]; i < re; i++)
n[i] = e[i % e.length];
return n
}

function p(e) {
var n = [];
return n.push(ee[e >>> t[17] & t[50]]),
n.push(ee[e & t[50]]),
n.join(l[0])
}

function j(e) {
var n = [];
return n[0] = e >>> t[68] & t[293],
n[1] = e >>> t[52] & t[293],
n[2] = e >>> t[32] & t[293],
n[3] = e & t[293],
n
}

function b(e) {
if (e < t[284])
return b(t[285] - (t[284] - e));
if (e >= t[284] && e <= t[276])
return e;
if (e > t[276])
return b(t[286] + e - t[276]);
throw Error(u[89])
}

function h(e) {
if (null == e || e.length == t[9])
return [];
e = new String(e);
for (var n = [], i = e.length / t[10], r = t[9], o = t[9]; o < i; o++) {
var a = parseInt(e.charAt(r++), t[52]) << t[17]
, s = parseInt(e.charAt(r++), t[52]);
n[o] = b(a + s)
}
return n
}

function d(e) {
if (null == e || void 0 == e)
return e;
e = encodeURIComponent(e);
for (var n = [], i = e.length, r = t[9]; r < i; r++)
if (e.charAt(r) == l[28]) {
if (!(r + t[10] < i))
throw Error(u[99]);
n.push(h(e.charAt(++r) + l[0] + e.charAt(++r))[0])
} else
n.push(e.charCodeAt(r));
return n
}

function o(e) {
var n = t[398];
if (null != e)
for (var i = t[9]; i < e.length; i++)
n = n >>> t[32] ^ te[(n ^ e[i]) & t[293]];
if (e = j(n ^ t[398]),
n = e.length,
null == e || n < t[9])
e = new String(l[0]);
else {
for (var i = [], r = t[9]; r < n; r++)
i.push(p(e[r]));
e = i.join(l[0])
}
return e
}

function x(i) {
var r = [u[88], u[135], u[86], u[61], u[112], u[118], s[6]]
, o = l[0];
if (null == i || void 0 == i)
return i;
if (("undefined" == typeof i ? "undefined" : typeof i) == [e[43], u[173], u[74]].join(l[0])) {
for (var o = o + u[95], a = t[9]; a < r.length; a++)
if (i.hasOwnProperty(r[a])) {
var f, c = l[30] + r[a] + e[14];
f = l[0] + i[r[a]],
f = null == f || void 0 == f ? f : f.replace(/'/g, s[83]).replace(/"/g, l[25]),
o += c + f + u[144]
}
return o.charAt(o.length - t[535]) == l[35] && (o = o.substring(t[9], o.length - t[535])),
o += u[96]
}
return null
}

function $(e) {
for (var n = [], i = t[9]; i < e; i++) {
var r = Math.random() * je
, r = Math.floor(r);
n.push(ce.charAt(r))
}
return n.join(l[0])
}

function get_fp() {
var e = true, n = {'v': 'v1.1'}, h = null;
n['h'] = host;
var p = new Date().getTime() + 900000,
_ = p + 1000 * 60 * 60 * 24 * 365 * 5;
n['u'] = $(3) + p + $(3);
// 由于返回结果简单,此处我直接拿的结果,未进行进一步解析,有兴趣可以进一步解析
var w = ["25662623634134", "38137900684561"] // ["18746497805452", "42111766674147"]
null != w && void 0 != w && w.length > t[9] ? n[u[135]] = w.join(l[35]) : (n[u[135]] = M(l[42], t[37]), n[u[112]] = l[43], e = !1)
var S = h = x(n)
, n = se;
if (null == n || void 0 == n)
throw Error(u[73]);
null != S && void 0 != S || (S = l[0]);
var E, w = S;
E = o(null == S ? [] : d(S));
var R = d(w + E)
, k = d(n);
null == R && (R = []),
E = [];
for (var C = t[9]; C < ae; C++) {
var O = Math.random() * t[295]
, O = Math.floor(O);
E[C] = b(O)
}
var X, k = r(k), k = y(k, r(E)), C = k = r(k);
if (null == R || void 0 == R || R.length == t[9])
X = f(ie);
else {
var L = R.length
, V = t[9]
, V = L % ie <= ie - oe ? ie - L % ie - oe : ie * t[10] - L % ie - oe
, O = [];
c(R, t[9], O, t[9], L);
for (var B = t[9]; B < V; B++)
O[L + B] = t[9];
c(j(L), t[9], O, L + V, oe),
X = O
}
if (L = X,
null == L || L.length % ie != t[9])
throw Error(u[83]);
X = [];
for (var Y = t[9], F = L.length / ie, U = t[9]; U < F; U++) {
X[U] = [];
for (var z = t[9]; z < ie; z++)
X[U][z] = L[Y++]
}
Y = [],
c(E, t[9], Y, t[9], ae);
for (var K = X.length, G = t[9]; G < K; G++) {
var J, Q, Z = X[G];
if (null == Z)
Q = null;
else {
for (var ee = b(t[92]), F = [], te = Z.length, ne = t[9]; ne < te; ne++)
F.push(v(Z[ne], ee));
Q = F
}
var re;
if (F = Q,
null == F)
re = null;
else {
for (var ce = b(t[91]), U = [], je = F.length, ve = t[9]; ve < je; ve++)
U.push(v(F[ve], ce--));
re = U
}
if (F = re,
null == F)
J = null;
else {
for (var ge = b(t[110]), U = [], _e = F.length, we = t[9]; we < _e; we++)
U.push(g(F[we], ge++));
J = U
}
var Te, Se = y(J, k);
if (F = Se,
U = C,
null == F)
Te = null;
else if (null == U)
Te = F;
else {
for (var z = [], Ee = U.length, Re = t[9], ke = F.length; Re < ke; Re++)
z[Re] = b(F[Re] + U[Re % Ee]);
Te = z
}
var Se = y(Te, C)
, Ce = i(Se)
, Ce = i(Ce);
c(Ce, t[9], Y, G * ie + ae, ie),
C = Ce
}
var Oe;
if (null == Y || void 0 == Y)
Oe = null;
else if (Y.length == t[9])
Oe = l[0];
else {
var Ie = t[13];
try {
for (var K = [], $e = t[9]; $e < Y.length; ) {
if (!($e + Ie <= Y.length)) {
K.push(a(Y, $e, Y.length - $e));
break
}
K.push(a(Y, $e, Ie)),
$e += Ie
}
Oe = K.join(l[0])
} catch (Xe) {
throw Error(u[64])
}
}
h = Oe
h = h + u[7] + p;
return h;
}


// console.log(get_fp())


module.exports = {
Get_fp: get_fp, // 获取fp参数,无需传参
}

这个W函数检测了许多有关window属性即浏览器指纹;这里面的一个fp是navigator和canvas等浏览器属性生成的(根据你浏览器版本不同生成的值也不同,可以写死,也可以多生成几个不同的随机切换),另一个h是网站host地址,这里使用时针对不同的网站要更换。

这里指纹的生成其实算比较核心的内容,一开始我以为指纹只影响get请求,实际上如果指纹有问题,还会影响最后的验证。

多说一些这里的扣得过程,根据执行过程中提示的错误,逐个去解决,比如某些变量值(window对象,属性之类的)未定义,那就去浏览器中调试看当前环境下其值什么的,将其替换,一般也不确定是不是定值,但是可以先去尝试。

验证

可以自己生成fpcb后,我们就可以发送获取验证码的请求了,以此来验证自己生成的fp是否可用。这里发送请求很简单,不详细讲了,如果生成的指纹可用,那么请求将会得到下面这样的返回结果:

1
__JSONP_vky5mlp_0({"data":{"bg":["https://necaptcha.nosdn.127.net/35167cc10b58441bb714e5b46e2a58fb.jpg","https://nos.netease.com/necaptcha/35167cc10b58441bb714e5b46e2a58fb.jpg"],"front":["https://necaptcha.nosdn.127.net/402fe7eb0c234117b6515f123213cef1.png","https://nos.netease.com/necaptcha/402fe7eb0c234117b6515f123213cef1.png"],"token":"8a5866b867134f8083c98daaad62bf62","type":2},"error":0,"msg":"ok"});

缺口计算

缺口计算在我的另一篇图像处理相关的文章中,利用像素值写传统算法和模板匹配都没有取得比较好的效果。所以最后使用深度学习目标检测的方法,最后初步获得了一个准确率在70%左右的模型。

模拟轨迹算法

模拟轨迹这部分主要参考这篇文章:

网易滑动验证码破解

这里贴一下我写的模拟方法:

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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
@staticmethod
def get_x_list_new(dis):
"""
拿到移动轨迹,模仿人的滑动行为,先匀加速后匀减速
匀变速运动基本公式:
①v=v0+at
②s=v0t+½at²
③v²-v0²=2as
:param dis: 需要移动的距离
:return: 存放每0.3秒移动的距离
"""
# 初速度
v = 50
# 单位时间为0.02s来统计轨迹,轨迹即0.02内的位移
t = 0.02
# 位移/轨迹列表,列表内的一个元素代表0.02s的位移
tracks = []
# 当前的位移
current = 0
# 到达mid值开始减速
mid = dis * 3 / 5

while current < dis:
if current < mid:
# 加速度越小,单位时间的位移越小,模拟的轨迹就越多越详细
a = 50
else:
a = -75
# 初速度
v0 = v
# 0.02秒时间内的位移
s = v0 * t + 0.5 * a * (t ** 2)
# 当前的位置
current += s
# 添加到轨迹列表
tracks.append(round(current))

# 速度已经达到v,该速度作为下次的初速度
v = v0 + a * t
tracks[-1] = dis
return tracks

@staticmethod
def get_y_list(num):
# 上下浮动值,设置几个比较小的备选值
# y_option = [0, 1, 2, 3, 4, 5, 6, 7,
# -7, -6, -5, -4, -3, -2, -1]
change_point = num // 5
y_list = []
# 先不考虑负值
for i in range(num):
if i <= change_point:
y_list.append(random.randint(0, 1))
elif change_point < i <= change_point*2:
y_list.append(random.randint(1, 2))
elif change_point*2 < i <= change_point*3:
y_list.append(random.randint(2, 3))
elif change_point*3 < i <= change_point*4:
y_list.append(random.randint(3, 4))
elif i > change_point*4:
y_list.append(random.randint(4, 5))
return y_list

@staticmethod
def get_time_list(num):
# 开始滑动的时间,设置几个随机值(单位毫米)
init_times = [87, 75, 91, 103, 116, 121, 137, 140, 154]
# 预计滑动需要的时间,设置几个随机值(单位毫秒)
# total_time = [1020, 1234, 1106, 988, 1356, 1407]
# 随机每步增长的时间大小
stride_time = [11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
init_time = random.choice(init_times)
time_list = [init_time]
for i in range(num - 1):
init_time += random.choice(stride_time)
time_list.append(init_time)
return time_list

def get_tracks(self, dis):
dis = round(dis)+10 # 据观察,实际缺口的位置与滑动距离相差10
x_list = self.get_x_list_new(dis)
y_list = self.get_y_list(len(x_list))
time_list = self.get_time_list(len(x_list))
traces = []
for x, y, t in zip(x_list, y_list, time_list):
traces.append([x, y, t])
return traces

实际上并不确定此轨迹生成方法是否可行(理论上再继续优化优化应该是可以的),因为后面易盾出现了watchman检测,因为我不咋想继续搞它了,所以没法完整验证,每次check请求都没有成功,所以就放着了,如果后面有继续对watchman破解,再来更新……

后续补充:后来又搞了一下watchman,经过测试,这里的轨迹算法可用,周围有大佬是利用深度学习训练了一个轨迹生成模型,后面有机会可以尝试下

补充:干扰块的排除

易盾在2.14.1版本中对滑动验证码进行了一个小升级,就是背景图会有两个滑块,类似这样:

也就是增加了一个干扰块,恰巧可以利用小滑块来解决此问题,因为我们可以获取到小滑块的原始图片,小滑块是一个背景透明的png图片

这里我故意采用截图的方式来展示,因为直接看原图很难直接意识到滑块实际的长和宽,因为背景是透明的;使用PIL打开时,模式为RGBA模式,获取像素值返回四个,前三个是RGB值,最后一个是透明度值(0~255),0表示完全透明,255表明完全不透明。易盾这里背景部分的透明度值为0,其他地方的透明度值为255。

所以这里可以利用透明度值获取滑块左上角的坐标,从而排除不在同一水平线的干扰块。

1
2
3
4
5
6
7
8
9
10
def get_top(response_content):
image = Image.open(BytesIO(response_content))
width, height = image.size
# 逐列扫描,找到第一列透明度不为0的最上面的行
for col in range(width):
for row in range(height-40):
_, _, _, a = image.getpixel((col, row))
if a:
print(row, col)
return row, col

这里根据经验,一般都在第二列,所以这里或许可以直接从上到下扫描第二列。