网络爬虫-破解极验三代滑动验证码

什么是“极验”?

如果你是从事爬虫相关工作的,那么一定对这两个字不会陌生的。

极验是首家「行为式验证」安全技术服务提供商,并以提供验证码服务而闻名。我们日常会登录一些网站,有的网站登录前需要校验验证码,而这个验证码服务很可能就是极验提供的。


我们直接进入正题

在这里插入图片描述
如图所示 这个在登陆面前的拦路虎 便是大名鼎鼎的极验滑块验证码了

看到这里 有点基础的小伙伴 应该马上能想到用selenium来模拟人为拖动滑块来解决,这确实是一个不错的方法,在需求量较小的情况下,不失为一个优先的选择,但它的缺点也十分明显:
一是模拟滑动,容易被极验检测到我们使用的是自动化软件,从而导致滑动操作失败;
二是每一次登录任务都需要驱动浏览器,将会导致登录耗时较长。

所以今天我们讲的是另一个方式,硬刚JS,破解每个请求中的加密参数,之后在程序中发送请求得到正确响应,即POST逆向协议的方式来解决它


首先国际惯例第一步先抓包分析

在这里插入图片描述

请求参数 Form Data 有多个,包括:appId、loginName、loginPwd、geetest_challenge 等。可以看到,密码被加密成 CN-SA95… 这一长段,另外还有三个以 geetest_ 开头的加密参数,分别是:

•geetest_challenge: 102f7d723ad76e387ad6000f87ff91f8j3
•geetest_validate: 651ecdf62cb1e940e5ea999b6af7fc10
•geetest_seccode: 651ecdf62cb1e940e5ea999b6af7fc10|jordan

从参数命名上,我们能够很清晰地看出,这是极验滑动验证码的加密参数。也即是说,我们点击验证码,拖动滑块这些动作,最终转换为这三个加密参数。我们的主要工作,也在于破解这三个参数。细心的同学可能发现了,其中 geetest_validate 与 geetest_seccode 参数基本相同,只不过 geetest_seccode 多了 |jordan 的字符串后缀。那么,最主要的工作就是解出 challenge/validate 两个参数。

我们接着往上找,可以发现ajax.php这个请求

在这里插入图片描述
在这里插入图片描述

仔细剖析这个接口 不难发现params里面有 gt、challenge、lang、w 和 callback。其中 w 加密成了一长串,所以我们重点来看这个w参数。
我们找到slide.xxx.js 文件,跳转到 Chrome Sources 菜单栏,查看 JavaScript 代码

在这里插入图片描述
在这里插入图片描述

剖析出一些关键代码

function tPcX(e) {
    var SkB = uklgT.yaA()[0][22];
    for (; SkB !== uklgT.yaA()[16][19]; ) {
        switch (SkB) {
        case uklgT.yaA()[0][22]:
            var t = this;
            var r = e["DxJq"];
            SkB = uklgT.yaA()[0][21];
            break;
        case uklgT.yaA()[16][21]:
            r["height"] = r["width"] = 0;
            t["vjyG"] = r["getContext"]("2d");
            SkB = uklgT.yaA()[4][20];
            break;
        case uklgT.yaA()[4][20]:
            t["wOTb"] = t["xmDd"] = t["yZRm"] = t["AZ_O"] = 0;
            t["BnKG"] = r;
            SkB = uklgT.yaA()[4][19];
            break;
        }
    }
}

去除冗余代码后
function tPcX(e) {
    var t = this;
    var r = e["DxJq"];
    r["height"] = r["width"] = 0;
    t["vjyG"] = r["getContext"]("2d");
    t["wOTb"] = t["xmDd"] = t["yZRm"] = t["AZ_O"] = 0;
    t["BnKG"] = r;
}
通过对多个 JavaScript 文件,如 slide.js/fullpage.js 等进行反混淆、去冗余,我们对 JavaScript 的调用逻辑清晰了很多。
完成了代码反混淆,还有一个重要的工作,就是如何从 JavaScript 代码中抽离出关键的 JavaScript 代码,这些代码就是请求参数的加密逻辑。我将此过程称为“代码解绑定”。
这个过程并不需要什么技巧,需要的只是耐心,耐心,耐心。跟着 Chrome 浏览器,打断点分析请求的入口与出口,一步步将关键代码剥离出来。

在这里插入图片描述

比如,我们需要解出参数 a,那么就抽离出加密参数 a 的代码,封装成一个 get_a() 的函数。

在这里插入图片描述

封装了几个需要的 JavaScript 函数,我们可以在 Python 程序中,使用 PyExecJS 库,方便地执行 JavaScript 代码拿到加密参数。以下为一些示例代码:
import execjs


path1 = path + '/js-file/get_rp.js'
path2 = path + '/js-file/get_gj.js'


# RSA
def get_yf():
    ec = Encrypyed()
    key = ec.create_secret_key(8)
    enc_sec_key = ec.rsa_encrpt(key, ec.pub_key, ec.modulus)
    return enc_sec_key,key


