好友
阅读权限25
听众
最后登录1970-1-1
|
本帖最后由 13955925361 于 2025-9-11 23:31 编辑
数美的滑块是一个标准的DES加密,其中轨迹参考了下雨天视频中K哥的教程,
我自己用ai也写了个轨迹函数,通过率没有那么高就是了,所以我给注释掉了。
第一个接口返回两张图片和一个rid参数给下个接口用。下个验证接口有gg,hg,th三个参数需要逆向。
直接关键词搜gg,hg,th,定位到滑块验证码位置。 点进getEncryptContent方法里,有DES关键词,经检验,是标准的,JS直接导库就好。
var CryptoJS = require("crypto-js");
function DESEncrypt(key, word) {
var key_ = CryptoJS.enc.Utf8.parse(key);
var srcs = CryptoJS.enc.Utf8.parse(word);
var encrypted = CryptoJS.DES.encrypt(srcs, key_, {
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.ZeroPadding
});
return encrypted.toString();
}
以下我将用python代码完成验证码的还原。
[Python] 纯文本查看 复制代码
import requests
import re
import json
import time
import datetime
import random
import string
import execjs
def generate_timestamp_random():
"""
生成一个由当前时间戳(YYYYMMDDHHMMSS)和随机字符串组成的字符串
返回:
str: 格式为"时间戳+16位随机字符"的字符串
"""
# 获取当前时间并格式化为YYYYMMDDHHMMSS
current_time = datetime.datetime.now()
timestamp = current_time.strftime("%Y%m%d%H%M%S")
# 生成16位随机字符串(包含大小写字母和数字)
# 使用示例中的字符集:大小写字母和数字
characters = string.ascii_letters + string.digits
random_string = ''.join(random.choices(characters, k=16))
# 组合时间戳和随机字符串
return timestamp + random_string
from captcha_recognizer.recognizer import Recognizer
import logging
captchaUuid=generate_timestamp_random()
headers = {
"Accept": "*/*",
"Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6",
"Cache-Control": "no-cache",
"Connection": "keep-alive",
"Origin": "https://www.ishumei.com",
"Pragma": "no-cache",
"Referer": "https://www.ishumei.com/",
"Sec-Fetch-Dest": "script",
"Sec-Fetch-Mode": "cors",
"Sec-Fetch-Site": "cross-site",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0",
"sec-ch-ua": "\"Not;A=Brand\";v=\"99\", \"Microsoft Edge\";v=\"139\", \"Chromium\";v=\"139\"",
"sec-ch-ua-mobile": "?0",
"sec-ch-ua-platform": "\"Windows\""
}
url = "https://captcha1.fengkongcloud.cn/ca/v1/register"
params = {
"appId": "default",
"organization": "d6tpAY1oV0Kv5jRSgxQr",
"captchaUuid": captchaUuid,
"data": "{}",
"channel": "default",
"sdkver": "1.1.3",
"rversion": "1.0.4",
"callback": f"sm_{time.time()*1000}",
"model": "slide",
"lang": "zh-cn"
}
response = requests.get(url, headers=headers, params=params).text
match = re.search(r'\((\{.*\})\)',response, re.DOTALL)
if match:
json_str = match.group(1)
try:
data = json.loads(json_str)
print("提取成功:")
print(json.dumps(data, indent=2, ensure_ascii=False))
except json.JSONDecodeError as e:
print("JSON 解析失败:", e)
else:
print("未找到 JSON 数据")
bg='https://castatic.fengkongcloud.cn/'+str(data['detail']['bg'])
front='https://castatic.fengkongcloud.cn/'+str(data['detail']['fg'])
bgContent=requests.get(bg,headers=headers).content
frontContent=requests.get(front,headers=headers).content
with open ('bg.png','wb') as f:
f.write(bgContent)
with open ('front.png','wb') as f:
f.write(frontContent)
import cv2
import os
def get_slide_distance( bg_path, slide_path):
bg_img = cv2.imread(bg_path)
sd_img = cv2.imread(slide_path)
# 获取滑块实际宽高(关键步骤)
slide_height, slide_width = sd_img.shape[:2] # 提取高度和宽度(忽略通道数)
# 背景图预处理(灰度化→模糊→边缘检测→转RGB)
bg_gray = cv2.cvtColor(bg_img, cv2.COLOR_BGR2GRAY)
bg_gray = cv2.GaussianBlur(bg_gray, (5, 5), 0)
bg_edge = cv2.Canny(bg_gray, 30, 100)
rgb_bg_gray = cv2.cvtColor(bg_edge, cv2.COLOR_GRAY2RGB)
# 滑块图预处理(与背景图处理一致)
sd_gray = cv2.cvtColor(sd_img, cv2.COLOR_BGR2GRAY)
sd_gray = cv2.GaussianBlur(sd_gray, (5, 5), 0)
sd_edge = cv2.Canny(sd_gray, 30, 100)
rgb_sd_gray = cv2.cvtColor(sd_edge, cv2.COLOR_GRAY2RGB)
# 模板匹配
result = cv2.matchTemplate(rgb_bg_gray, rgb_sd_gray, cv2.TM_CCORR_NORMED)
_, _, _, max_loc = cv2.minMaxLoc(result)
# 用滑块真实宽高标记矩形(核心修改处)
# 右下角坐标 = 左上角坐标 + 滑块宽高
cv2.rectangle(
bg_img,
(max_loc[0], max_loc[1]), # 左上角
(max_loc[0] + slide_width, max_loc[1] + slide_height), # 右下角(动态计算)
(0, 255, 0), # 绿色
2 # 线宽
)
# 保存结果图
result_path = os.path.join(os.path.dirname(bg_path), "result.png")
cv2.imwrite(result_path, bg_img)
# 返回滑动距离(滑块左上角x坐标)
return max_loc[0]
distance= get_slide_distance('bg.png','front.png')
print(f"滑块需要滑动的距离是: {distance}px")
result_distance=distance/2
print(result_distance)
rid=data['detail']['rid']
print(rid)
with open('数美滑块.js', 'r', encoding='utf-8')as f:
js_code = f.read()
ctx=execjs.compile(js_code)
num=result_distance/300
print(num)
gg=ctx.call('DESEncrypt',"5129c2c2",num)
print(gg)
# def generate_slider_trace(distance):
# """
# 生成符合规律的滑块轨迹:
# - x轴:过冲→回调→稳定
# - y轴:小幅向下抖动,中间回调
# - z轴:稳定递增(每次+100±10)
# - 点数:≈ distance × 0.25~0.3
# #
# # 参数:
# # distance: 目标滑动距离(如122)
# #
# # 返回:
# # list: 轨迹列表[[x, y, z], ...]
# # """
# # # 初始化轨迹起点
# x = [0]
# y = [0]
# z = [0]
#
# # 计算总点数(0.25x~0.3x)
# total_points = int(distance * random.uniform(0.25, 0.3))
# # 分配各阶段点数(按规律比例)
# accelerate_points = int(total_points * 0.15) # 加速阶段(15%)
# overshoot_points = 1 # 过冲点(固定1个)
# callback_points = int(total_points * 0.1) # 回调阶段(10%)
# adjust_points = int(total_points * 0.2) # 微调阶段(20%)
# stable_points = total_points - (accelerate_points + overshoot_points + callback_points + adjust_points) # 稳定阶段(剩余)
# #
# # # -------------------- 1. X轴轨迹生成 --------------------
# # 阶段1:加速增长(快速接近目标)
# prev_x = 0
# for _ in range(accelerate_points):
# # 加速阶段:每次增量逐渐增大(模拟加速)
# ratio = _ / max(1, accelerate_points - 1) # 0~1
# delta = int(distance * 0.05 + distance * 0.6 * ratio) # 从慢到快
# prev_x += delta
# x.append(prev_x)
# #
# # 阶段2:过冲(超过目标值5%~15%)
# overshoot_ratio = random.uniform(0.05, 0.15)
# overshoot_x = distance + int(distance * overshoot_ratio)
# x.append(overshoot_x)
#
# # 阶段3:回调(从过冲值降到目标值下方5%~10%)
# callback_target = distance - int(distance * random.uniform(0.05, 0.1))
# step = (overshoot_x - callback_target) // callback_points
# current_x = overshoot_x
# for _ in range(callback_points):
# current_x -= step
# x.append(current_x)
#
# # 阶段4:微调(从目标下方逐步接近目标)
# current_x = x[-1]
# for _ in range(adjust_points):
# delta = random.randint(1, 3)
# current_x += delta
# if current_x >= distance:
# current_x = distance
# x.append(current_x)
#
# # 阶段5:稳定(保持在目标值)
# x.extend([distance] * stable_points)
#
# # 截断/补充至总点数(避免计算误差)
# x = x[:total_points]
# #
# # # -------------------- 2. Y轴轨迹生成 --------------------
# # 阶段1:初期抖动(幅度逐渐增大)
# current_y = 0
# for i in range(min(5, len(x) // 3)): # 前1/3轨迹
# delta = random.randint(-3, -1) # 向下抖动
# current_y += delta
# y.append(current_y)
# #
# # 阶段2:中期回调(向上调整)
# for i in range(min(3, len(x) // 4)): # 中间1/4轨迹
# delta = random.randint(1, 3) # 向上回调
# current_y += delta
# if current_y > 0:
# current_y = 0 # 不超过0
# y.append(current_y)
# #
# # 阶段3:后期稳定(小幅向下后保持)
# remaining = len(x) - len(y)
# for _ in range(remaining):
# if current_y > -5: # 限制最低值
# delta = random.choice([-1, -1, 0])
# else:
# delta = random.choice([0, 0, 1])
# current_y += delta
# y.append(current_y)
# #
# # # -------------------- 3. Z轴轨迹生成 --------------------
# # 每次增量100±10,稳定递增
# current_z = 0
# for _ in range(len(x) - 1):
# increment = random.randint(90, 110) # 100±10
# current_z += increment
# z.append(current_z)
#
# # 组合轨迹
# trace = [list(point) for point in zip(x, y, z)]
# return trace
#
# trace = generate_slider_trace(result_distance)
# print(trace)
# hg=ctx.call('DESEncrypt',"be221ccf",str(trace))
# print(hg)
# time_diff=round(int(result_distance)*3181/107)
# #
# print(f"滑块滑动时间差为: {time_diff}ms")
# th=ctx.call('DESEncrypt',"231a540d",time_diff)
# print(th)
import numpy as np
import math
def get_track(distance):
x = [0, 0]
y = [0, 0, 0]
z = [0]
count = np.linspace(-math.pi / 2, math.pi / 2, random.randrange(20, 30))
func = list(map(math.sin, count))
nx = [i + 1 for i in func]
add = random.randrange(10, 15)
sadd = distance + add
x.extend(list(map(lambda x: x * (sadd / 2), nx)))
x.extend(np.linspace(sadd, distance, 3 if add > 12 else 2))
x = [math.floor(i) for i in x]
for i in range(len(x) - 2):
if y[-1] < 30:
y.append(y[-1] + random.choice([0, 0, 1, 1, 2, 2, 2, 1, 2, 0, 0, 3, 3]))
else:
y.append(y[-1] + random.choice([0, 0, -1, -1, -2, -2, -1, -2, -1, -2, 0, 0, -3, -3]))
for i in range(len(x) - 1):
z.append((z[-1] // 100 * 100) + 100 + random.choice([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2]))
trace = list(map(list, zip(x, y, z)))
times = trace[-1][-1] + random.randint(1, 5)
# logger.info(f'模拟的轨迹--->>>{trace}')
# logger.info(f'times--->>>{times}')
return trace, times
trace,times=get_track(result_distance)
print(trace)
print( times)
hg=ctx.call('DESEncrypt',"be221ccf",str(trace))
print(hg)
th=ctx.call('DESEncrypt',"231a540d",times)
print(th)
#
#
# # 测试:生成目标距离为182的轨迹
# #
# #
params = {
"to": "bftazdO+dKs=",
"ny": "cvSxP/Xnulg=",
"callback": f"sm_{round(time.time()*1000)}",
"bs": "ZGIsKZZObiI=",
"fm": "BNYA+9sHvZU=",
"act.os": "web_pc",
"captchaUuid": captchaUuid,
"lf": "LCntkg8Oqr0=",
"protocol": "185",
"sl": "ld3hnK7eLbY=",
"rid": rid,
"qt": "QcZFnVbE0HA=",
"sdkver": "1.1.3",
"rversion": "1.0.4",
"yh": "wFVE7H+kToU=",
"ostype": "web",
"bq": "1szrpYdSRZQ=",
"organization": "d6tpAY1oV0Kv5jRSgxQr",
'gg':gg,
'hg': hg,
'th':th,
}
print(params)
url_2 = "https://captcha1.fengkongcloud.cn/ca/v2/fverify"
headers_2= {
"Accept": "*/*",
"Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6",
"Cache-Control": "no-cache",
"Connection": "keep-alive",
"Origin": "https://www.ishumei.com",
"Pragma": "no-cache",
"Referer": "https://www.ishumei.com/",
"Sec-Fetch-Dest": "script",
"Sec-Fetch-Mode": "cors",
"Sec-Fetch-Site": "cross-site",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36 Edg/140.0.0.0",
"sec-ch-ua": "\"Chromium\";v=\"140\", \"Not=A?Brand\";v=\"24\", \"Microsoft Edge\";v=\"140\"",
"sec-ch-ua-mobile": "?0",
"sec-ch-ua-platform": "\"Windows\""
}
response_2 = requests.get(url_2, headers=headers_2, params=params)
print(response_2.text)
最终输出效果为pass代表通过。
|
免费评分
-
查看全部评分
|