本文章只做技术探讨, 请勿用于非法用途。
目标网站
继续来说易盾, 这次来聊验证接口。配合上期的获取图片接口, 可以实现无感过易盾验证码。
接口分析
还是先来看接口, 可以通过多次尝试滑动来观察不同的情况。
Json
// 目标接口
https://c.dun.163.com/api/v3/check
// 核心参数
{
"id": "07e2387ab53a4d6f930b8d9a9be71bdf", // 绑定浏览器, 定值
"token": "7bbb4243ed7e4c2a9071ea549e2ffce9", // 获取验证码图片时一并返回
"data": {"d":"Mu5sTZnRyggS6kmLW2mk94Y6KppHjjCHlqZFidiesQ.+Upkz9OZUAWjRnJBXGCgDWDiFC20MRnuryh5.YTbBXCWssqOythtza1IjxnTdzSIsLDkXOeIh+LOiBZu9+MOaSchEicLO8mZWdgVqxRgqoqbR0kvFpY.CjsWDA/9pz+9uyeHgof30DRDGUqi.WxihlSTu5QxjDpS9/2OnSIKGX0dQDO16DIg06gbZMp9uvQ6kCkHwjythhNYyGesLJXGXeyeUX+yRa6sJ2jdAL+1LDYj4L+Ou6UxrJpAzJA09DIG8Gk96+O/KxkVz0puBzlrczdAc4NGrx2s4/.Qutp9pIcNZ5WLKJEJuESnZ9JNvj4jhzoNAQZabPkZWwFhtbcltMCQa0.qP6LXcx+KcDqf8XJXwAtH06NUMuMRSjUalwsBWOZHdcx0Twcy1h0hCif/8X8JpbW+Bzzyk4hlKyrJKjGpfKqaATT2ivF3nXXroqQtSm9LHNwzsRPtbS+wqB2oRv++m06a0A6fiahyq5NNvk.PPL8Y0o5IyU4an.WpNAsvd84dcL34OSapB8mSqUNwmrklRFVyDym/5gNgvLBJupZLTR5wBFe/u4K/BJIvdTK5lzGdRcsdMcaJjh62ZFnkHKMzeboeHm5iQjyJFEiI5E0boTapR4mXAE99nvOLagZXRrUgclduwUlbJ/oHbl1+gOY3M+9na/WQcgj.32pyOKeVaLXvdMj.CKcIFCbQTHlsLHjCZhaRawDEV4NaZTdEk0mnLam5y5OWn5ovXL2SvkXrhi5LSgS4.F5fc40F5c3aU22xHnIEPkidUqTiiI2gZ8PUDlmaVVZrxEmEumZI3IVQ8mwPa2MK+gjAfiJN4yvfVQRV24Qh0JVpnvkYemMHEWKnRw6I1okRcqdKcaZeZ4KTYjrtajEOpXtegM1cazv.hHYgZMFJOfxGcLEX34VdRCsUH8+jJQ.REF8FFygqy2raffQEYVOeClvdsZ041c4GFyjaBRNb6tPNlDwXiTIsTYGysiQ2ehE3yycWR4gtPFRHuXC1HyGzeJ6FUbFk/sAa/Dr9atNZ4rQAzgPbQhrU08DuUnJZhHoxu5.Lvg/FxE5ijhPjlHthGVL3oRth50NqvGTsi4nsKtmgdAJYPxAliPF3FIlCuZ6PxO/hT9rmGzt8YS5wR9npKqao3is+XXa6XpWKs","m":"","p":"NEsSFPLKeiEXrLWYGTkOptXmK9CyI6zUMvR6zz+wGsKvnq264nb4baMzjtgNeAuiaqIQ.B1IX6lyDpLuZeeJeVAnZ/f7","f":"nKJyVUdFfjYzHB/sVtUFHPzQTxfM+9lGmUbabsSwRQphN+ENG/krDnNWg1eIc15spqSa2V2sLI6AmbVXiNfSNuf+wuXU3G1WKBrStCCoYJsKBvzQHoFfXRgY5gdN56aVYLJ68JAedkTae/8L5+oElwlFThCb4g.zsJdKoPbyzuSbL5ifo65alWLTkcBMloa+VXG9.ipc2O.RZHJvg8k6MOhCPGCpMpvbgpEbR61qu195zqy.bnwfqdG141YPFBgdy4JnTr8f5Ky4CXxLfPa2gGu0pm5SWZ06Cd6q4Lz0qGKsT+teyHscIsQBwCPeQPE0JKDa3f9Lr9dOgrAoKSDvvYMj4uOwn2x3ja/2bJVrb59eTTexRyXxL0d2D3JzeQ8HoEnrs.6vP5dJXhqqaNj+l.3aIN.mqvuB9GJpTxB2e29CyNZDAclCK4JuDpseQPmP4amh0E5Ujw0MEDLwrkl6D4urSJjQymtA/E3sh0kxIA19RZRzAAFUIrRPvtXYPDl4j8ZsQX77","ext":".ggcbmz4wXbCi8yOeGA.AX4IwfM5X/ri2OhsHL.qYgkgdDM+P+rxl8fbaUISkcTXpbvYtD580GZQzWA2XCdebcMdbEs7"}, // 滑动轨迹信息, 需逆向参数
"cb": "D3B6.KV5scsTxCUi8zuLDb6LuonP3gDhvuetYX%2BF9yR6tCbxWngKY4GV%2F89pVnvjO0ksKRMPGtDnJOIumJirnlNFT%2FE7", // 浏览器指纹, 上期有讲
}
// 响应 A, 参数校验失败
{
"error": 100,
"msg":"param check error"
}
// 响应 B, 轨迹校验失败
{
"data": {
"result": false,
"zoneId": "CN31",
"token": "4e5d5080835643bd9e0335d8264cea63",
"validate": ""
},
"error": 0,
"msg": "ok"
}
// 响应 C, 校验成功
{
"data": {
"result": true,
"zoneId": "CN31",
"token": "a5168f8f8edf432b890886968a363f24",
"validate": "8gxMgwjCs36ABQyKiWXApPYj4qmeePZtNacdk+33/pWyyVk9xmp6Fe6etQ75HC/G/p4SqUksSPlt8+SstaDC3Eve43eTujSRtRjRkjwxQHqabY3Yt/dLHI1eYxltI8ofBf09ykmqlvr5T34qcjkDRQdIVobyM0ejR6jtvIPPQ8U="
},
"error": 0,
"msg": "ok"
}
本文重点在于逆向部分, 能拿到响应 B 或是响应 C 即认为成功, 轨迹校验可以自己设计算法或是训练大模型来处理。
由上信息可知, data 就是我们需要逆向分析的参数。
加密分析
还是老方法, 先尝试全局搜索参数。因为 data 字段在响应中会出现, 导致会干扰搜索结果, 这里尝试搜索了 data 中的字段 ext , 将所有出现的位置都打上断点。
搜索结果示例
断点位置示例
变量值示例
分析断点处代码, 会发现这是一个 mouseUp 的监听事件, 也就是说在我们鼠标抬起时出触发的事件。他通过对 this["traceDta"]、this["atomTraceData"]、token 等变量处理来得到最终的 data 值, 通过查看我们基本可以确定这两个数组就是我们的轨迹内容, 接下来就是确定如何生成两个数组。
按照正常的思路, 我们应该继续往上找堆栈, 来查看 this 的指向。但是继续下去会发现上层的 this 指向是 document 对象, 和这里的 this 是不同的, 也就是说在事件函数中, 有哪里统一改变了 this 的指向问题。 只能改变方法, 尝试搜索 atomTraceData 和 a0_0x1e60(0x2d5)(atomTraceData 的加密值) 两个变量, 看看能不能找到他们生成的位置。
atomTraceData 定位示例
最终我们可以追到图中所示的地方, 可以看到这里是一个 mouseMove 事件, 监听鼠标的移动。这里向 atomTraceData 中 push 了一个数组 _0x1d0d76, 根据代码分析可以知道 _0x1d0d76 的内容为 [x轴偏移量, y轴偏移量, 耗费时间(毫秒), isTrust参数(恒定为 1)]。
traceData 加密示例
traceData 加密函数
继续分析, 可以知道, traceData 的值是通过 atmosTraceData 中的数组以及 token 值经过 _0x564a9f 函数加密得到。到此, 我们基本可以确定接下来的处理思路了。
- 自己设计算法生成 atmosTraceData 轨迹数组。
- 根据 atmosTraceData 调用加密函数生成对应的 traceData。
- 调用 mouseUp 函数, 传入两个数组, 获得最终的 data 值。
在开始之前, 还要做一些准备工作, 就是要把加密函数 _0x564a9f 以及 mouseUp 函数给抠出来到我们本地用。
加密函数全局化
加密函数测试
函数逻辑还是在 webpack 中, 位于第 8 个参数函数内, 跟之前的做法一样, 首先将其全局化, 拿到加密结果就算成功。
mouseUp 位置示例
mouseUp 处理
mouseUp 函数在第 36 个参数函数中的一个临时变量中, 无法直接获取, 所以我选择把他先赋值给一个变量, 然后再把变量全局化。
函数处理示例
该函数之前通过调用 this 中的值来计算, 现在我们改为传入数组参数, 所以要对代码做一些改动, 同时删掉一些和加密无关的兼容代码。
加密结果示例
开整
本地化
本地化代码示例
结合上期内容, 按照分析中的内容改动, 然后抽出来三个函数。
补环境
目前来看, 不需要额外的环境, 上期的环境可以通用。
请求
Python + subprocess
Python 代码示例
调用结果示例
补充点
- 说一下验证码识别的问题, 可以用打码平台, 可以训练大模型, 不想费事的话用 ddddocr 这个库也可以的(对这个验证码来说准确度很高), 还有一点就是, 滑块的初始位置就有 10px, 计算的时候记得加上。
- 滑动轨迹, 模拟的时候可以在 push 那个位置加上一个日志断点, 看看正常浏览器采集的数据是怎么样的作为参考。
- 有大佬愿意的话, 可以分享一下自己的轨迹算法。
总结
啰哩啰嗦的, 总算是把这个说完了。
网站不能说复杂, 但是要关注的点确实很多, 如果不是跟着做的话, 可能会不知道再说什么。 比起来应该是没抖音、小红书那两期说的清楚, 不过确实没办法。
有问题的话私信我吧。
请洒潘江,各倾陆海云尔。