某度数字点选验证码逆向分析

本文章中所有内容仅供学习交流使用,不用于其他任何目的,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关!若有侵权,请添加(wx:ShawYbo)联系删除

目标网站

网站

aHR0cHM6Ly90aWViYS5iYWlkdS5jb20vZj9pZT11dGYtOCZrdz0lRTYlOTglQkUlRTUlOEQlQTEmcG49MzE=

目标:验证码图片初始化响应及图片正确顺序处理、轨迹参数构造。

分析过程

初始化请求:获取验证码会话信息

  1. 图片数据请求:获取加密的验证码图片数据

  2. 数据解密:解密图片下载地址和拼接规则

  3. 图片重构:下载并重新拼接验证码图片

  4. 数字识别:识别图片中的数字及坐标

  5. 轨迹生成:生成符合人类行为的点击轨迹

  6. 数据加密:构建并加密提交参数

  7. 结果提交:提交验证结果

前两步没什么好说的,参数都是死的,直接照搬就行。查看devtools我们可以看到,请求回来的验证码是乱序的,正确的顺序在初始化请求中,需要先解密,然后重新拼接图片,最后进行识别:

QQ截图20250915103829.png

2655e4dbd8784149b40b242c6801160b.jpeg

通过XHR断点可以找到,初始化验证码图片请求是BiocCaptcha.js发出来的,粗略看一下这个js可知这是vmp,混淆强度不大且结构清晰:

  • M[2]: 栈操作指令

  • M[3-4]: 变量赋值和取值指令

  • M[5-8]: 常量加载指令

  • M[29-41]: 算术运算指令

  • M[47]: 方法调用指令(核心)

  • M[51-53]: 控制流指令

M[47]就是这个vmp指令执行的核心了,给这里插桩,分析日志。


M[47] = function(t, n) {
    for (var r = n.X, i = r[t[1]].get(), o = i[r[t[2]].get()], c = [], a = t[3]; a < t[4]; a++) {
        var s = r[a].get();
        c.push(s)
    }
n.V = new e(o.apply(i, c))
}

首先解密/webapi/verint/img请求响应中的enc_data,该响应包含了验证码图片的正确拼接顺序和请求地址。通过插桩日志可以看出,先构建一个字符串,具体规则为:r+ak+bid+'{bioc_slat}',r和bid的值同为当前响应,ak为固定值(同个网站相同),然后使用sha1对该字符串加密,再截取前16位作为后续解密的key。具体的解密算法为aes-cbc,key我们已经获取到了,iv是固定值16fe0555d0c6d15d

QQ截图20250915143004.png

最终的解密结果示例:


接下来就是按照config["pm"]中的规则还原底图。数组第一位config["pm"][0]表示切割方块的长宽(150,50),由于原图是300*200,所以整好被分为了8快,接下来config["pm"][1]到config["pm"][8]代表每一块原本的位置。

我们以底图左上角为坐标起点,按照config["pm"][0]划分坐标系。比如config["pm"][2]就是第二块图,他的值为0_50_150_0,由于只看左上角的坐标,所以去前两个点位0_50,那么他对应的实际位置即为3(当前为2)。

{
  "master":"https://bioc-captcha.cdn.bcebos.com",
  "standby":"https://bioc-captcha-su-standby.cdn.bcebos.com",
  "imgUrl":"cimages/20231017/2655e4dbd8784149b40b242c6801160b.jpeg",
  "config":{
    "pm":[
      "150_50",
      "150_0_0_0",
      "0_50_150_0",
      "0_150_0_50",
      "150_100_150_50",
      "0_0_0_100",
      "0_100_150_100",
      "150_150_0_150",
      "150_50_150_150"
    ],
    "clickCount":1,
    "question":{
      "type":"string",
      "value":"请点击最小的数值"
    }
  }
}

wechat_2025-09-15_152239_954.png

wechat_2025-09-15_150430_258.png

还原好底图后,就可以获取点击坐标了,我这里是使用的某打码平台,后续会自己训个模型。

接下来就是构造轨迹和加密payload了,轨迹直接用贝塞尔,几个点位一连接就行。

payload中有lil、la、rl、bfi等,这几个值是先前js文件的加载时间戳与BiocCaptcha.js初始化时间错的差值,hook一下date.now即可得知,这里不赘述了。

在正真加密之前,先对payload进行base64编码,通过日志可以看出他对编码的字符集随机调换了位置。

wechat_2025-09-15_154156_423.png

完成编码后,payload进行aes-cbc加密,具体流程可见下图,key的获取和解密enc_data时一样,其中af8b9d6a68de383f7141a92faff7730bdd38047b为固定值(初始化的时候已加载),截取sha1前16位作为key,iv为固定值。

图片

PS: 这个vmp样本还是比较简单的,直接找到call、apply插桩即可,该样本既没有高强度混淆,也没有devtools检测,也没有代码展开检测,插完桩分析日志即可。

结果验证

图片


可添加宫中号:冰敷逆向笔记
一起交流学习。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值