一、網站http://www.gsxt.gov.cn滑動驗證碼概述
二、極驗驗證碼破解-抓包分析
三、極驗驗證碼破解-搭建本地驗證碼服務
四、極驗驗證碼破解-分析geetest.js,得到所需參數
五、極驗驗證碼破解-Track的擷取
六、極驗驗證碼破解-擷取背景圖檔及缺口距離d的計算
七、極驗驗證碼破解-總結
參考文獻
運作截圖
四、極驗驗證碼破解-分析geetest.js,得到所需參數
- 為了找出如何生成userresponse和a,我們在geetest.js中搜尋userrespnse,發現隻有一處提到userresponse,如下所示:
可以看出userresponse和a都在上述代碼中指派。
首先,我們追蹤ca.ra,得到下面代碼:
計算userresponse需要參數l和challenge,challenge我們已知,下面分析l(先猜測為滑塊移動的距離)。
由
可得到a由n生成,
由上述可知oa.qa的傳回值是f,下面繼續追蹤f:
由上述可知(console為我添加,目的是列印資訊),f的傳回值即為所求a,觀察其包含!!資訊,比較所需a值:
可以發現,目前推測無誤。
2. 我們發現f依賴于oa下的c函數,追蹤c函數:
觀察c函數的參數a,由a[h+1][1]可知a應該是一個二維數組。
添加如下資訊,輸出a的内容:
重新整理http://localhost:8000/,檢視console控件下的資訊:
可以發現,這很大可能就是我們所要找的滑動軌迹Track。
回到之前userresponse中的l參數,我們在相應位置輸出:
檢視Console發現:
之前我們猜測l為滑動距離,比較l與Track最後一個坐标,可以發現l與Track[-1][0]相等,是以驗證我們猜想—l是滑動距離。
3. 要想得到userresponse,需要得到l,需要得到Track,由于Track是随機采樣生成的離散軌迹坐标序列,是以我們需要根據缺口的位置來模拟Track。由于Track較難模拟,我們先假設已根據缺口距離生成了Track。
則可以寫出生成userresponse的函數:
def cal_userresponse(a,b):
d=[]
c=b[:]
for e in range(len(c)):
f=ord(str(c[e]))
tmp=f- if f> else f-
d.append(tmp)
c=*d[]+d[]
g=int(round(a))+c
b=b[:]
i=[[],[],[],[],[]]
j={}
k=
e=
for e in range(len(b)):
h=b[e]
if h in j:
pass
else:
j[h]=
i[k].append(h)
k+=
k= if (k==) else k
n=g
o=
p=""
q=[,,,,]
while n>:
if n-q[o]>=:
m=int(random.random()*len(i[o]))
p+=str(i[o][m])
n-=q[o]
else:
del(i[o])
del(q[o])
o-=
return p
參數a和b分别是l和challenge。上述函數是我根據
改寫成Python形式
至此,userresponse參數破解成功,接下來看a的生成。
4. 之前分析a是由oa下的f函數生成:
其中參數a是Track。其中f函數用到了c函數、e函數和d函數。
根據js函數源碼,我将其改寫成python函數。
# 計算每次間隔 相當于c函數
def fun_c(a):
g=[]
e=[]
f=
for h in range(len(a)-):
b=int(round(a[h+][]-a[h][]))
c=int(round(a[h+][]-a[h][]))
d=int(round(a[h+][]-a[h][]))
g.append([b,c,d])
if b==c==d==:
pass
else:
if b==c==:
f+=d
else:
e.append([b,c,d+f])
f=
if f!=:
e.append([b,c,f])
return e
def fun_e(item): # 相當于e函數
b=[[, ], [, ], [, -], [, ], [, ], [, -], [, ], [, -], [, ]]
c='stuvwxyz~'
for i,t in enumerate(b):
if t==item[:]:
return c[i]
return
def fun_d(a):
b='()*,-./0123456789:[email protected]_abcdefghijklmnopqr'
c=len(b)
d=''
e=abs(a)
f=int(e/c)
if f>=c:
f=c-
if f>:
d=b[f]
e%=c
g=''
if a<:
g+='!'
if d:
g+='$'
return g+d+b[e]
def fun_f(track_list):
skip_list=fun_c(track_list)
g,h,i=[],[],[]
for j in range(len(skip_list)):
b=fun_e(skip_list[j])
if b:
h.append(b)
else:
g.append(fun_d(skip_list[j][]))
h.append(fun_d(skip_list[j][]))
i.append(fun_d(skip_list[j][]))
return ''.join(g)+'!!'+''.join(h)+'!!'+''.join(i)
代碼隻截取部分,具體細節後面會開源。
完整的f函數如上所示,參數為Track,傳回值即為f(也就是所需的a)。
至此,參數a也破解完成!!!隻差最會一步,Track如何得到。