132 lines
2.7 KiB
Python
132 lines
2.7 KiB
Python
#!/usr/bin/env python3
|
|||
|
|
from fastecdsa.curve import Curve
|
||
|
|
from fastecdsa.point import Point
|
||
|
|
from base64 import urlsafe_b64decode, urlsafe_b64encode
|
||
|
|
from zlib import crc32
|
||
|
|
|
||
|
|
import requests
|
||
|
|
import json
|
||
|
|
import re
|
||
|
|
import sys
|
||
|
|
import time
|
||
|
|
|
||
|
|
HOST = sys.argv[1]
|
||
|
|
PORT = 14000
|
||
|
|
|
||
|
|
url = f"http://{HOST}:{PORT}"
|
||
|
|
|
||
|
|
r = requests.get(f"{url}/params").text
|
||
|
|
r = r.replace("<pre>", "").replace("</pre>", "")
|
||
|
|
params = json.loads(r)
|
||
|
|
# print(params)
|
||
|
|
|
||
|
|
C = Curve(
|
||
|
|
"burvesigner",
|
||
|
|
params["p"],
|
||
|
|
params["a"],
|
||
|
|
params["b"],
|
||
|
|
params["n"],
|
||
|
|
params["G"][0],
|
||
|
|
params["G"][1],
|
||
|
|
)
|
||
|
|
G = C.G
|
||
|
|
Y = Point(params["Y"][0], params["Y"][1], C)
|
||
|
|
|
||
|
|
b64p = lambda x: x + b"=" * (-len(x) % 4)
|
||
|
|
b64u = lambda x: x.rstrip(b"=")
|
||
|
|
b64e = lambda x: b64u(urlsafe_b64encode(x))
|
||
|
|
b64d = lambda x: urlsafe_b64decode(b64p(x))
|
||
|
|
|
||
|
|
|
||
|
|
def get_token():
|
||
|
|
r = requests.post(url, data={"username": "guest", "password": "guest"}).cookies
|
||
|
|
return r["token"]
|
||
|
|
|
||
|
|
|
||
|
|
token1 = get_token()
|
||
|
|
token2 = get_token()
|
||
|
|
# print(token1)
|
||
|
|
# print(token2)
|
||
|
|
|
||
|
|
sig1 = token1.split(".")[1]
|
||
|
|
sig2 = token2.split(".")[1]
|
||
|
|
|
||
|
|
t = 112 // 8
|
||
|
|
shift_u = pow(2, 112 - 64)
|
||
|
|
|
||
|
|
|
||
|
|
def from_bytes(data):
|
||
|
|
return int.from_bytes(data, "little")
|
||
|
|
|
||
|
|
|
||
|
|
def to_bytes(num):
|
||
|
|
return int.to_bytes(num, t, "little")
|
||
|
|
|
||
|
|
|
||
|
|
sig1dec = urlsafe_b64decode(sig1)
|
||
|
|
arr1 = [sig1dec[t * i : t * (i + 1)] for i in range(3)]
|
||
|
|
Rx1, Ry1, s1 = map(from_bytes, arr1)
|
||
|
|
|
||
|
|
sig2dec = urlsafe_b64decode(sig2)
|
||
|
|
arr2 = [sig2dec[t * i : t * (i + 1)] for i in range(3)]
|
||
|
|
Rx2, Ry2, s2 = map(from_bytes, arr2)
|
||
|
|
|
||
|
|
R1 = Point(Rx1, Ry1, C)
|
||
|
|
R2 = Point(Rx2, Ry2, C)
|
||
|
|
|
||
|
|
# bf diff
|
||
|
|
for bf in range(1, 2**20):
|
||
|
|
diff = bf * shift_u
|
||
|
|
if R1 + G * diff == R2:
|
||
|
|
# print(bf, diff)
|
||
|
|
break
|
||
|
|
|
||
|
|
|
||
|
|
def apa(msg):
|
||
|
|
return crc32(msg)
|
||
|
|
|
||
|
|
|
||
|
|
def fake_sign(msg, x):
|
||
|
|
k = 555555
|
||
|
|
R = k * C.G
|
||
|
|
s = (apa(msg) - x * R.x) * pow(k, -1, C.q) % C.q
|
||
|
|
sig = b"".join(map(to_bytes, [R.x, R.y, s]))
|
||
|
|
return urlsafe_b64encode(sig)
|
||
|
|
|
||
|
|
|
||
|
|
def dup_verify(msg, sig):
|
||
|
|
assert len(sig) == 4 * t
|
||
|
|
sig = urlsafe_b64decode(sig)
|
||
|
|
arr = [sig[t * i : t * (i + 1)] for i in range(3)]
|
||
|
|
Rx, Ry, s = map(from_bytes, arr)
|
||
|
|
R = Point(Rx, Ry, C)
|
||
|
|
return apa(msg) * C.G == s * R + Y * R.x
|
||
|
|
|
||
|
|
|
||
|
|
payload = b64e(
|
||
|
|
json.dumps(
|
||
|
|
{"user": "admin", "role": "admin", "exp": int(time.time()) + 300}
|
||
|
|
).encode()
|
||
|
|
)
|
||
|
|
|
||
|
|
h1 = apa(token1.split(".")[0].encode())
|
||
|
|
h2 = apa(token2.split(".")[0].encode())
|
||
|
|
h3 = apa(payload)
|
||
|
|
|
||
|
|
k1 = (Rx1 * h2 - Rx1 * s2 * diff - Rx2 * h1) * pow(Rx1 * s2 - s1 * Rx2, -1, C.q) % C.q
|
||
|
|
priv = (h1 - s1 * k1) * pow(Rx1, -1, C.q) % C.q
|
||
|
|
sig3 = fake_sign(payload, priv)
|
||
|
|
# print(k1, priv, to_bytes(priv))
|
||
|
|
|
||
|
|
token3 = payload + b"." + sig3
|
||
|
|
token3 = token3.decode()
|
||
|
|
# print(token3)
|
||
|
|
|
||
|
|
r = requests.get(url, cookies={"token": token3}).text
|
||
|
|
if "flashes" in r:
|
||
|
|
print("failed")
|
||
|
|
exit(1)
|
||
|
|
|
||
|
|
flag = re.findall(r'Welcome, admin! (.+)</p>', r)[0]
|
||
|
|
print(flag)
|