-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathapp.py
More file actions
137 lines (114 loc) ยท 6.01 KB
/
Copy pathapp.py
File metadata and controls
137 lines (114 loc) ยท 6.01 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
import streamlit as st
import base64
import json
import requests
import cv2
import numpy as np
from PIL import Image
from io import BytesIO
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
import time
import uuid
st.set_page_config(page_title="EpCube Token Generator", page_icon="๐")
st.caption("โ ๏ธ This site does not store your credentials. Full source code is available on GitHub.")
st.title("๐ EpCube Token Generator")
st.markdown("""
**๐ฎ๐น Istruzioni**
Inserisci l'email e la password che usi per accedere all'app EpCube.
Se il login fallisce, riprova: il CAPTCHA puรฒ non riuscire al primo tentativo.
**๐ฌ๐ง Instructions**
Enter the email and password you use to log into the EpCube mobile app.
If login fails, try again: CAPTCHA may fail on first attempt.
""")
region = st.selectbox("๐ Regione / Region", options=["EU", "US", "JP"], index=0)
email = st.text_input("๐ง Email", value="", placeholder="es. nome@email.com")
password = st.text_input("๐ Password", type="password", placeholder="Inserisci la password / Enter password")
if st.button("๐ Genera Token / Generate Token"):
if not email or not password:
st.error("โ Inserisci email e password / Please enter both email and password.")
else:
try:
BASE_URLS = {
"EU": "https://monitoring-eu.epcube.com/api/",
"US": "https://epcube-monitoring.com/app-api/",
"JP": "https://monitoring-jp.epcube.com/api/"
}
BASE_URL = BASE_URLS[region]
with st.spinner("๐งฉ Solving CAPTCHA..."):
start_time = time.perf_counter()
client_uid = str(uuid.uuid4())
headers = {
"User-Agent": "ReservoirMonitoring/2.1.0 (iPhone; iOS 18.3.2; Scale/3.00)",
"Accept": "*/*",
"Content-Type": "application/json",
"Accept-Encoding": "gzip, deflate, br",
"Accept-Language": "it-IT"
}
def decode_base64_image(b64):
image_data = base64.b64decode(b64)
pil_image = Image.open(BytesIO(image_data))
return cv2.cvtColor(np.array(pil_image), cv2.COLOR_RGB2BGR)
def encrypt_point_json(x, y, secret_key):
data = json.dumps({"x": float(x), "y": float(y)}, separators=(",", ":")).encode("utf-8")
cipher = AES.new(secret_key.encode("utf-8"), AES.MODE_ECB)
return base64.b64encode(cipher.encrypt(pad(data, AES.block_size))).decode("utf-8")
def generate_captcha_verification(token, x, y, secret_key):
raw = f"{token}---{json.dumps({'x': float(x), 'y': float(y)}, separators=(',', ':'))}".encode("utf-8")
cipher = AES.new(secret_key.encode("utf-8"), AES.MODE_ECB)
return base64.b64encode(cipher.encrypt(pad(raw, AES.block_size))).decode("utf-8")
#st.write("๐ก Richiesta a:", f"{BASE_URL}/open/common/captcha/get")
r = requests.post(f"{BASE_URL}/open/common/captcha/get",
json={"clientUid": client_uid}, headers=headers)
if r.status_code != 200:
st.error(f"โ Errore HTTP: {r.status_code}")
st.text(r.text)
st.stop()
try:
r_json = r.json()
except Exception as ex:
st.error("โ La risposta non รจ un JSON valido.")
st.text(r.text)
st.stop()
if "data" not in r_json or "repData" not in r_json["data"]:
st.error("โ Il server non ha restituito repData.")
st.text(json.dumps(r_json, indent=2))
st.stop()
rep_data = r_json["data"]["repData"]
# Decodifica immagini CAPTCHA
original = decode_base64_image(rep_data["originalImageBase64"])
puzzle = decode_base64_image(rep_data["jigsawImageBase64"])
secret_key = rep_data["secretKey"]
captcha_token = rep_data["token"]
bg_gray = cv2.cvtColor(original, cv2.COLOR_BGR2GRAY)
piece_gray = cv2.cvtColor(puzzle, cv2.COLOR_BGR2GRAY)
if piece_gray.shape[0] > bg_gray.shape[0] or piece_gray.shape[1] > bg_gray.shape[1]:
bg_gray, piece_gray = piece_gray, bg_gray
res = cv2.matchTemplate(bg_gray, piece_gray, cv2.TM_CCOEFF_NORMED)
_, _, _, max_loc = cv2.minMaxLoc(res)
x = float(max_loc[0])
y = 5
point_json = encrypt_point_json(x, y, secret_key)
check = requests.post(
f"{BASE_URL}/open/common/captcha/check",
json={"clientUid": client_uid, "token": captcha_token, "pointJson": point_json},
headers=headers
).json()
if check["data"]["repData"]["result"]:
captcha_verification = generate_captcha_verification(captcha_token, x, y, secret_key)
login = requests.post(
f"{BASE_URL}/open/common/login",
json={"userName": email, "password": password, "captchaVerification": captcha_verification},
headers=headers
).json()
elapsed = time.perf_counter() - start_time
token = login.get("data", {}).get("token")
if token:
st.success(f"โ
Token generato in {elapsed:.2f}s / Token generated in {elapsed:.2f}s")
st.code(token, language="text")
else:
st.error(f"โ Login fallito / Login failed: {login}")
else:
st.error("โ CAPTCHA non riuscito / CAPTCHA failed.")
except Exception as e:
st.exception(e)