timeslover 发表于 2022-6-26 21:46

网易易盾——推理拼图验证码参数逆向分析和调用

之前发过一篇文章,《对无序的验证码拼图还原》对拼图图像的还原,地址在[这里](https://www.52pojie.cn/thread-1583574-1-1.html)。今天的这篇文章主要是对验证提交参数进行逆向分析,成功演示结果在最底部。

### 目标网址
```js
aHR0cHM6Ly9kdW4uMTYzLmNvbS90cmlhbC9pbmZlcmVuY2U=
```
![在这里插入图片描述](https://img-blog.csdnimg.cn/43a7ea0625844abab819cef74f0af4b8.png)


### 抓包

提交分析,因为是用的jsonP发送,这里没办法用XHR断点,
```js
提交链接   https://c.dun.163.com/api/v3/check
```
拖动提交参数
```js
data = {
    referer:'https://dun.163.com/trial/inference',
    zoneId:'CN31',
    id:'07e2387ab53a4d6f930b8d9a9be71bdf',
    token:'9be1b7c8292f43439d10f2280abe0fbb',
    acToken:'undefined',
    data:'{"d":"","m":"2uGwkSzkkHWNvxTIpo4HjCWz\\H7N190ntn5i4jK1IP6Ls//e1d1i\\zxU5WMwMlzXQDPdnRFrQLHeov0ENzwXK/b+4o4rv0fF488wACUwfJ7zcVgyBVTM\\I2csuLKwSyeSPyJ\\+sLKhSnR+t/6zWskh2z9f7cYje21rw9IGh5mGMNZMu99hV7sYRPMPr\\S/BELzqtTVbu4TkutjGD5kqV9S2kE/b/T+j86RlcPrh/LkYhChIOt9JajayqVEyhalWROS/EfQdm9O6LI5FuMlWmCS9z9KnR1eA0XS5\\VU/6paz+gauRshkrZDnwfTC/cKuocGT4yqxi/Ar9s7SvJ1VJU\\KLrKs8gC+QfmiuUOzxvcWcH99+1j0USVSK4CkrYJm7A9YbC8lAJ\\zAeqKn0qH2PRU0dOBusTSKn8EVvxPSJuU0pudxrlMcgp33","p":"4jqSwRIFBE4WUzd9uS5\\XqmtsfS3","ext":"tFOr5AoqV5zZf61+zE8p2blNn4A/8Vkp"}',
    width:'320',
    type:'9',
    version:'2.19.1',
    cb:'5HuUbe4XK+D5Y7GrJCqQkGh9cFnj7NK1Hh1lGzd/hii2FbBMfNG/b1nFpy4Gx9ne',
    extraData:'',
    bf:0,
    runEnv:10,
    sdkVersion:undefined,
    callback:'__JSONP_mvnvfob_6'
}
```
以下几个参数是会变动的,所以我们主要是对这几个参数进行分析
```js
{
    token:'',
    data:'',
    cb:'',
    callback:''
}
```

我们先直接拖动验证一下,看下请求发送,会发送一个check请求,再查看一下请求堆栈调用,所有的调用都在文件core.v2.19.1.min.js里面,调用方法里面,发现有一个onDragEnd的调用,我们点进去看一下

![在这里插入图片描述](https://img-blog.csdnimg.cn/3e2370f426974553be48afb980bb770f.png)
![在这里插入图片描述](https://img-blog.csdnimg.cn/ad7b40828ee94440a8af5f26a3c53c68.png)


在此处下断点,然后拖动验证,拖动结束的时候,会在这里断下,查看一下参数,这里的data参数就是我们提交的data参数,这里做了一个JSON.stringify的操作

![在这里插入图片描述](https://img-blog.csdnimg.cn/8c877bc6d56c4e159077cc20ed0f9cc7.png)
![在这里插入图片描述](https://img-blog.csdnimg.cn/68b1ae30e1f143b394b89338a3ec3642.png)
不过这里有一个需要注意的点,下面这张图,你在这里断下之后,你每次取查看的时候他都是会变的,说明里面有一些随机数在变化,为了可以看到他真实固定的值,我们需要魔改一下代码,这里直接使用Fiddler抓包替换,然后二次编辑源码
![在这里插入图片描述](https://img-blog.csdnimg.cn/7a18a8a476b240dfafb0f2a1089cdda1.png)


将代码下载下来,然后设置替换
![在这里插入图片描述](https://img-blog.csdnimg.cn/74cfd005e3a44272afacaffc19d579af.png)


我们把上面的JSON.stringify独立出来,然后我们再提交验证一下最后的结果是不在这里
![在这里插入图片描述](https://img-blog.csdnimg.cn/6db0dd3c7fd443dab8f8a1598b605a74.png)


到了这里我们不需要做其他的,直接拖动验证,可以看到这个值和我们提交的是一致的,首先把data里面的参数一个一个解出来
![在这里插入图片描述](https://img-blog.csdnimg.cn/6407dd5c121045769f9bce1d8e27ffe5.png)


首先我们先分析一下m
```js
m: _0x4b1c93(_0x37bdc3['sample'](this, _0x3b034c)(':'))
```
```js
‘_0x487f4d(0xb64)’表示“join”
_0x3b034c是一个固定值50
this是一个字符串数组,简化为this['traceData']

根据上面的信息,简化之后就是
_0x4b1c93(_0x37bdc3['sample'](this['traceData'], 50).join(':'))
```
![在这里插入图片描述](https://img-blog.csdnimg.cn/b2ce8b30a83840a0bb288d0fd63f30b8.png)


我们先把this['traceData']这个数组的内容给找出来,直接搜索关键字this['traceData'],发现都在这这个作用域内部,这个线索算是断了,不过根据他的英文翻译,可以猜测它可能是我们需要的路径,只是已经做了加密处理

我们到源码看一眼上下文,会发现目前是在onDragEnd,拖拽结束的事件里面
![在这里插入图片描述](https://img-blog.csdnimg.cn/8616e988a2574f5899fe9483e7adfde2.png)
那么我们根据上面的发现,在onMouseMove里面看一下,我们分别在这两个位置下断点,可以看清他到底发生了什么,当我们把鼠标移到外面的时候,会在第一个位置断下,我们把第一个断点去掉,只留下if里面那个,然后就不会了

![在这里插入图片描述](https://img-blog.csdnimg.cn/b62cf572557942f4a5ee24ae31290335.png)


当我们按住方块拖动的时候,刚好他就断下来了,说明这里面就是路径跟踪的处理逻辑

![在这里插入图片描述](https://img-blog.csdnimg.cn/ff78e2baca124353aa69a92cd1ca56f9.png)


```js
var _0x4c7923 = this['state']
var _0x1eb7c7 = _0x5054ec(_0x4c7923, (_0x3c8f13), Math(_0x46347e), _0x37bdc3['now']() - this['drag']] + '')
this(_0x1eb7c7)
```
上面代码简化之后就是这个样子
```js
var _0x4c7923 = this.$store.state.token
var _0x1eb7c7 = _0x5054ec(_0x4c7923, ] + '')
this.traceData.push(_0x1eb7c7)
```

![在这里插入图片描述](https://img-blog.csdnimg.cn/0dd7aeb7978e41a0a68fc1e94d047b15.png)

_0x1eb7c7的值是一个经过处理字符串,最后一行的this.traceData.push(_0x1eb7c7),这个基本可以肯定,我们之前在onDragEnd里面遇到的那个数组就是通过这里产生的

知道上述信息之后,我们还要魔改一下源码,先定义一个全局变量win_traceData和win_traceDataStr

![在这里插入图片描述](https://img-blog.csdnimg.cn/e2cc795bafdb467094e6a27ecb981c32.png)


首先修改一下'onMouseMove': function(_0x7e6f33)里面的逻辑
![在这里插入图片描述](https://img-blog.csdnimg.cn/6d00c9ec0bab437397ed89aa924cf576.png)


然后呢,在'onDragEnd': function(_0x115c47)的时候输出一下结果,验证一下我们之前的推测

![在这里插入图片描述](https://img-blog.csdnimg.cn/b9275c056c5a48c7b3a1d8eb1564fd8e.png)

可以看到,这里的值是没有做二次处理,那这个函数就是
![在这里插入图片描述](https://img-blog.csdnimg.cn/3ecd44194d0b4a1a999b33709dc1a34c.png)

那么我们现在就是要找这个函数

![在这里插入图片描述](https://img-blog.csdnimg.cn/9e2f2c0cdc1946c4910671c4bef74a6f.png)


跳转到function _0x1767c8(_0x3261e8, _0x286191)这里面,到了这里,我们还要再修改一下源码,方便我们后面算法的调用,这里我们不去扣他的代码,不过觉得自己有能力的可以去扣一下,反正我去我去扣了之后发现,太难了

![在这里插入图片描述](https://img-blog.csdnimg.cn/b676b8c14b1845b296cd4ebb0ec0f80c.png)


### 路径加密函数
我们定义一个全局变量win_0x1767c8,然后把代码修改如下

![在这里插入图片描述](https://img-blog.csdnimg.cn/246a7fc9c7f14189b4ac34b20e783bcf.png)

![在这里插入图片描述](https://img-blog.csdnimg.cn/2231e54b6f044765aaa3ab4883e21348.png)


我们创建一个文件本地进行调用测试,先验证一个坐标的数据
```js
var _0x1eb7c7 = _0x5054ec(_0x4c7923, + '')
这一句代码也就可以变为
var _0x1eb7c7 = win_0x1767c8(_0x4c7923, + '')
```
然后将_0x4c7923,m1,m2和diftime写si一个数据,这里我们使用'onDragEnd': function(_0x115c47)打印的结果做验证,使用以下的测试数据测试
![在这里插入图片描述](https://img-blog.csdnimg.cn/cbef146c7f0f4525b223707eb05aef8b.png)

那么这个就可以确定这玩意就是这个的算法了,pathList是真实的路径,token需要自己获取,那么根据这个原理,我们可以把所有拖动路径都录制保存一遍,以后需要的时候可以直接拿来用,路径和时间差的使用,可以随机微调1-5个值让他更加随机,具体的看自己

到了这一步,我们解决了路径加密的计算规则,我们再回到'onDragEnd': function(_0x115c47)这里,继续搞这个m值
```js
m: _0x4b1c93(_0x37bdc3['sample'](this, _0x3b034c)(':'))
```
首先把这个sample函数导出来

![在这里插入图片描述](https://img-blog.csdnimg.cn/b7cee18e09024f9b92c14ddce7c6321f.png)


指向了这个位置,可以看到它是一个函数对象
![在这里插入图片描述](https://img-blog.csdnimg.cn/c17529ae00864bcda44bdbbcacd97af6.png)

全部都在_0x43823b对象里面
![在这里插入图片描述](https://img-blog.csdnimg.cn/d1389d4182dc4a8993b7d49d264fb49d.png)

然后他会导出到,_0x5a8f15['exports'],这里定义一个全局参数来接收一下
![在这里插入图片描述](https://img-blog.csdnimg.cn/55157d2b3ff34eddbf36261b9e16c80e.png)


修改之后就是这样,现在_0x37bdc3已经导出来了,然后我们还有再找一个函数_0x4b1c93
```js
m: _0x4b1c93(_0x37bdc3['sample'](this, _0x3b034c)(':'))
```
![在这里插入图片描述](https://img-blog.csdnimg.cn/424ba81c614b4ffd82384a69b129c73c.png)

_0x4b1c93,跳转到下面位置,这里我们也有去哪聚去接收他
![在这里插入图片描述](https://img-blog.csdnimg.cn/e5526508ff0e4f2aa6780574ef1bce7e.png)


![在这里插入图片描述](https://img-blog.csdnimg.cn/a4a65b6ddde4496b885b21b15bb0ca76.png)


### data的m值加密函数
修改之后就是这样

![在这里插入图片描述](https://img-blog.csdnimg.cn/d461cf310cb2406787fca4a9ee9e8009.png)

这里调用测试一下,每次调用的时候它的值都是变动的

![在这里插入图片描述](https://img-blog.csdnimg.cn/b48cb6d34fa24465898150f94bc7e48d.png)

这是因为,他每次经过的时候都会调用var _0x55cbbe = _0x4fffbf();
![在这里插入图片描述](https://img-blog.csdnimg.cn/e66f987007bd4e57bcc248b8be9dbff7.png)

然后_0x4fffbf()函数是下面这样的,所以同一个路径同一个token,每次计算出的结果都是不一样
![在这里插入图片描述](https://img-blog.csdnimg.cn/dce35f6033ef463ea65a5e323d204638.png)


### data的p值加密函数
```js
原函数是这样的
'p': _0x4b1c93(_0x5054ec(this, this['exchangePos']['join'](',')))

简化一下就是下面这样
win_0x4b1c93(win_0x1767c8(token, this['exchangePos']['join'](',')))
```
this['exchangePos']这个参数,需要特别说明一下,他是一个数组,里面有2个值,第一个值表示的意思是开始拖动滑块的下标索引值,第二个参数是被交换的滑块索引值,并且,顺序不能颠倒,比如我将0号滑块拖动到7号,那结果就是,不能是

写到这里,我之前写的[《对无序的验证码拼图还原》](https://juejin.cn/post/7060430919081361421),计算出最后的结果,就可以通过这种方式匹配出来,然后我们录制完所有的路径之后,去选择我们需要的路径方案进行计算就可以实现一条龙服务了。

将上面简化之后的结果进行测试

![在这里插入图片描述](https://img-blog.csdnimg.cn/cc4f7fe45f1f4a8b92ead07c17ce76f0.png)

### data的ext值加密函数
```js
// ext值原始函数
'ext': _0x4b1c93(_0x5054ec(this, this + ',' + this))

简化一下就是下面这样
win_0x4b1c93(win_0x1767c8(token, 1 + ',' + pathStr.length))
```
将上面简化之后的结果进行测试
![在这里插入图片描述](https://img-blog.csdnimg.cn/2ac112af28894b1e875cf94743f5899c.png)


### cb参数加密函数
在core.v2.19.1.min_copy.js文件下搜索referer关键字,然后下断点,可以看到这个cb跟最后发送请求的是一样的
![在这里插入图片描述](https://img-blog.csdnimg.cn/9b8618ef9179479fafeb4d52d27e07cb.png)

我们向上往回走一步

![在这里插入图片描述](https://img-blog.csdnimg.cn/6ea81ce482d6443bbee0e6f451bb7925.png)

跟进去,会进到function _0x285d22()这个函数,他会return返回_0xe25de6(_0x45082c)
![在这里插入图片描述](https://img-blog.csdnimg.cn/829c7e7c9978480a9dff93f76a059c71.png)

在这里插入图片描述

然后再跟进去看下return返回的_0xe25de6(_0x45082c),可以看到他调用了我们之前全局定义的的win_0x4b1c93
![在这里插入图片描述](https://img-blog.csdnimg.cn/d640b130f4f64e918decfac690d84734.png)


这里我们直接修改一下源码,将_0x285d22()也暴露出来

![在这里插入图片描述](https://img-blog.csdnimg.cn/f57c6ae2993845cfb79f7d40e92ec0fd.png)

这里的_0x2acb72['uuid'](0x20)要说明一下,进到这个函数里面,他会有一个随机数,所以他是随机的

![在这里插入图片描述](https://img-blog.csdnimg.cn/264d73943dfd4d42993a8587d4e72fce.png)

![在这里插入图片描述](https://img-blog.csdnimg.cn/00f544accf3c4ee3ae44168a6de1e661.png)

那么cb参数的调用就是
```js
win_0x285d22()
```

![在这里插入图片描述](https://img-blog.csdnimg.cn/2182a651d21e48b785931b5159d50e86.png)

### callback参数加密函数
最后还剩下一个callback参数

因为callback参数我们从调试开始到现在是一直没有遇到的,我们直接从发送请求的调用堆栈去找找,直接从最后往前找

![在这里插入图片描述](https://img-blog.csdnimg.cn/fd6ebc728ff043c3ab0a423e17804f37.png)

进到里面之后,我们先下断点,然后滑动完成,在这个位置断下来了,可以看到,会生成一个最后实际请求的要发送的callback参数

![在这里插入图片描述](https://img-blog.csdnimg.cn/06327489e07a46258a5618c10044d1fa.png)

将鼠标往后面拖动,会发现有一个__JSONP的字符,我们先复制下来

![在这里插入图片描述](https://img-blog.csdnimg.cn/9b761180f1744bfab2431d1984e8c3c4.png)

将逗号表达式改为正常赋值,然后替换到源码上,方便查看调试
```js
var _0x541624
var _0x21d7a8
var _0x12fd7e = Math()(0x24)(0x2, 0x9)
var _0x421a5c = _0x9795d6 || '__JSONP'
var _0x2582fe = _0x9795d6 || _0x421a5c + ('_' + _0x12fd7e) + ('_' + _0x12f742++)
var _0x46c3ff = _0x9795d6 || _0x3daaf1(0x643)
var _0x5babb5 = _0x9795d6 || 0x1770
var _0x5c6aa5 = window
var _0x4b24f9 = document['getElementsByTagName'](_0x3daaf1(0x58f)) || document
```
![在这里插入图片描述](https://img-blog.csdnimg.cn/605c21d23c1545e1b0e536b22d0586a8.png)

通过查看,在这一行生成了最后的callback参数

![在这里插入图片描述](https://img-blog.csdnimg.cn/ec0f86dcdf984d2ab9f999e7a5fe2cab.png)

```js
// 原始代码
var _0x12fd7e = Math()(0x24)(0x2, 0x9)
var _0x421a5c = _0x9795d6 || '__JSONP'
var _0x2582fe = _0x9795d6 || _0x421a5c + ('_' + _0x12fd7e) + ('_' + _0x12f742++)

简化后就是这样
var _0x12fd7e = Math.random().toString(0x24).slice(0x2, 0x9)
var _0x421a5c = _0x9795d6['prefix'] || '__JSONP'
// var _0x2582fe = _0x9795d6['name'] || _0x421a5c + ('_' + _0x12fd7e) + ('_' + _0x12f742++)
var _0x2582fe = _0x9795d6['name'] || _0x421a5c + ('_' + _0x12fd7e) + ('_' + 1)
```
参数_0x12f742是表示次数,你没发送一次只要没有成功,他就会叠加,所以这里我们直接写成固定值

直接调用测试

![在这里插入图片描述](https://img-blog.csdnimg.cn/7bbf173f3bbe486eb9a61b4e55977e22.png)

### 验证测试

到这里,我们所有需要的参数都找到了,下一步就是模拟调用进行验证,我已经录制好了所有出现的路径(一共是7+6+5+4+3+2+1 = 28条),当然你愿意的话也可以去录制7*7的路径条数,目前先手动填写需要交换的顺序,自动填写的话,需要参考我之前发的文章[《对无序的验证码拼图还原》](https://juejin.cn/post/7060430919081361421),将这个项目做成一个服务其调用,识别计算拼图结果。

进到调用堆栈,看他最后的请求

![在这里插入图片描述](https://img-blog.csdnimg.cn/03c3a684a09a438386f7128eef27c2ce.png)
![在这里插入图片描述](https://img-blog.csdnimg.cn/e2795245f2a84f47ad2a914df39442a6.png)

这段代码修复一下,下面是修复的代码,可以看到,他会创建一个javaScript标签,然后通过javaScript标签去请求
```js
    let _0x5f84aa = "https://c.dun.163.com/api/v3/check"
    _0x5f84aa += (~_0x5f84aa.indexOf('?') ? '&' : '?') + _0x31e743(senObj) + '&' + 'callback' + '=' + callback
    _0x5f84aa = _0x5f84aa['replace']('?&', '?')
    var _0x4b24f9 = document['getElementsByTagName']('script') || document['head'];
    _0x5f84aa['replace']('?&', '?')
    let _0x541624 = document.createElement('script')
    _0x541624['type'] = 'text/javascript'
    _0x541624['src'] = _0x5f84aa
    _0x4b24f9['parentNode']['insertBefore'](_0x541624, _0x4b24f9)
    _0x30c635;
```

这里需要注意一个,发送的get请求如果你只模拟这一段的话,最后会因为请求链接有空格,他会给你报链接检测错误的信息,
我们直接按照他的处理方式去处理
```js
_0x5f84aa += (~_0x5f84aa.indexOf('?') ? '&' : '?') + _0x31e743(senObj) + '&' + 'callback' + '=' + callback
```
_0x31e743(senObj)这个方法他会帮你处理好请求链接的空格问题。这里不再赘述,详细的可以去看具体细节。这里直接贴上完整模拟代码
```js
// 前端模拟提交,这里也可以使用py去提交,我是不想去折腾了,py提交的时候记得带上cookies
window = function (_0x203a88) {
    console.log('okokokok');
}
function _0x31e743(_0x295923) {
    var _0x50ff1e = []
    for (var _0x5b5df6 in _0x295923)
      _0x295923['hasOwnProperty'](_0x5b5df6) && _0x50ff1e['push'](encodeURIComponent(_0x5b5df6) + '=' + encodeURIComponent(_0x295923));
    return _0x50ff1e['join']('&');
}
function _0x30c635() {
    window()
}
let _0x5f84aa = "https://c.dun.163.com/api/v3/check"
_0x5f84aa += (~_0x5f84aa.indexOf('?') ? '&' : '?') + _0x31e743(senObj) + '&' + 'callback' + '=' + callback
_0x5f84aa = _0x5f84aa['replace']('?&', '?')
var _0x4b24f9 = document['getElementsByTagName']('script') || document['head'];
_0x5f84aa['replace']('?&', '?')
let _0x541624 = document.createElement('script')
_0x541624['type'] = 'text/javascript'
_0x541624['src'] = _0x5f84aa
_0x4b24f9['parentNode']['insertBefore'](_0x541624, _0x4b24f9)
_0x30c635;
```

### 完整代码
最后一步,将我们之前找出来的东西封装成函数来调用,代码如下
```js
function createUrl(obj) {
    // 已经录制好的路径字典
    let movPath = {
      '0,1': [
            {
                "_0x3c8f13": 1,
                "_0x46347e": 0,
                "diffTime": 77
            },
            {
                "_0x3c8f13": 2,
                "_0x46347e": 0,
                "diffTime": 99
            },
            {
                "_0x3c8f13": 3,
                "_0x46347e": 0,
                "diffTime": 113
            },
            {
                "_0x3c8f13": 5,
                "_0x46347e": 0,
                "diffTime": 120
            },
            {
                "_0x3c8f13": 7,
                "_0x46347e": 1,
                "diffTime": 129
            },
            {
                "_0x3c8f13": 10,
                "_0x46347e": 1,
                "diffTime": 137
            },
            {
                "_0x3c8f13": 14,
                "_0x46347e": 1,
                "diffTime": 145
            },
            {
                "_0x3c8f13": 20,
                "_0x46347e": 2,
                "diffTime": 152
            },
      .................此处省略,因为实在太长了,6000多行,具体的可以去看最后的项目地址,里面有完整代码
      ]
    }

    function randomNum(minNum, maxNum) {
      switch (arguments.length) {
            case 1:
                return parseInt(Math.random() * minNum + 1, 10);
                break;
            case 2:
                return parseInt(Math.random() * (maxNum - minNum + 1) + minNum, 10);
                break;
            default:
                return 0;
                break;
      }
    }
    let pathKey = obj.pos + ',' + obj.pos
    let pathList = movPath
    let pathStr = []
    for (let i = 0; i < pathList.length; i++) {
      const item = pathList
      // 调用路径加密函数
      // 这里对录制的路径做了随机处理
      let m1 = item._0x3c8f13+randomNum(1,3)
      let m2 = item._0x46347e+randomNum(1,3)
      let dTime = item.diffTime+randomNum(5,10)
      let str = win_0x1767c8(obj.token, + '')
      pathStr.push(str)
    }
    // m值
    let m = win_0x4b1c93(win_exports['sample'](pathStr, 50)['join'](':'))
    // p值
    let p = win_0x4b1c93(win_0x1767c8(obj.token, obj.pos['join'](',')))
    // ext值
    let ext = win_0x4b1c93(win_0x1767c8(obj.token, 1 + ',' + pathStr.length))
    let data = JSON.stringify({ d: "", m: m, p: p, ext: ext })
    console.log('data=', data);
    // referer
    let referer = location.href.replace(/\?[\s\S]*/, "").substring(0x0, 0x80)
    // cb值
    let cb = win_0x285d22()
    // callback值
    let _0x12fd7e = Math.random().toString(0x24).slice(0x2, 0x9)
    let _0x421a5c = '__JSONP'
    let callback = _0x421a5c + ('_' + _0x12fd7e) + ('_' + 1)

    let senObj = {
      referer: referer,
      zoneId: 'CN31',
      id: '07e2387ab53a4d6f930b8d9a9be71bdf',
      token: obj.token,
      acToken: undefined,
      data: data,
      width: '320',
      type: '9',
      version: '2.19.1',
      cb: cb,
      extraData: '',
      bf: 0,
      pos: obj.pos['join'](','),
      runEnv: 10,
      sdkVersion: undefined
    }

    // 模拟提交,这里可以使用py去提交,我这里是不想去折腾了,记得带上cookies
    window = function (_0x203a88) {
      console.log('okokokok');
    }
    function _0x31e743(_0x295923) {
      var _0x50ff1e = []
      for (var _0x5b5df6 in _0x295923)
            _0x295923['hasOwnProperty'](_0x5b5df6) && _0x50ff1e['push'](encodeURIComponent(_0x5b5df6) + '=' + encodeURIComponent(_0x295923));
      return _0x50ff1e['join']('&');
    }
    function _0x30c635() {
      window()
    }
    let _0x5f84aa = "https://c.dun.163.com/api/v3/check"
    _0x5f84aa += (~_0x5f84aa.indexOf('?') ? '&' : '?') + _0x31e743(senObj) + '&' + 'callback' + '=' + callback
    _0x5f84aa = _0x5f84aa['replace']('?&', '?')
    var _0x4b24f9 = document['getElementsByTagName']('script') || document['head'];
    _0x5f84aa['replace']('?&', '?')
    let _0x541624 = document.createElement('script')
    _0x541624['type'] = 'text/javascript'
    _0x541624['src'] = _0x5f84aa
    _0x4b24f9['parentNode']['insertBefore'](_0x541624, _0x4b24f9)
    _0x30c635;
}
```
调用测试示例:
此处不作py测试,不想折腾了,道理其实是一样的

### 测试方法
第一步:抓包替换文件。

第二步:找到token,这里我们直接手动找一个,在get中会返回一个token

![在这里插入图片描述](https://img-blog.csdnimg.cn/5770333466824a3f8715c98f988bd48f.png)

第三步,如下

![在这里插入图片描述](https://img-blog.csdnimg.cn/32edefa424054c7aa567d4cfc54889f4.png)

如果成功的话就会返回这样的一个很长的结果
![在这里插入图片描述](https://img-blog.csdnimg.cn/92655de6be2b493791ef8c4d26f2a3e0.png)

如果失败,就会像下面这样

![在这里插入图片描述](https://img-blog.csdnimg.cn/eddc70f4c59148699cde3ae8502f4d60.png)


### 项目代码地址
[项目地址在这里](https://gitcode.net/weixin_45307278/wyyd)
### 演示
![在这里插入图片描述](https://img-blog.csdnimg.cn/cd6dc0dbe5d04361bbb92eb358dd2ff8.gif)

470485700 发表于 2023-2-26 18:28

timeslover 发表于 2023-2-20 23:40
滑块拼图那个直接看他js就行了

版本不一样。小程序的版本我看验证请求时v2,官方那个抓到的验证是v3。不知道会不会存在版本不一致问题。前几天没时间继续搞,今天开始继续跟进。

470485700 发表于 2023-2-20 00:19

感谢分享。正在想办法搞网易易盾微信小程序的滑块拼图。小程序上这玩意儿是个插件。没能抓到他的JS代码。但是整体思路一样。只是版本号有区别,不知道能不能过。正在想办法尝试。

xkoga 发表于 2022-8-5 10:37

网易团队:感谢老哥为我们争取的加班!!!让我们挣的更多了!!

login 发表于 2022-7-7 23:48

公司安全部门要求加班替换服务商{:1_911:}

亡者之心x 发表于 2022-6-27 14:48

亡者之心x 发表于 2022-6-27 14:38
对这类了解不多, 大概看了下帖子
1. 逆向js,将处理好的js放在本地
2. 执行时将本地js替换成原版js,获取正 ...

续: 看了帖子中连接的无序验证码文章, 是通过一个拼图算法获取正确位置的,非js自带,谢谢分享

happyBread 发表于 2022-7-3 22:18

感谢分享

快乐小风 发表于 2022-6-27 11:56

厉害{:1_921:},能看懂js,到了分析的时候脑袋就一团麻了

hxiang 发表于 2022-6-27 12:54

这是什么软件?

tukuai88ya 发表于 2022-6-27 14:18

感谢分享

亡者之心x 发表于 2022-6-27 14:38

本帖最后由 亡者之心x 于 2022-6-27 14:40 编辑

对这类了解不多, 大概看了下帖子
1. 逆向js,将处理好的js放在本地
2. 执行时将本地js替换成原版js,获取正确位置参数

有个疑问是为什么验证码的js会储存位置信息呢,
正常验证码只显示图片,图片支持拖动,能记录图片位置即可
验证 拖动验证码的正确性应该是服务端去验证用户提交的位置
为什么演示中,直接本地就能解析出来

timeslover 发表于 2022-6-27 15:15

亡者之心x 发表于 2022-6-27 14:48
续: 看了帖子中连接的无序验证码文章, 是通过一个拼图算法获取正确位置的,非js自带,谢谢分享

是的,仅做本地演示,做成全自动的,可以参考之前的文章自己写接口服务调用

sdieedu 发表于 2022-6-27 16:07

js逆向,Mark一下

落神 发表于 2022-6-27 16:20

人麻了,看不下去。。

xq2581 发表于 2022-6-27 18:08


谢谢大佬分享!!! 新增验证吗越来越复杂了!
页: [1] 2 3 4 5 6 7 8
查看完整版本: 网易易盾——推理拼图验证码参数逆向分析和调用