mirror of
https://github.com/sijiyo/projects.git
synced 2025-04-12 03:26:58 +08:00
Add files via upload
This commit is contained in:
commit
94d9f32e3f
26395
geetest3_fullpage/jiyan.js
Normal file
26395
geetest3_fullpage/jiyan.js
Normal file
File diff suppressed because one or more lines are too long
32
geetest3_fullpage/mian.py
Normal file
32
geetest3_fullpage/mian.py
Normal file
@ -0,0 +1,32 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import random,threading, execjs, requests, time, json
|
||||
|
||||
|
||||
def main():
|
||||
frist_time = str(round(time.time() * 1000))
|
||||
url = "https://www.geetest.com/demo/gt/register-fullpage?t=" + str(round(time.time() * 1000))
|
||||
res = requests.get(url).json()
|
||||
gt = res['gt']
|
||||
challenge = res['challenge']
|
||||
with open('jiyan.js', 'r', encoding='utf-8') as f:
|
||||
js = execjs.compile(f.read())
|
||||
key = js.call('get_key')
|
||||
w = js.call('get_w1', gt, challenge, key)
|
||||
url = "https://apiv6.geetest.com/get.php?gt=" + gt + "&challenge=" + challenge + "&lang=zh-cn&pt=0&client_type=web&w=" + w + "&callback=geetest_" + str(
|
||||
round(time.time() * 1000))
|
||||
res = requests.get(url).text
|
||||
res = json.loads(res[res.index("(") + 1:res.rindex(")")])
|
||||
s = res['data']['s']
|
||||
w = js.call('get_w2',s,str(random.randint(500, 3000)),gt,challenge,frist_time,key)
|
||||
url = "https://api.geetest.com/ajax.php?gt=" + gt + "&challenge=" + challenge + "&lang=zh-cn&pt=0&client_type=web&w=" + w + "&callback=geetest_" + str(
|
||||
round(time.time() * 1000))
|
||||
res = requests.get(url).text
|
||||
res = json.loads(res[res.index("(") + 1:res.rindex(")")])
|
||||
print(res)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
for i in range(1):
|
||||
thr = threading.Thread(target=main)
|
||||
thr.start()
|
||||
time.sleep(2)
|
BIN
geetest3_slide/__pycache__/gap.cpython-38.pyc
Normal file
BIN
geetest3_slide/__pycache__/gap.cpython-38.pyc
Normal file
Binary file not shown.
BIN
geetest3_slide/__pycache__/trace.cpython-38.pyc
Normal file
BIN
geetest3_slide/__pycache__/trace.cpython-38.pyc
Normal file
Binary file not shown.
92
geetest3_slide/gap.py
Normal file
92
geetest3_slide/gap.py
Normal file
@ -0,0 +1,92 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import cv2,os
|
||||
from PIL import Image
|
||||
class SlideCrack(object):
|
||||
def __init__(self, gap, bg, out):
|
||||
self.gap = gap
|
||||
self.bg = bg
|
||||
self.out = out
|
||||
|
||||
@staticmethod
|
||||
def clear_white(img):
|
||||
# 清除图片的空白区域,这里主要清除滑块的空白
|
||||
img = cv2.imread(img)
|
||||
rows, cols, channel = img.shape
|
||||
min_x = 255
|
||||
min_y = 255
|
||||
max_x = 0
|
||||
max_y = 0
|
||||
for x in range(1, rows):
|
||||
for y in range(1, cols):
|
||||
t = set(img[x, y])
|
||||
if len(t) >= 2:
|
||||
if x <= min_x:
|
||||
min_x = x
|
||||
elif x >= max_x:
|
||||
max_x = x
|
||||
|
||||
if y <= min_y:
|
||||
min_y = y
|
||||
elif y >= max_y:
|
||||
max_y = y
|
||||
img1 = img[min_x:max_x, min_y: max_y]
|
||||
return img1
|
||||
|
||||
def template_match(self, tpl, target):
|
||||
th, tw = tpl.shape[:2]
|
||||
result = cv2.matchTemplate(target, tpl, cv2.TM_CCOEFF_NORMED)
|
||||
# 寻找矩阵(一维数组当作向量,用Mat定义) 中最小值和最大值的位置
|
||||
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
|
||||
tl = max_loc
|
||||
br = (tl[0] + tw, tl[1] + th)
|
||||
cv2.rectangle(target, tl, br, (0, 0, 255), 2)
|
||||
cv2.imwrite(self.out, target)
|
||||
return tl[0]
|
||||
@staticmethod
|
||||
def image_edge_detection(img):
|
||||
edges = cv2.Canny(img, 100, 200)
|
||||
return edges
|
||||
def discern(self):
|
||||
img1 = self.clear_white(self.gap)
|
||||
img1 = cv2.cvtColor(img1, cv2.COLOR_RGB2GRAY)
|
||||
slide = self.image_edge_detection(img1)
|
||||
|
||||
back = cv2.imread(self.bg, 0)
|
||||
back = self.image_edge_detection(back)
|
||||
|
||||
slide_pic = cv2.cvtColor(slide, cv2.COLOR_GRAY2RGB)
|
||||
back_pic = cv2.cvtColor(back, cv2.COLOR_GRAY2RGB)
|
||||
x = self.template_match(slide_pic, back_pic)
|
||||
# 输出横坐标, 即 滑块在图片上的位置
|
||||
return x
|
||||
def get_gap():
|
||||
# 滑块图片
|
||||
# image1 = "img/tukuai.png"
|
||||
image1 = r'./img/slide.png'
|
||||
# 背景图片
|
||||
# image2 = "img/beijing.png"
|
||||
image2 = r'./img/bg.png'
|
||||
# 处理结果图片,用红线标注
|
||||
#image3 = "img/show_image.png"
|
||||
image3 = r'./img/show_image.png'
|
||||
sc = SlideCrack(image1, image2, image3)
|
||||
os.remove('./img/oldbg.png')
|
||||
os.remove('./img/oldallbg.png')
|
||||
os.remove('./img/newallbg.png')
|
||||
return sc.discern()
|
||||
def restore_picture():
|
||||
img_list = ["./img/oldbg.png", "./img/oldallbg.png"]
|
||||
for index, img in enumerate(img_list):
|
||||
image = Image.open(img)
|
||||
s = Image.new("RGBA", (260, 160))
|
||||
ut = [39, 38, 48, 49, 41, 40, 46, 47, 35, 34, 50, 51, 33, 32, 28, 29, 27, 26, 36, 37, 31, 30, 44, 45, 43,42,12, 13, 23, 22, 14, 15, 21, 20, 8, 9, 25, 24, 6, 7, 3, 2, 0, 1, 11, 10, 4, 5, 19, 18, 16, 17]
|
||||
height_half = 80
|
||||
for inx in range(52):
|
||||
c = ut[inx] % 26 * 12 + 1
|
||||
u = height_half if ut[inx] > 25 else 0
|
||||
l_ = image.crop(box=(c, u, c + 10, u + 80))
|
||||
s.paste(l_, box=(inx % 26 * 10, 80 if inx > 25 else 0))
|
||||
if index == 0:
|
||||
s.save("./img/bg.png")
|
||||
else:
|
||||
s.save("./img/newallbg.png")
|
BIN
geetest3_slide/img/bg.png
Normal file
BIN
geetest3_slide/img/bg.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 58 KiB |
BIN
geetest3_slide/img/show_image.png
Normal file
BIN
geetest3_slide/img/show_image.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.1 KiB |
BIN
geetest3_slide/img/slide.png
Normal file
BIN
geetest3_slide/img/slide.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.4 KiB |
2276
geetest3_slide/jiyan.js
Normal file
2276
geetest3_slide/jiyan.js
Normal file
File diff suppressed because one or more lines are too long
47
geetest3_slide/mian.py
Normal file
47
geetest3_slide/mian.py
Normal file
@ -0,0 +1,47 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import threading,execjs, requests, time, json
|
||||
from urllib import request
|
||||
from gap import *
|
||||
from trace import *
|
||||
|
||||
|
||||
def get_image():
|
||||
url = "https://www.geetest.com/demo/gt/register-slide?t=" + str(round(time.time() * 1000))
|
||||
res = requests.get(url).json()
|
||||
gt = res['gt']
|
||||
challenge = res['challenge']
|
||||
res = requests.get("https://api.geetest.com/ajax.php?gt=" + gt + "&challenge=" + challenge + "&lang=zh-cn&pt=0&w=&callback=geetest_" + str(
|
||||
round(time.time() * 1000))).text
|
||||
url = "https://api.geetest.com/get.php?is_next=true&type=slide3>=" + gt + "&challenge=" + challenge + "&lang=zh-cn&https=true&protocol=https%3A%2F%2F&offline=false&product=embed&api_server=api.geetest.com&isPC=true&autoReset=true&width=100%25&callback=geetest_" + str(
|
||||
round(time.time() * 1000))
|
||||
res = requests.get(url).text
|
||||
res = json.loads(res[res.index("(") + 1:res.rindex(")")])
|
||||
challenge = res['challenge']
|
||||
s = res['s']
|
||||
request.urlretrieve('https://static.geetest.com/' + res['fullbg'], 'img/oldallbg.png')
|
||||
request.urlretrieve('https://static.geetest.com/' + res['bg'], 'img/oldbg.png')
|
||||
request.urlretrieve('https://static.geetest.com/' + res['slice'], 'img/slide.png')
|
||||
restore_picture()
|
||||
distance = get_gap()
|
||||
track = get_track(distance - 5)
|
||||
return gt, challenge, s, distance, track
|
||||
|
||||
def main():
|
||||
gt, challenge, s, distance, track = get_image()
|
||||
with open('jiyan.js', 'r', encoding='utf-8') as f:
|
||||
js = execjs.compile(f.read())
|
||||
passtime = track[-1][-1]
|
||||
track = js.call('get_encode_trace', track, s)
|
||||
w = js.call('get_w', distance - 5, track, challenge, challenge[:32], passtime, str(random.randint(100, 200)),gt)
|
||||
url = "https://api.geetest.com/ajax.php?gt=" + gt + "&challenge=" + challenge + "&lang=zh-cn&pt=0&w=" + w + "&callback=geetest_" + str(
|
||||
round(time.time() * 1000))
|
||||
res = requests.get(url).text
|
||||
res = json.loads(res[res.index("(") + 1:res.rindex(")")])
|
||||
print(res)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
for i in range(1):
|
||||
thr = threading.Thread(target=main)
|
||||
thr.start()
|
||||
time.sleep(2)
|
47
geetest3_slide/trace.py
Normal file
47
geetest3_slide/trace.py
Normal file
@ -0,0 +1,47 @@
|
||||
import random
|
||||
|
||||
|
||||
def __ease_out_expo(sep):
|
||||
'''
|
||||
轨迹相关操作
|
||||
'''
|
||||
if sep == 1:
|
||||
return 1
|
||||
else:
|
||||
return 1 - pow(2, -10 * sep)
|
||||
|
||||
def get_track(distance):
|
||||
"""
|
||||
根据滑动距离生成滑动轨迹
|
||||
:param distance: 需要滑动的距离
|
||||
:return: 滑动轨迹<type 'list'>: [[x,y,t], ...]
|
||||
x: 已滑动的横向距离
|
||||
y: 已滑动的纵向距离, 除起点外, 均为0
|
||||
t: 滑动过程消耗的时间, 单位: 毫秒
|
||||
"""
|
||||
|
||||
if not isinstance(distance, int) or distance < 0:
|
||||
raise ValueError(f"distance类型必须是大于等于0的整数: distance: {distance}, type: {type(distance)}")
|
||||
# 初始化轨迹列表
|
||||
slide_track = [
|
||||
[random.randint(-50, -10), random.randint(-50, -10), 0],
|
||||
[0, 0, 0],
|
||||
]
|
||||
# 共记录count次滑块位置信息
|
||||
count = 30 + int(distance / 2)
|
||||
# 初始化滑动时间
|
||||
t = random.randint(50, 100)
|
||||
# 记录上一次滑动的距离
|
||||
_x = 0
|
||||
_y = 0
|
||||
for i in range(count):
|
||||
# 已滑动的横向距离
|
||||
x = round(__ease_out_expo(i / count) * distance)
|
||||
# 滑动过程消耗的时间
|
||||
t += random.randint(10, 20)
|
||||
if x == _x:
|
||||
continue
|
||||
slide_track.append([x, _y, t])
|
||||
_x = x
|
||||
slide_track.append(slide_track[-1])
|
||||
return slide_track
|
57
geetest4_fullpage/jiyan.js
Normal file
57
geetest4_fullpage/jiyan.js
Normal file
@ -0,0 +1,57 @@
|
||||
const NodeRSA = require('node-rsa');
|
||||
const crypto = require('crypto');
|
||||
const CryptoJS = require("crypto-js");
|
||||
function get_key() {
|
||||
var s4 = "";
|
||||
for (i = 0; i < 4; i++) {
|
||||
s4 = s4 + ((1 + Math["random"]()) * 65536 | 0)["toString"](16)["substring"](1);
|
||||
}
|
||||
return s4;
|
||||
}
|
||||
function MD5_Encrypt(word) {
|
||||
return CryptoJS.MD5(word).toString();
|
||||
}
|
||||
function AES_Encrypt(key, word) {
|
||||
var srcs = CryptoJS.enc.Utf8.parse(word);
|
||||
var encrypted = CryptoJS.AES.encrypt(srcs, CryptoJS.enc.Utf8.parse(key), {
|
||||
iv: CryptoJS.enc.Utf8.parse("0000000000000000"),
|
||||
mode: CryptoJS.mode.CBC,
|
||||
padding: CryptoJS.pad.Pkcs7
|
||||
});
|
||||
return CryptoJS.enc.Hex.stringify(CryptoJS.enc.Base64.parse(encrypted.toString()));
|
||||
}
|
||||
function RSA_encrypt(data) {
|
||||
const public_key_1 = '00C1E3934D1614465B33053E7F48EE4EC87B14B95EF88947713D25EECBFF7E74C7977D02DC1D9451F79DD5D1C10C29ACB6A9B4D6FB7D0A0279B6719E1772565F09AF627715919221AEF91899CAE08C0D686D748B20A3603BE2318CA6BC2B59706592A9219D0BF05C9F65023A21D2330807252AE0066D59CEEFA5F2748EA80BAB81';
|
||||
const public_key_2 = '10001';
|
||||
const public_key = new NodeRSA();
|
||||
public_key.importKey({
|
||||
n: Buffer.from(public_key_1, 'hex'),
|
||||
e: parseInt(public_key_2, 16),
|
||||
}, 'components-public');
|
||||
const encrypted = crypto.publicEncrypt({
|
||||
key: public_key.exportKey('public'),
|
||||
padding: crypto.constants.RSA_PKCS1_PADDING
|
||||
}, Buffer.from(data));
|
||||
return encrypted.toString('hex');
|
||||
}
|
||||
|
||||
function get_w(captchaId, lot_number, detail_time, distance) {
|
||||
romdon_key = get_key()
|
||||
pow_msg = "1|0|md5|" + detail_time + "|" + captchaId + "|" + lot_number + "||" + romdon_key
|
||||
xiyu = {
|
||||
"setLeft": distance,
|
||||
"userresponse": distance / (.8876 * 340 / 300),
|
||||
"device_id": "D00D",
|
||||
"lot_number": lot_number,
|
||||
"pow_msg": pow_msg,
|
||||
"pow_sign": MD5_Encrypt(pow_msg),
|
||||
"geetest": "captcha",
|
||||
"lang": "zh",
|
||||
"ep": "123",
|
||||
'cuel': '632729377',
|
||||
"em": {"ph": 0, "cp": 0, "ek": "11", "wd": 1, "nt": 0, "si": 0, "sc": 0}
|
||||
}
|
||||
xiyu = JSON.stringify(xiyu).replace(" ", "").replace("'", '"')
|
||||
w = AES_Encrypt(romdon_key, xiyu)+ RSA_encrypt(romdon_key)
|
||||
return w
|
||||
}
|
48
geetest4_fullpage/mian.py
Normal file
48
geetest4_fullpage/mian.py
Normal file
@ -0,0 +1,48 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import re, requests, time, uuid, execjs, json
|
||||
from lxml import etree
|
||||
from urllib import request
|
||||
|
||||
|
||||
def get_captchaId():
|
||||
url = "https://www.geetest.com/adaptive-captcha-demo"
|
||||
res = requests.get(url).text
|
||||
js_url = re.search(r'preload" href="(/_next/static/[^"]+\.js)" as="script"/>', res).group(1)
|
||||
res = requests.get("https://www.geetest.com" + js_url).text
|
||||
captchaId = re.search('captchaId:"([0-9a-z]+)"', res).group(1)
|
||||
return captchaId
|
||||
|
||||
|
||||
def main(captchaId, challenge):
|
||||
url = "https://gcaptcha4.geetest.com/load?captcha_id=" + captchaId + "&challenge=" + challenge + "&client_type=web&risk_type=ai&lang=zh&callback=geetest_" + str(
|
||||
round(time.time() * 1000))
|
||||
res = requests.get(url).text
|
||||
res = json.loads(res[res.index("(") + 1:res.rindex(")")])
|
||||
lot_number = res['data']['lot_number']
|
||||
detail_time = res['data']["pow_detail"]["datetime"]
|
||||
with open('jiyan.js', 'r', encoding='utf-8') as f:
|
||||
js = execjs.compile(f.read())
|
||||
key = js.call('get_key')
|
||||
w = js.call('get_w', captchaId, lot_number, detail_time)
|
||||
url = "https://gcaptcha4.geetest.com/verify"
|
||||
params = {
|
||||
"callback": "geetest_" + str(round(time.time() * 1000)),
|
||||
"captcha_id": captchaId,
|
||||
"client_type": "web",
|
||||
"lot_number": lot_number,
|
||||
"risk_type": "ai",
|
||||
"payload": res['data']['payload'],
|
||||
"process_token": res['data']['process_token'],
|
||||
"payload_protocol": "1",
|
||||
"pt": "1",
|
||||
"w": w
|
||||
}
|
||||
res = requests.get(url, params=params).text
|
||||
res = json.loads(res[res.index("(") + 1:res.rindex(")")])
|
||||
print('fullpage4:',res)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
captchaId = get_captchaId()
|
||||
challenge = str(uuid.uuid4())
|
||||
main(captchaId, challenge)
|
BIN
geetest4_slide/__pycache__/gap.cpython-38.pyc
Normal file
BIN
geetest4_slide/__pycache__/gap.cpython-38.pyc
Normal file
Binary file not shown.
BIN
geetest4_slide/__pycache__/trace.cpython-38.pyc
Normal file
BIN
geetest4_slide/__pycache__/trace.cpython-38.pyc
Normal file
Binary file not shown.
89
geetest4_slide/gap.py
Normal file
89
geetest4_slide/gap.py
Normal file
@ -0,0 +1,89 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import cv2
|
||||
|
||||
|
||||
class SlideCrack(object):
|
||||
def __init__(self, gap, bg, out):
|
||||
"""
|
||||
init code
|
||||
:param gap: 缺口图片
|
||||
:param bg: 背景图片
|
||||
:param out: 输出图片
|
||||
"""
|
||||
self.gap = gap
|
||||
self.bg = bg
|
||||
self.out = out
|
||||
|
||||
@staticmethod
|
||||
def clear_white(img):
|
||||
# 清除图片的空白区域,这里主要清除滑块的空白
|
||||
img = cv2.imread(img)
|
||||
rows, cols, channel = img.shape
|
||||
min_x = 255
|
||||
min_y = 255
|
||||
max_x = 0
|
||||
max_y = 0
|
||||
for x in range(1, rows):
|
||||
for y in range(1, cols):
|
||||
t = set(img[x, y])
|
||||
if len(t) >= 2:
|
||||
if x <= min_x:
|
||||
min_x = x
|
||||
elif x >= max_x:
|
||||
max_x = x
|
||||
|
||||
if y <= min_y:
|
||||
min_y = y
|
||||
elif y >= max_y:
|
||||
max_y = y
|
||||
img1 = img[min_x:max_x, min_y: max_y]
|
||||
return img1
|
||||
|
||||
def template_match(self, tpl, target):
|
||||
th, tw = tpl.shape[:2]
|
||||
result = cv2.matchTemplate(target, tpl, cv2.TM_CCOEFF_NORMED)
|
||||
# 寻找矩阵(一维数组当作向量,用Mat定义) 中最小值和最大值的位置
|
||||
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
|
||||
tl = max_loc
|
||||
br = (tl[0] + tw, tl[1] + th)
|
||||
# 绘制矩形边框,将匹配区域标注出来
|
||||
# target:目标图像
|
||||
# tl:矩形定点
|
||||
# br:矩形的宽高
|
||||
# (0,0,255):矩形边框颜色
|
||||
# 1:矩形边框大小
|
||||
cv2.rectangle(target, tl, br, (0, 0, 255), 2)
|
||||
cv2.imwrite(self.out, target)
|
||||
return tl[0]
|
||||
|
||||
@staticmethod
|
||||
def image_edge_detection(img):
|
||||
edges = cv2.Canny(img, 100, 200)
|
||||
return edges
|
||||
|
||||
def discern(self):
|
||||
img1 = self.clear_white(self.gap)
|
||||
img1 = cv2.cvtColor(img1, cv2.COLOR_RGB2GRAY)
|
||||
slide = self.image_edge_detection(img1)
|
||||
|
||||
back = cv2.imread(self.bg, 0)
|
||||
back = self.image_edge_detection(back)
|
||||
|
||||
slide_pic = cv2.cvtColor(slide, cv2.COLOR_GRAY2RGB)
|
||||
back_pic = cv2.cvtColor(back, cv2.COLOR_GRAY2RGB)
|
||||
x = self.template_match(slide_pic, back_pic)
|
||||
# 输出横坐标, 即 滑块在图片上的位置
|
||||
return x
|
||||
|
||||
|
||||
def get_gap():
|
||||
# 滑块图片
|
||||
image1 = "img/slide.png"
|
||||
# 背景图片
|
||||
image2 = "img/bg.png"
|
||||
|
||||
# 处理结果图片,用红线标注
|
||||
image3 = "img/show_image.png"
|
||||
sc = SlideCrack(image1, image2, image3)
|
||||
return sc.discern()
|
BIN
geetest4_slide/img/bg.png
Normal file
BIN
geetest4_slide/img/bg.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 84 KiB |
BIN
geetest4_slide/img/show_image.png
Normal file
BIN
geetest4_slide/img/show_image.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 9.4 KiB |
BIN
geetest4_slide/img/slide.png
Normal file
BIN
geetest4_slide/img/slide.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 8.6 KiB |
189539
geetest4_slide/img/tracks.json
Normal file
189539
geetest4_slide/img/tracks.json
Normal file
File diff suppressed because it is too large
Load Diff
59
geetest4_slide/jiyan.js
Normal file
59
geetest4_slide/jiyan.js
Normal file
@ -0,0 +1,59 @@
|
||||
const NodeRSA = require('node-rsa');
|
||||
const crypto = require('crypto');
|
||||
const CryptoJS = require("crypto-js");
|
||||
function get_key() {
|
||||
var s4 = "";
|
||||
for (i = 0; i < 4; i++) {
|
||||
s4 = s4 + ((1 + Math["random"]()) * 65536 | 0)["toString"](16)["substring"](1);
|
||||
}
|
||||
return s4;
|
||||
}
|
||||
function MD5_Encrypt(word) {
|
||||
return CryptoJS.MD5(word).toString();
|
||||
}
|
||||
function AES_Encrypt(key, word) {
|
||||
var srcs = CryptoJS.enc.Utf8.parse(word);
|
||||
var encrypted = CryptoJS.AES.encrypt(srcs, CryptoJS.enc.Utf8.parse(key), {
|
||||
iv: CryptoJS.enc.Utf8.parse("0000000000000000"),
|
||||
mode: CryptoJS.mode.CBC,
|
||||
padding: CryptoJS.pad.Pkcs7
|
||||
});
|
||||
return CryptoJS.enc.Hex.stringify(CryptoJS.enc.Base64.parse(encrypted.toString()));
|
||||
}
|
||||
function RSA_encrypt(data) {
|
||||
const public_key_1 = '00C1E3934D1614465B33053E7F48EE4EC87B14B95EF88947713D25EECBFF7E74C7977D02DC1D9451F79DD5D1C10C29ACB6A9B4D6FB7D0A0279B6719E1772565F09AF627715919221AEF91899CAE08C0D686D748B20A3603BE2318CA6BC2B59706592A9219D0BF05C9F65023A21D2330807252AE0066D59CEEFA5F2748EA80BAB81';
|
||||
const public_key_2 = '10001';
|
||||
const public_key = new NodeRSA();
|
||||
public_key.importKey({
|
||||
n: Buffer.from(public_key_1, 'hex'),
|
||||
e: parseInt(public_key_2, 16),
|
||||
}, 'components-public');
|
||||
const encrypted = crypto.publicEncrypt({
|
||||
key: public_key.exportKey('public'),
|
||||
padding: crypto.constants.RSA_PKCS1_PADDING
|
||||
}, Buffer.from(data));
|
||||
return encrypted.toString('hex');
|
||||
}
|
||||
|
||||
function get_w(captchaId, lot_number, detail_time, distance, passtime, track) {
|
||||
romdon_key = get_key()
|
||||
pow_msg = "1|0|md5|" + detail_time + "|" + captchaId + "|" + lot_number + "||" + romdon_key
|
||||
xiyu = {
|
||||
"setLeft": distance,
|
||||
"track": track,
|
||||
"passtime": passtime,
|
||||
"userresponse": distance / (.8876 * 340 / 300),
|
||||
"device_id": "D00D",
|
||||
"lot_number": lot_number,
|
||||
"pow_msg": pow_msg,
|
||||
"pow_sign": MD5_Encrypt(pow_msg),
|
||||
"geetest": "captcha",
|
||||
"lang": "zh",
|
||||
"ep": "123",
|
||||
'cuel': '632729377',
|
||||
"em": {"ph": 0, "cp": 0, "ek": "11", "wd": 1, "nt": 0, "si": 0, "sc": 0}
|
||||
}
|
||||
xiyu = JSON.stringify(xiyu).replace(" ", "").replace("'", '"')
|
||||
w = AES_Encrypt(romdon_key, xiyu)+ RSA_encrypt(romdon_key)
|
||||
return w
|
||||
}
|
60
geetest4_slide/mian.py
Normal file
60
geetest4_slide/mian.py
Normal file
@ -0,0 +1,60 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import re, requests, time, uuid, execjs,json
|
||||
from lxml import etree
|
||||
from urllib import request
|
||||
from gap import *
|
||||
from trace import *
|
||||
|
||||
|
||||
def get_captchaId():
|
||||
url = "https://www.geetest.com/adaptive-captcha-demo"
|
||||
res = requests.get(url).text
|
||||
HTML = etree.HTML(res)
|
||||
js_url = HTML.xpath("//link[contains(@href, 'adaptive-captcha-demo')]")[0].attrib["href"]
|
||||
res = requests.get("https://www.geetest.com" + js_url).text
|
||||
captchaId = re.search('captchaId:"([0-9a-z]+)"', res).group(1)
|
||||
return captchaId
|
||||
|
||||
|
||||
def get_image(captchaId, challenge):
|
||||
url = "https://gcaptcha4.geetest.com/load?captcha_id=" + captchaId + "&challenge=" + challenge + "&client_type=web&risk_type=slide&pt=1&lang=zho&callback=geetest_" + str(
|
||||
round(time.time() * 1000))
|
||||
res = requests.get(url).text
|
||||
res = json.loads(res[res.index("(") + 1:res.rindex(")")])
|
||||
request.urlretrieve('https://static.geetest.com/' + res['data']['bg'], 'img/bg.png')
|
||||
request.urlretrieve('https://static.geetest.com/' + res['data']['slice'], 'img/slide.png')
|
||||
distance = get_gap()
|
||||
track = get_track(distance)
|
||||
return res, distance, track
|
||||
|
||||
|
||||
def main(captchaId, challenge):
|
||||
res, distance, track = get_image(captchaId, challenge)
|
||||
lot_number = res['data']['lot_number']
|
||||
passtime = track[-1][-1]
|
||||
detail_time = res['data']["pow_detail"]["datetime"]
|
||||
with open('jiyan.js', 'r', encoding='utf-8') as f:
|
||||
js = execjs.compile(f.read())
|
||||
key = js.call('get_key')
|
||||
w = js.call('get_w', captchaId, lot_number, detail_time, distance, passtime, track)
|
||||
url = "https://gcaptcha4.geetest.com/verify"
|
||||
params = {
|
||||
"callback": "geetest_" + str(round(time.time() * 1000)),
|
||||
"captcha_id": captchaId,
|
||||
"client_type": "web",
|
||||
"lot_number": lot_number,
|
||||
"risk_type": "slide",
|
||||
"payload": res['data']['payload'],
|
||||
"process_token": res['data']['process_token'],
|
||||
"payload_protocol": "1",
|
||||
"pt": "1",
|
||||
"w": w
|
||||
}
|
||||
res = requests.get(url, params=params).text
|
||||
res = json.loads(res[res.index("(") + 1:res.rindex(")")])
|
||||
print(res)
|
||||
|
||||
if __name__ == '__main__':
|
||||
captchaId = get_captchaId()
|
||||
challenge = str(uuid.uuid4())
|
||||
main(captchaId, challenge)
|
33
geetest4_slide/trace.py
Normal file
33
geetest4_slide/trace.py
Normal file
@ -0,0 +1,33 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import random
|
||||
|
||||
|
||||
def __ease_out_expo(x):
|
||||
if x == 1:
|
||||
return 1
|
||||
else:
|
||||
return 1 - pow(2, -10 * x)
|
||||
def get_track(distance):
|
||||
if not isinstance(distance, int) or distance < 0:
|
||||
raise ValueError(f"distance类型必须是大于等于0的整数: distance: {distance}, type: {type(distance)}")
|
||||
# 初始化轨迹列表
|
||||
slide_track = [[random.randint(20, 60), random.randint(10, 40), 0]]
|
||||
# 共记录count次滑块位置信息
|
||||
count = 30 + int(distance / 2)
|
||||
# 初始化滑动时间
|
||||
t = random.randint(50, 100)
|
||||
# 记录上一次滑动的距离
|
||||
_x = 0
|
||||
_y = 0
|
||||
for i in range(count):
|
||||
# 已滑动的横向距离
|
||||
x = round(__ease_out_expo(i / count) * distance)
|
||||
# 滑动过程消耗的时间
|
||||
t = random.randint(10, 20)
|
||||
if x == _x:
|
||||
continue
|
||||
slide_track.append([x - _x, _y, t])
|
||||
_x = x
|
||||
slide_track.append([0, 0, random.randint(200, 300)])
|
||||
return slide_track
|
||||
|
Loading…
x
Reference in New Issue
Block a user