当我们滑动滑块之后,发送了两个请求,一个是snapshot,提交的是滑块的轨迹信息,一个是SendLoginCode,是发送短信的接口,其他的都是在检测你是否扫描了当前页面上的二维码。
SendLoginCode接口提交的参数需要用到snapshot的返回值,所以我们得先搞定snapshot才能调用发送短信接口。
在snapshot请求里面,我们需要找到data参数生成的位置,才能模拟这个请求,并发送出去。
首先来查看调用栈,第一层是ajax请求,不用看,我们直接看第二层调用堆栈
这个位置发送了一个ajax请求,里面对应了抓包的四个参数,其他三个参数都是固定的,我们主要关心的是里面的a
a的来源是t.encryption()
我们再进入t.encryption()
函数
value: function() {
var e = JSON.stringify(this.sliderInfo);
return d.AES.encrypt(d.enc.Utf8.parse(e), d.enc.Utf8.parse("227V2xYeHTARSh1R"), {
mode: d.mode.ECB,
padding: d.pad.Pkcs7
}).toString()
}
这里读取了this.sliderInfo
的值进行json序列化操作,然后对e进行Aes加密。
sliderInfo是鼠标的轨迹信息,那么现在就需要找到sliderInfo的算法。鼠标的轨迹信息涉及到了多个鼠标事件
在这个大函数里面一共有下面的几个鼠标事件,分别是:
onMouseDown
onMouseMove
onMouseUp
handleTouchMove
这几个函数就是轨迹的生成算法,通过鼠标的点击事件记录鼠标滑动的坐标信息,保存到一个数组里面。这个轨迹信息,我们可以自己通过算法生成出来,主要就是要生成trank数组里面的数据。
示例代码如下:
import random
import time
def get_slider_info():
# 轨迹信息数组
slider_list = []
# 定义一个起始x坐标和y坐标
client_x = 300
client_y = 500
# 开始时间
start_time = int(int(time.time() * 1000) % 1e5)
# 设置一个滑块的宽度 设置一个大概的范围
width = random.randint(419, 431)
# 每滑动一次是3个像素
for slice_distance in range(3, width, 26):
if width - slice_distance <= 26:
slice_distance = width
start_time += random.randint(10, 1000)
# 开始时间
i = start_time
# x坐标
o = f"{client_x + slice_distance}.00"
# y坐标
u = f"{client_y + random.randint(-5, 5)}.00"
a = f"{slice_distance}.00"
# 拼接数据 放到数组
f = f"{i};{o};{u};{a}"
slider_list.append(f)
return slider_list
def run():
slider_list = get_slider_info()
print(slider_list)
if __name__ == '__main__':
run()
算法生成出来的轨迹数据如下:
E:\pyproject\test\venv\Scripts\python.exe E:\pyproject\test\main.py
['18080;303.00;498.00;3.00', '18584;329.00;505.00;29.00', '19080;355.00;501.00;55.00', '19190;381.00;497.00;81.00', '19297;407.00;501.00;107.00', '20133;433.00;497.00;133.00', '21088;459.00;495.00;159.00', '21864;485.00;496.00;185.00', '21960;511.00;505.00;211.00', '22482;537.00;501.00;237.00', '23408;563.00;496.00;263.00', '24050;589.00;504.00;289.00', '24313;615.00;501.00;315.00', '24340;641.00;502.00;341.00', '25192;667.00;499.00;367.00', '25824;693.00;498.00;393.00', '26381;731.00;498.00;431.00']
进程已结束,退出代码为 0
接下来把AES加密算法扣下来
def aes_encrypt(data_string):
# key = "227V2xYeHTARSh1R".encode('utf-8')
key_string = "32323756327859654854415253683152"
key = binascii.a2b_hex(key_string)
aes = AES.new(
key=key,
mode=AES.MODE_ECB
)
raw = pad(data_string.encode('utf-8'), 16)
aes_bytes = aes.encrypt(raw)
res_string = base64.b64encode(aes_bytes).decode('utf-8')
return res_string
然后模拟发送请求,看看返回值中的ret字段是否为true,如果是的话,那么这个滑块协议就分析成功了
直接运行,可以看到我们的算法就已经模拟成功了。
本文视频链接:视频链接