前言
数美滑块算是入门级滑块了,主要有两个难点
- 代码混淆
- 动态更新
一、目标网址
atob(‘aHR0cHM6Ly93d3cuaXNodW1laS5jb20vdHJpYWwvY2FwdGNoYS5odG1s’)
二、抓包分析
1.获取接口
该接口用于获取验证码的图片和参数rid
。
可以看到这个接口中有organization
和captchaUuid
两个参数。其中organization为场景标识,不同网站这个值不同。captchaUuid是当前时间(年月日时分秒)+ 随机字符,可以写死。
2.验证接口
这个接口用于验证滑块,验证成功后,就可以带着获取接口返回的rid
进行下一步操作。
可以看到这个接口用到了获取接口返回的rid
,除此之外还有很多加密参数,这些参数名会动态更新,而我们只需要重点关注其中三个参数就行,因为其他参数的明文都是固定的,甚至有些网站直接不校验其他参数。在这个版本中,我们需要重点关注的三个参数名分别为uk
、gm
、zg
。其中最长的一个参数gm
是轨迹加密,也是我们逆向定位的关键参数。
三、逆向分析
话不多说,直接打开F12,搜索关键词 'gm'
可以看到这里会出现三个搜索结果,三个结果都是同一份JS代码中的,我们随便点击一行进入。
进入JS代码文件后,我们可以看到有三个大的case块,并且都包含了我们需要的参数gm
。这里我们在第二个case块的第一行uk
参数这一行打上断点。然后我们手动验证滑块,使断点断下。
这里this[_0x551ddd(0x511)]
是加密函数,传入了两个参数,第一个是明文,第二个是密钥,我们在控制台输出一下这三个重点参数的明文和密钥。根据输出我们可以看出
uk
明文为73(缺口坐标) / 300
的结果0.24333333333333335
密钥为c523b053
gm
明文为滑动轨迹
密钥为995190d6
zg
明文为1240(滑动时间)
密钥为92bb58f9
需要注意!我们获取到的背景图宽度为600,前端显示的图片宽度为300,轨迹生成是根据前端滑动距离生成的,所以我们通过背景图识别到坐标后先/2
。
接下来我们来看看这个加密函数,进入加密函数,断下断点。
可以看到这里是一个switch块,执行顺序为8|2|1|5|0|7|6|3|4
我们一行一行执行,执行到case 6
时发现这里是调用了一个DES
函数,直接套库。至此,我们的逆向部分就全部结束了。
四、代码实现
1.加密函数
import base64
from Cryptodome.Cipher import DES
def des_encrypt(content: str, key):
content = content.replace(' ', '').encode()
while len(content) % 8:
content += b'\0'
cipher = DES.new(key.encode('utf-8'), DES.MODE_ECB)
encrypted = cipher.encrypt(content)
return base64.b64encode(encrypted).decode('utf-8')
2.坐标识别
这里使用opencv的matchTemplate函数进行模板匹配,也可以使用目标检测进行训练。
import cv2
import numpy as np
def get_distance(slider: bytes, background: bytes):
"""
slider: 滑块图
background: 背景图
"""
target = cv2.imdecode(np.frombuffer(slider, dtype=np.uint8), 0)
template = cv2.imdecode(np.frombuffer(background, dtype=np.uint8), 0)
result = cv2.matchTemplate(target, template, cv2.TM_CCORR_NORMED)
_, distance = np.unravel_index(result.argmax(), result.shape)
return distance
3.轨迹生成
import random
def get_slide_track(distance):
slide_track = [[0, -1, 1]]
x = y = t = 0
while x < distance:
x += random.randint(5, 8)
t += random.randint(100, 110)
slide_track.append([x, y, t])
return slide_track
五、结果演示
最后提供两个动态更新的思路:
1、解析JS文件拿到参数名和密钥
2、修改加密函数,传参调用