Post

HackTheBox Brevi Moduli Writeup

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

Server Script

server.py

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
from Crypto.Util.number import isPrime, getPrime, bytes_to_long
from Crypto.PublicKey import RSA

rounds = 5
e = 65537

for i in range(rounds):
    print('*'*10, f'Round {i+1}/{rounds}', '*'*10)

    pumpkin1 = getPrime(110)
    pumpkin2 = getPrime(110)
    n = pumpkin1 * pumpkin2
    large_pumpkin = RSA.construct((n, e)).exportKey()
    print(f'\n🎃Can you crack this pumpkin🎃?\n{large_pumpkin.decode()}\n')

    assert isPrime(_pmp1 := int(input('enter your first pumpkin = '))), exit()
    assert isPrime(_pmp2 := int(input('enter your second pumpkin = '))), exit()

    if n != _pmp1 * _pmp2:
        print('wrong! bye...')
        exit()

    print()

print(open('flag.txt').read())

Proof of Concept (PoC)

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
from pwn import *
from Crypto.PublicKey import RSA
import re
import subprocess

def get_sage_factors(n):
    with open('factor.sage', 'w') as f:
        f.write(f"n = {n}\nF = factor(n)\nprint(F[0][0])\nprint(F[1][0])")
    subprocess.run(['sage', '--preparse', 'factor.sage'])
    result = subprocess.run(['sage', 'factor.sage.py'], capture_output=True, text=True)
    lines = result.stdout.strip().split('\n')
    return int(lines[0]), int(lines[1])

def solve_challenge():
    try:
        conn = remote('94.237.59.119', 39188)
        for round_num in range(5):
            print(f"\nStarting Round {round_num + 1}/5")
            conn.recvuntil(b'Round')
            line = conn.recvline().decode()
            print(f"Current round: {line.strip()}")
            data = conn.recvuntil(b'enter your first pumpkin = ').decode()
            match = re.search('-----BEGIN PUBLIC KEY-----(.*?)-----END PUBLIC KEY-----', data, re.DOTALL)
            if not match:
                raise ValueError("Could not find PUBLIC KEY in response")
            pem = match.group(0)
            key = RSA.importKey(pem.encode())
            n = key.n
            print(f'n = {n}')
            p, q = get_sage_factors(n)
            print(f'Factors found: p = {p}, q = {q}')
            print(f'Verifying: {p} * {q} == {n}')
            if p * q != n:
                raise ValueError("Factorization verification failed!")
            conn.sendline(str(p).encode())
            print("Sent first factor")
            conn.recvuntil(b'enter your second pumpkin = ')
            conn.sendline(str(q).encode())
            print("Sent second factor")
            response = conn.recvline()
            print(response.decode().strip())
        remaining = conn.recvall(timeout=1)
        if remaining:
            print(remaining.decode().strip())  
    except Exception as e:
        print(f'Error occurred: {str(e)}')
    finally:
        conn.close()

if __name__ == '__main__':
    solve_challenge()

Summary

Brevi Moduli on Hack The Box involves cracking RSA keys by factoring small modulus values across multiple rounds. Each round gives a 220-bit modulus $n = p \times q$, requiring the client to factorize $n$ and submit $p$ and $q$ to verify correctness. The poc uses SageMath for rapid factorization. After completing all rounds, the server reveals the flag.

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