def get_w1(gt,challenge):
    yf,key = get_yf()
    test  = '''{"gt":"%s","challenge":"%s","offline":false,"product":"bind","width":"300px","protocol":"http://","maze":"/static/js/maze.1.0.1.js","click":"/static/js/click.2.7.6.js","fullpage":"/static/js/fullpage.8.7.3.js","geetest":"/static/js/geetest.6.0.9_orgin.js","type":"fullpage","static_servers":["static.geetest.com/","dn-staticdown.qbox.me/"],"pencil":"/static/js/pencil.1.0.3.js","slide":"/static/js/slide.7.5.5.js","voice":"/static/js/voice.1.2.0.js","beeline":"/static/js/beeline.1.0.1.js","aspect_radio":{"click":128,"voice":128,"slide":103,"beeline":50,"pencil":128},"cc":12,"ww":true,"i":"3359!!17234!!CSS1Compat!!50!!-1!!-1!!-1!!-1!!3!!-1!!-1!!-1!!9!!9!!-1!!9!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!9!!-1!!4!!-1!!-1!!-35!!72!!0!!0!!901!!841!!1955!!958!!zh-CN!!zh-CN,zh!!-1!!1!!24!!Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36!!1!!1!!1920!!1080!!1920!!1030!!1!!1!!1!!-1!!Linux x86_64!!0!!-8!!2618e15e5d8c7f174cad42997c4436f2!!07f3564381d09b0994b7e73a99c6d7c7!!internal-pdf-viewer,mhjfbmdgcfjbbpaeojofohoefgiehjai,internal-nacl-plugin!!0!!-1!!0!!12!!Arial,Courier,CourierNew,Helvetica,Times,TimesNewRoman,Wingdings,Wingdings2,Wingdings3!!1559555859986!!-1,-1,1,0,0,0,0,1,57,3,3,3,4,368,368,407,693,693,693,-1!!-1!!-1!!60!!6!!-1!!-1!!14!!false!!false"}'''%(gt,challenge)
    ec = Encrypyed()
    iv = b"0000000000000000"
    enc_text = ec.aes_encrypt(test, key.decode('utf-8'), iv)
    array = []
    for byte in enc_text:
        array.append(byte)
    enc_text = ec.bytes_to_string(array)
    return enc_text+yf, key


def get_w2(gt,challenge,key,c,s):
    passtime = 1230
    _js = execjs.compile(open(path1, 'r').read())
    rp = _js.call('f3',gt,challenge,passtime)
    _js1 = execjs.compile(open(path2, 'r').read())
    tt = fun_u('M*d8PjAA3(-95e6D:)lN1NU91W-O/MEM92N*)O,n2_(/Xn(e5((,,-_N(,)(I-*5P4)(db9-5/)1g:AAdbE-NME)qqn(2DM()jFOJb5,)M9QEQ2,)(/*(M57(,(M((b',c,s)
    text = '''{"lang":"zh-cn","type":"fullpage","tt":"%s","light":"INPUT_0","s":"93e3d79ea85149d4e44244d3df6e16e5","h":"3deef994fc3cbf723df4c186cfe78a27","hh":"152caf38ccf01c64d90d2d0e8526c018","hi":"541c245c0365e2dcb84cef1b1366f775","ep":{"ts":1559840826770,"v":"8.7.3","ip":"192.168.124.11,218.98.33.165","f":"aea0f96bf3e494262bedf6ec7570f83b","de":false,"te":false,"me":true,"ven":"NVIDIA Corporation","ren":"GeForce GTX 1050 Ti/PCIe/SSE2","ac":[],"pu":false,"ph":false,"ni":false,"se":false,"fp":["move",302,315,1559840498541,"pointermove"],"lp":["up",234,339,1559840499124,"pointerup"],"em":{"ph":0,"cp":0,"ek":"11","wd":0,"nt":0,"si":0,"sc":0},"tm":{"a":1559840496633,"b":1559840496768,"c":1559840496768,"d":0,"e":0,"f":1559840496635,"g":1559840496635,"h":1559840496635,"i":1559840496635,"j":1559840496635,"k":0,"l":1559840496635,"m":1559840496735,"n":1559840496745,"o":1559840496773,"p":1559840496832,"q":1559840496832,"r":1559840496906,"s":1559840496930,"t":1559840496930,"u":1559840496930},"by":2},"captcha_token":"bboy","passtime":%s,"rp":"%s"}'''%(tt,passtime,rp)
    ec = Encrypyed()
    iv = b"0000000000000000"
    enc_text = ec.aes_encrypt(text, key.decode('utf-8'), iv)
    array = []
    for byte in enc_text:
        array.append(byte)
    enc_text = ec.bytes_to_string(array)
    return enc_text
以上便是整个极验滑动验证码破解的过程,再简单总结一下:

1.请求参数分析
2.代码反混淆
3.代码解绑定
4.滑动轨迹采集

其中,还包括验证码图片的还原,图片缺口的计算等等…


在这里插入图片描述

最终我们经过测试 可以发现这个vcalidate是可以通过登陆验证的关键token,至此破解结束。


Ending

Github传送门

持续更新ing (欢迎各种star与fork)

联系方式: 442891187(QQ)

如有权益问题可以发私信联系我删除

  • 3
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值