← Back to Writeups
CUSTOMEasyCrypto

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

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

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

Platform: CUSTOM | Category: Crypto | Type: Challenge | Difficulty: Easy | OS: N/A | **Author: XESXOR Techniques: FactorDB modulus lookup, RSA decryption with known factors, Modular inverse calculation

Summary

Walkthrough of the CUSTOM Crypto Ничего особенного (Nothing Special). Detailed walkthrough.

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) ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Key Takeaways / Lessons

  • Mastering FactorDB modulus lookup, RSA decryption with known factors, Modular inverse calculation was key to this challenge.
  • Always check for common misconfigurations and verify assumptions.

Crafted by XESXOR Research • 2026-01-02 • CUSTOM • Ничего особенного (Nothing Special) • Difficulty: Easy