MihoyoBBS-gt-server/crack.py
2024-11-03 01:36:08 +08:00

534 lines
19 KiB
Python

import hashlib
import json
import math
import random
import time
import httpx
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.primitives import padding, serialization
from cryptography.hazmat.primitives.asymmetric.padding import PKCS1v15
class Crack:
def __init__(self, gt=None, challenge=None):
self.pic_path = None
self.s = None
self.c = None
self.session = httpx.Client(http2=True)
self.session.headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36"
}
# self.session.verify = False
self.gt = gt
self.challenge = challenge
self.aeskey = "".join(
f"{int((1 + random.random()) * 65536):04x}"[1:] for _ in range(4)
)
public_key = """-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDB45NNFhRGWzMFPn9I7k7IexS5
XviJR3E9Je7L/350x5d9AtwdlFH3ndXRwQwprLaptNb7fQoCebZxnhdyVl8Jr2J3
FZGSIa75GJnK4IwNaG10iyCjYDviMYymvCtZcGWSqSGdC/Bcn2UCOiHSMwgHJSrg
Bm1Zzu+l8nSOqAurgQIDAQAB
-----END PUBLIC KEY-----"""
self.public_key = serialization.load_pem_public_key(public_key.encode())
self.enc_key = self.public_key.encrypt(self.aeskey.encode(), PKCS1v15()).hex()
with open("mousepath.json", "r") as f:
self.mouse_path = json.loads(f.read())
def get_type(self) -> dict:
url = f"https://api.geetest.com/gettype.php?gt={self.gt}"
res = self.session.get(url)
return json.loads(res.text[1:-1])["data"]
@staticmethod
def encode(input_bytes: list):
def get_char_from_index(index):
char_table = (
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789()"
)
return char_table[index] if 0 <= index < len(char_table) else "."
def transform_value(value, bit_mask):
result = 0
for r in range(23, -1, -1):
if (bit_mask >> r) & 1:
result = (result << 1) + ((value >> r) & 1)
return result
encoded_string = ""
padding = ""
input_length = len(input_bytes)
for i in range(0, input_length, 3):
chunk_length = min(3, input_length - i)
chunk = input_bytes[i : i + chunk_length]
if chunk_length == 3:
value = (chunk[0] << 16) + (chunk[1] << 8) + chunk[2]
encoded_string += (
get_char_from_index(transform_value(value, 7274496))
+ get_char_from_index(transform_value(value, 9483264))
+ get_char_from_index(transform_value(value, 19220))
+ get_char_from_index(transform_value(value, 235))
)
elif chunk_length == 2:
value = (chunk[0] << 16) + (chunk[1] << 8)
encoded_string += (
get_char_from_index(transform_value(value, 7274496))
+ get_char_from_index(transform_value(value, 9483264))
+ get_char_from_index(transform_value(value, 19220))
)
padding = "."
elif chunk_length == 1:
value = chunk[0] << 16
encoded_string += get_char_from_index(
transform_value(value, 7274496)
) + get_char_from_index(transform_value(value, 9483264))
padding = ".."
return encoded_string + padding
@staticmethod
def MD5(text: str):
return hashlib.md5(text.encode()).hexdigest()
@staticmethod
def encode_mouse_path(path: list, c: list, s: str):
def preprocess(path: list):
def BFIQ(e):
t = 32767
if not isinstance(e, int):
return e
else:
if t < e:
e = t
elif e < -t:
e = -t
return round(e)
def BGAB(e):
t = ""
n = 0
len(e or [])
while n < len(e) and not t:
if e[n]:
t = e[n][4]
n += 1
if not t:
return e
r = ""
i = ["mouse", "touch", "pointer", "MSPointer"]
for s in range(len(i)):
if t.startswith(i[s]):
r = i[s]
_ = list(e)
for a in range(len(_) - 1, -1, -1):
c = _[a]
l = c[0]
if l in ["move", "down", "up"]:
value = c[4] or ""
if not value.startswith(r):
_.pop(a)
return _
t = 0
n = 0
r = []
s = 0
if len(path) <= 0:
return []
o = None
_ = None
a = BGAB(path)
c = len(a)
for l in range(0 if c < 300 else c - 300, c):
u = a[l]
h = u[0]
if h in ["down", "move", "up", "scroll"]:
if not o:
o = u
_ = u
r.append([h, [u[1] - t, u[2] - n], BFIQ(u[3] - s if s else s)])
t = u[1]
n = u[2]
s = u[3]
elif h in ["blur", "focus", "unload"]:
r.append([h, BFIQ(u[1] - s if s else s)])
s = u[1]
return r
def process(prepared_path: list):
h = {
"move": 0,
"down": 1,
"up": 2,
"scroll": 3,
"focus": 4,
"blur": 5,
"unload": 6,
"unknown": 7,
}
def p(e, t):
n = bin(e)[2:]
r = ""
i = len(n) + 1
while i <= t:
i += 1
r += "0"
return r + n
def d(e):
t = []
n = len(e)
r = 0
while r < n:
i = e[r]
s = 0
while True:
if s >= 16:
break
o = r + s + 1
if o >= n:
break
if e[o] != i:
break
s += 1
r += 1 + s
_ = h[i]
if s != 0:
t.append(_ | 8)
t.append(s - 1)
else:
t.append(_)
a = p(n | 32768, 16)
c = ""
for l in range(len(t)):
c += p(t[l], 4)
return a + c
def g(e, tt):
def temp1(e1):
n = len(e)
r = 0
i = []
while r < n:
s = 1
o = e[r]
_ = abs(o)
while True:
if n <= r + s:
break
if e[r + s] != o:
break
if (_ >= 127) or (s >= 127):
break
s += 1
if s > 1:
i.append((49152 if o < 0 else 32768) | s << 7 | _)
else:
i.append(o)
r += s
return i
e = temp1(e)
r = []
i = []
def n(e, t):
return 0 if e == 0 else math.log(e) / math.log(t)
for temp in e:
t = math.ceil(n(abs(temp) + 1, 16))
if t == 0:
t = 1
r.append(p(t - 1, 2))
i.append(p(abs(temp), t * 4))
s = "".join(r)
o = "".join(i)
def temp2(t):
return t != 0 and t >> 15 != 1
def temp3(e1):
n = []
def temp(e2):
if temp2(e2):
n.append(e2)
for r in range(len(e1)):
temp(e1[r])
return n
def temp4(t):
if t < 0:
return "1"
else:
return "0"
if tt:
n = []
e1 = temp3(e)
for r in range(len(e1)):
n.append(temp4(e1[r]))
n = "".join(n)
else:
n = ""
return p(len(e) | 32768, 16) + s + o + n
def u(e):
t = ""
n = len(e) // 6
for r in range(n):
t += "()*,-./0123456789:?@ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~"[
int(e[6 * r : 6 * (r + 1)], 2)
]
return t
t = []
n = []
r = []
i = []
for a in range(len(prepared_path)):
_ = prepared_path[a]
a = len(_)
t.append(_[0])
n.append(_[1] if a == 2 else _[2])
if a == 3:
r.append(_[1][0])
i.append(_[1][1])
c = d(t) + g(n, False) + g(r, True) + g(i, True)
l = len(c)
if l % 6 != 0:
c += p(0, 6 - l % 6)
return u(c)
def postprocess(e, t, n):
i = 0
s = e
o = t[0]
_ = t[2]
a = t[4]
while True:
r = n[i : i + 2]
if not r:
break
i += 2
c = int(r, 16)
l = chr(c)
u = (o * c * c + _ * c + a) % len(e)
s = s[:u] + l + s[u:]
return s
return postprocess(process(preprocess(path)), c, s)
def aes_encrypt(self, content: str):
cipher = Cipher(
algorithms.AES(self.aeskey.encode()), modes.CBC(b"0000000000000000")
)
encryptor = cipher.encryptor()
padder = padding.PKCS7(128).padder()
padded_data = padder.update(content.encode())
padded_data += padder.finalize()
ct = encryptor.update(padded_data) + encryptor.finalize()
return ct
def get_c_s(self):
o = {
"gt": self.gt,
"challenge": self.challenge,
"offline": False,
"new_captcha": True,
"product": "embed",
"width": "300px",
"https": True,
"protocol": "https://",
}
o.update(self.get_type())
o.update(
{
"cc": 16,
"ww": True,
"i": "-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1",
}
)
o = json.dumps(o, separators=(",", ":"))
# print(o)
ct = self.aes_encrypt(o)
s = []
for byte in ct:
s.append(byte)
i = self.encode(s)
r = self.enc_key
w = i + r
params = {
"gt": self.gt,
"challenge": self.challenge,
"lang": "zh-cn",
"pt": 0,
"client_type": "web",
"callback": "geetest_" + str(int(round(time.time() * 1000))),
"w": w,
}
resp = self.session.get("https://api.geetest.com/get.php", params=params).text
# print(resp)
data = json.loads(resp[22:-1])["data"]
self.c = data["c"]
self.s = data["s"]
return data["c"], data["s"]
def gettype(self):
url = f"https://api.geetest.com/gettype.php?gt={self.gt}&callback=geetest_{str(int(round(time.time() * 1000)))}"
return self.session.get(url).text
def ajax(self):
def transform(e, t, n):
if not t or not n:
return e
o = 0
i = list(e)
s = t[0]
a = t[2]
b = t[4]
while o < len(n):
r = n[o : o + 2]
o += 2
c = int(r, 16)
l = chr(c)
u = (s * c * c + a * c + b) % len(i)
i.insert(u, l)
return "".join(i)
mouse_path = [
["move", 385, 313, 1724572150164, "pointermove"],
["move", 385, 315, 1724572150166, "pointermove"],
["move", 386, 315, 1724572150174, "pointermove"],
["move", 387, 315, 1724572150182, "pointermove"],
["move", 387, 316, 1724572150188, "pointermove"],
["move", 388, 316, 1724572150204, "pointermove"],
["move", 388, 317, 1724572150218, "pointermove"],
["down", 388, 317, 1724572150586, "pointerdown"],
["focus", 1724572150587],
["up", 388, 317, 1724572150632, "pointerup"],
]
tt = transform(
self.encode_mouse_path(mouse_path, self.c, self.s), self.c, self.s
)
rp = self.MD5(self.gt + self.challenge + self.s)
temp1 = (
""""lang":"zh-cn","type":"fullpage","tt":"%s","light":"DIV_0","s":"c7c3e21112fe4f741921cb3e4ff9f7cb","h":"321f9af1e098233dbd03f250fd2b5e21","hh":"39bd9cad9e425c3a8f51610fd506e3b3","hi":"09eb21b3ae9542a9bc1e8b63b3d9a467","vip_order":-1,"ct":-1,"ep":{"v":"9.1.9-dbjg5z","te":false,"me":true,"ven":"Google Inc. (Intel)","ren":"ANGLE (Intel, Intel(R) Iris(R) Xe Graphics (0x0000A7A0) Direct3D11 vs_5_0 ps_5_0, D3D11)","fp":["scroll",0,1602,1724571628498,null],"lp":["up",386,217,1724571629854,"pointerup"],"em":{"ph":0,"cp":0,"ek":"11","wd":1,"nt":0,"si":0,"sc":0},"tm":{"a":1724571567311,"b":1724571567549,"c":1724571567562,"d":0,"e":0,"f":1724571567312,"g":1724571567312,"h":1724571567312,"i":1724571567317,"j":1724571567423,"k":1724571567330,"l":1724571567423,"m":1724571567545,"n":1724571567547,"o":1724571567569,"p":1724571568259,"q":1724571568259,"r":1724571568261,"s":1724571570378,"t":1724571570378,"u":1724571570380},"dnf":"dnf","by":0},"passtime":1600,"rp":"%s","""
% (tt, rp)
)
r = "{" + temp1 + '"captcha_token":"1198034057","du6o":"eyjf7nne"}'
# print(r)
ct = self.aes_encrypt(r)
s = [byte for byte in ct]
w = self.encode(s)
params = {
"gt": self.gt,
"challenge": self.challenge,
"lang": "zh-cn",
"pt": 0,
"client_type": "web",
"callback": "geetest_" + str(int(round(time.time() * 1000))),
"w": w,
}
resp = self.session.get("https://api.geetest.com/ajax.php", params=params).text
return json.loads(resp[22:-1])["data"]
def get_pic(self, retry):
params = {
"type": "click",
"gt": self.gt,
"challenge": self.challenge,
"lang": "zh-cn",
"callback": "geetest_" + str(int(round(time.time() * 1000))),
}
if retry == 0:
url = "https://api.geevisit.com/get.php"
params.update(
{
"is_next": "true",
"https": "true",
"protocol": "https://",
"offline": "false",
"product": "float",
"api_server": "api.geevisit.com",
"isPC": True,
"autoReset": True,
"width": "100%",
}
)
else:
url = "https://api.geetest.com/refresh.php"
resp = self.session.get(url, params=params).text
data = json.loads(resp[22:-1])["data"]
self.pic_path = data["pic"]
pic_url = "https://" + data["image_servers"][0][:-1] + data["pic"]
return data["pic_type"], self.session.get(pic_url).content
def verify(self, points: list):
u = self.enc_key
o = {
"lang": "zh-cn",
"passtime": 1600,
"a": ",".join(points),
"pic": self.pic_path,
"tt": self.encode_mouse_path(self.mouse_path, self.c, self.s),
"ep": {
"ca": [
{"x": 524, "y": 209, "t": 0, "dt": 1819},
{"x": 558, "y": 299, "t": 0, "dt": 428},
{"x": 563, "y": 95, "t": 0, "dt": 952},
{"x": 670, "y": 407, "t": 3, "dt": 892},
],
"v": "3.1.0",
"$_FB": False,
"me": True,
"tm": {
"a": 1724585496403,
"b": 1724585496605,
"c": 1724585496613,
"d": 0,
"e": 0,
"f": 1724585496404,
"g": 1724585496404,
"h": 1724585496404,
"i": 1724585496404,
"j": 1724585496404,
"k": 0,
"l": 1724585496413,
"m": 1724585496601,
"n": 1724585496603,
"o": 1724585496618,
"p": 1724585496749,
"q": 1724585496749,
"r": 1724585496751,
"s": 1724585498068,
"t": 1724585498068,
"u": 1724585498069,
},
},
"h9s9": "1816378497",
}
o["rp"] = self.MD5(self.gt + self.challenge + str(o["passtime"]))
o = json.dumps(o, separators=(",", ":"))
# print(o)
ct = self.aes_encrypt(o)
s = []
for byte in ct:
s.append(byte)
p = self.encode(s)
w = p + u
params = {
"gt": self.gt,
"challenge": self.challenge,
"lang": "zh-cn",
"pt": 0,
"client_type": "web",
"w": w,
}
resp = self.session.get("https://api.geevisit.com/ajax.php", params=params).text
return resp[1:-1]