Post

HackTheBox signup Challenge

Explore the basics of cybersecurity in the signup Challenge on Hack The Box. This medium-level Challenge introduces encryption reversal and file handling concepts in a clear and accessible way, perfect for beginners.

https://app.hackthebox.com/challenges/236

Description

The aliens attacked our territory and stole our necessary supplies and kept them in a secure manner. We can get them back, but it requires a lot of data samples. Fortunately, we have some stuff to get back what we need. But, are we lucky enough?!

Exploitation

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
#!/usr/bin/env python3
from hashlib import sha512
from Crypto.Util.number import long_to_bytes, bytes_to_long

def parse_signatures(data):
    signatures = {}
    current_msg = None
    for line in data.split('\n'):
        if 'message :' in line:
            current_msg = line.split(':')[1].strip()
        elif 'signature:' in line and current_msg:
            sig = eval(line.split(':')[1].strip())
            signatures[current_msg] = sig
    return signatures

def find_duplicate_r(signatures):
    r_values = {}
    for msg, (r, s) in signatures.items():
        if r in r_values:
            return (r_values[r], msg)
        r_values[r] = msg
    return None

def get_message_hash(message):
    return int(sha512(message.encode('utf-8')).hexdigest(), 16)

def extended_gcd(a, b):
    if a == 0:
        return b, 0, 1
    gcd, x1, y1 = extended_gcd(b % a, a)
    x = y1 - (b // a) * x1
    y = x1
    return gcd, x, y

def mod_inverse(a, m):
    _, x, _ = extended_gcd(a, m)
    return (x % m + m) % m

def recover_private_key(msg1, sig1, msg2, sig2, q):
    r = sig1[0]
    s1 = sig1[1]
    s2 = sig2[1]
    h1 = get_message_hash(msg1)
    h2 = get_message_hash(msg2)
    numerator = (h1 - h2) % q
    denominator = (s1 - s2) % q
    k = (numerator * mod_inverse(denominator, q)) % q
    x = ((s1 * k - h1) * mod_inverse(r, q)) % q
    return x

def repeating_xor_key(message, key):
    repeation = 1 + (len(message) // len(key))
    key = key * repeation
    key = key[:len(message)]
    return bytes([c ^ k for c, k in zip(message, key)])

def main():
    q = 82349764091980216703243528787846721157571379253101971061732427939554681522787
    encrypted_flag = "caaa08c4332e5701a9105ab701cc830b9ddbe18f6612c999f82a344bdc597819fba00f81772e4001bc584cff06d287089d8085a3123bdca5e7706612d7641f66a2b6228a67336c60975719ef04e1b55edad4e6850126ee92bc25692bd15e274db3b214973f224001af5f46bb40d2930cd69bae"
    sample_data = """********************************************************************************
message : EISZZOL199OKHQB4JMJB7A3Z1W9S0P0ENI98V7RFS8K9RPYQ1V
signature: (14238399380669249177320087107027881078478542661146360644630244485798709030798, 33299491256343856509045723633358260063303030066061530037315886172050511280880)
********************************************************************************
message : 2XKSQ0LYL0ASEKH5ROEB02AKNEKGRWEQCMBE6UUCJO1GK0MXP5
signature: (14238399380669249177320087107027881078478542661146360644630244485798709030798, 31010083525559078114799933393024424305929989859345011192619627339807386206438)"""
    signatures = parse_signatures(sample_data)
    dup_result = find_duplicate_r(signatures)
    if not dup_result:
        print("No duplicate r values found!")
        return
    msg1, msg2 = dup_result
    sig1 = signatures[msg1]
    sig2 = signatures[msg2]
    print(f"Found messages with same r value:")
    print(f"Message 1: {msg1}")
    print(f"Message 2: {msg2}")
    private_key = recover_private_key(msg1, sig1, msg2, sig2, q)
    print(f"Recovered private key: {private_key}")
    key_bytes = long_to_bytes(private_key)
    flag_bytes = bytes.fromhex(encrypted_flag)
    decrypted = repeating_xor_key(flag_bytes, key_bytes)
    print(f"Decrypted flag: {decrypted.decode()}")

if __name__ == "__main__":
    main()

Summary

The Signup Challenge on Hack The Box is a medium-level cryptography challenge that involves exploiting vulnerabilities in ECDSA signatures due to repeated nonce values, allowing participants to recover the private key. By analyzing multiple signed messages with the same r value, attackers can solve for the private key using modular arithmetic. Once the key is obtained, it is used to decrypt an XOR-encrypted flag, demonstrating the critical risks of nonce reuse in digital signature schemes and the importance of implementing secure randomness in cryptographic applications.

This post is licensed under CC BY 4.0 by the author.