← Back to Writeups
CUSTOMEasyCrypto

Ничего особенного (Nothing Special)

XESXOR9/10/20262 min read
#crypto#custom#easy#factordb-modulus-lookup#rsa-decryption-with-known-fact#modular-inverse-calculation

Ничего особенного (Nothing Special)

Platform: hackerlab | Category: Crypto | Type: Challenge | Difficulty: Easy | OS: NA | Author: XESXOR | Date: 2026-01-02 | Status: Solved Techniques: FactorDB modulus lookup, RSA decryption with known factors, Modular inverse calculation

Summary

Ничего особенного (Nothing Special) — hackerlab

Description

Обыкновенная реализация RSA без видимых уязвимостей... Или они все-таки есть?

(An ordinary RSA implementation without visible vulnerabilities... Or are there?)

Analysis

Key Generation Source Code (gen.py)

python
from Crypto.Util.number import getPrime, bytes_to_long
from math import gcd

flag = b"CODEBY{???????????????????}"

m = bytes_to_long(flag)
e = 65537

while True:
    p, q = getPrime(1024), getPrime(1024)
    n, phi = p * q, (p-1) * (q-1)
    if gcd(phi, e) == 1:
        break
‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

c = pow(m, e, n)

print(f"n = {n}")
print(f"e = {e}")
print(f"c = {c}")

RSA Parameters (key.txt)

n = 15360430612195884668505674226320381918816025423409674792639378283651917493564662095392839462768570280688204963687867587119107450770617692216265741475101438908006141086639657319549195208471346757021503258405279036848538487620298374935971042386105752140990313817542782558218726126638092132813167983904390108008435327737975189710851416185214897318087233960475165126758817935351719601177948252794308918244726980044400917760281088072141936954809516779668499304057531735464446988261314507139561002499535818114960847038017448821042494772684216534039163581484460326934555526049210974762066564580982899537315296746870282829017
e = 65537
c = 1491256285226085686080611462534436394708242996098270582046567754972224965119033695760219715986423304961241507616485548629836330764574311108463787749157200309630204195118236839038863198705121448107995400351994929874239442260815545380843831260638279253970650134650588879470252350531416719849751458191011287820528294737197122284186820620482815046862426923319233325486987032280629228239872991776919866826115243577863684772467998968626705298310096374368417600077513507819307209464862337340524066758551533994058022549685305943809319129173122798255064046867622893134212025744669998037984544773340481660247657588558073081228

‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Vulnerability Analysis

At first glance, the implementation looks standard:

  • 2048-bit modulus (1024-bit primes)
  • Standard public exponent e = 65537
  • Correct gcd(phi, e) == 1 check

Key idea: Check the modulus n in public factorization databases.

FactorDB Lookup

A query to the FactorDB API showed that the modulus is already factored:

Status: FF (Fully Factored)

Factors:

p = 92133612143601003460753963400553326313631247291872841467234890871335677358323652121483203255607538607397520559533969068385208282473025726567978148910391235608932737386346886173637063761999297550741949888715388999500504609320713717892572628370857424144201953756512442268141235557845031854215314272175438854889
‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

q = 166719075208457670936880711026162297723745757812858268695795773980561287422477976116460219005091865350450475891287086358438546550026482944367465602068291657209239755271507435690591236270513336877245643027009588412586461222029019395352299823995987298151291208647534045693060467231170009220305398301784616279153

Solution

python
#!/usr/bin/env python3
"""
Ничего особенного (Nothing Special) - hackerlab CTF
RSA with FactorDB-known factorization
"""

from Crypto.Util.number import long_to_bytes
‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

# RSA parameters from key.txt
n = 15360430612195884668505674226320381918816025423409674792639378283651917493564662095392839462768570280688204963687867587119107450770617692216265741475101438908006141086639657319549195208471346757021503258405279036848538487620298374935971042386105752140990313817542782558218726126638092132813167983904390108008435327737975189710851416185214897318087233960475165126758817935351719601177948252794308918244726980044400917760281088072141936954809516779668499304057531735464446988261314507139561002499535818114960847038017448821042494772684216534039163581484460326934555526049210974762066564580982899537315296746870282829017
e = 65537
c = 1491256285226085686080611462534436394708242996098270582046567754972224965119033695760219715986423304961241507616485548629836330764574311108463787749157200309630204195118236839038863198705121448107995400351994929874239442260815545380843831260638279253970650134650588879470252350531416719849751458191011287820528294737197122284186820620482815046862426923319233325486987032280629228239872991776919866826115243577863684772467998968626705298310096374368417600077513507819307209464862337340524066758551533994058022549685305943809319129173122798255064046867622893134212025744669998037984544773340481660247657588558073081228
‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

# Factors from FactorDB (status: FF - Fully Factored)
p = 92133612143601003460753963400553326313631247291872841467234890871335677358323652121483203255607538607397520559533969068385208282473025726567978148910391235608932737386346886173637063761999297550741949888715388999500504609320713717892572628370857424144201953756512442268141235557845031854215314272175438854889
q = 166719075208457670936880711026162297723745757812858268695795773980561287422477976116460219005091865350450475891287086358438546550026482944367465602068291657209239755271507435690591236270513336877245643027009588412586461222029019395352299823995987298151291208647534045693060467231170009220305398301784616279153
‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

# Verify factorization
assert p * q == n, "Factorization error!"

# Calculate private key
phi = (p - 1) * (q - 1)
d = pow(e, -1, phi)

# Decrypt
m = pow(c, d, n)
flag = long_to_bytes(m)

print(f"Flag: {flag.decode()}")

Why This Works

The flag REDACTED (thanks for factorization) confirms:

  • The author intentionally used an already-factored modulus
  • Or the modulus was added to FactorDB after generation
  • Lesson: never reuse RSA keys and verify their uniqueness

FactorDB Tools

Python API

python
import requests
‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

def check_factordb(n):
    url = f"http://factordb.com/api?query={n}"
    r = requests.get(url)
    data = r.json()
    status = data.get('status')
    # FF = Fully Factored, CF = Composite, no factors known
    if status == 'FF':
        factors = [int(f[0]) for f in data.get('factors', [])]
        return factors
    return None

Online

  • http://factordb.com/
  • Paste n, check status

Related Techniques

  • RsaCtfTool — automatically checks FactorDB
  • Yafu — local factorization for small moduli
  • CADO-NFS — for serious factorization (not needed here) ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