极验验证码

你可能曾经遇到过需要在网站登录时校验验证码的情况,这就是一种叫做“极验”的安全技术服务。极验是行为式验证安全技术服务的领先者,他们提供验证码服务,让用户在登录网站时需要输入验证码来确保安全性。如果你曾经在某些网站登录时需要校验验证码,那很有可能这个验证码就是由极验提供的。

PS:动手能力弱得朋友可以直奔www.ttocr.com进行使用。

例如某“XX”官网,它使用了极验验证码来保护用户账户的安全。一种常见的破解极验验证码的方法是计算缺口位置,使用Selenium自动化测试工具模拟人类手动拖动滑块的过程。虽然这种方法实现简单,但存在两个缺点:首先,模拟滑动容易被极验检测到自动化软件,导致滑动操作失败;其次,每次登录任务都需要驱动浏览器,登录耗时较长,不适合实时性要求较高的数据采集任务。

因此,一些人选择更艰难的方法,他们死磕JavaScript代码,破解每个请求中的加密参数,然后在程序中发送请求以获取正确响应。这种方法最直接且高效,无需等待浏览器对页面进行渲染,只要解出加密的请求参数,发送请求获取响应即可。需要注意的是,用户在浏览器中的操作最终都会转化为请求发送到服务端,服务端对请求参数进行合法性校验,并响应结果。

请求参数分析

我使用登录方法作为分析入口。我输入错误的账号密码,然后点击滑动验证码直到正确的位置。此后,页面会提示“账户名或密码错误!”。我查看浏览器的Network栏,发现登录动作实际上是发送了一个名为“accLoginPC.do”的请求。

该请求的URL为“https://xxx.xxx/webapi/accLoginPC.do”(已隐去敏感信息)。

该请求参数Form Data中包含多个参数,如“appId”、“loginName”、“loginPwd”、“geetest_challenge”等。可以看到,密码已被加密为一长串字符“CN-SA95...”,另外还有三个以“geetest_”开头的加密参数,分别为:

• “geetest_challenge: 102f7d723ad76e387ad6000f87ff91f8j3”

• “geetest_validate: 651ecdf62cb1e940e5ea999b6af7fc10”

• “geetest_seccode: 651ecdf62cb1e940e5ea999b6af7fc10|jordan”

从参数命名上,我们可以清楚地看到这是极验滑动验证码的加密参数。也就是说,我们的点击和拖动操作最终会转换为这三个加密参数。因此,我们的主要工作就是破解这三个参数。注意到,其中的“geetest_validate”和“geetest_seccode”参数基本相同,只是后者多了一个“|jordan”的字符串后缀。因此,我们的主要工作是解密“challenge”和“validate”两个参数。

对于其他非极验加密参数,如“loginPwd”、“jtSafeKey”、“token”等,这些都是XX官网自身的加密逻辑,破解难度不大。因此,在本文中,我们将重点关注极验参数的破解。

我们进一步查看,发现了一个名为“ajax.php?”的请求,其中响应信息类似于JSON格式,其中包含“validate”参数。惊讶的是,这不就是我们之前提到的“geetest_validate”参数吗?

仔细观察其请求参数,我们发现它包含“gt”、“challenge”、“lang”、“w”和“callback”等参数。其中,“w”被加密为一长串字符。

通过分析,我们逐渐理清了思路,确定了每个请求需要解密哪些参数。接下来,我们需要查看 JavaScript 代码中这些参数的加密方式,逐步解决这个问题。

然而,极验为了增加破解的难度,对代码进行了大量的混淆操作,使得代码几乎无法被理解。它采用了 Unicode 编码和大量混淆代码,这导致我们无法直接搜索关键参数名如“challenge”来找到相关代码。

因此,我们需要将完整的 JavaScript 代码复制出来,然后使用一个 Unicode 编码还原工具进行解码。解码后,我们可以将代码复制到编辑器中,搜索“challenge”参数,终于找到了几个关键的参数。

然而,这些代码仍然难以阅读,因为极验对每个关键参数都进行了混淆。它使用类似于“UtTS”这样的代码进行替换,具体的混淆逻辑藏在 JavaScript 代码中。我们需要进一步还原代码。

此外,我们还会发现一些看起来毫无意义的代码,例如“var xow_list = uklgT.xow”。经过研究,我们发现这实际上是极验加入的冗余代码,主要目的是为了混淆视听。

比如,对于这样的冗余代码:

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;

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值