Ничего особенного (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 read-only • copy allowedfrom 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 read-only • copy allowed#!/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 read-only • copy allowedimport 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)