Factor Master | Tjctf 2022

Fichier(s)

Necessaires

  • Python3 + Pwntools

Flag

tjctf{S0_y0u_r34lly_c4n_F4c7t0r_4ny7th1nG_c36f63cfe73c}

Solution détaillée

Le challenge se décompose en 3 parties : 3 fois le serveur va nous fournir un nombre et nous allons devoir le factoriser en 2 produits de nombres premiers ; à la manière d’un chiffrement RSA.

Commencons directement avec la première étape:

Etape 1 :

def challenge1():
    p = getPrime(44)
    q = getPrime(1024)
    n = p * q
    return [p, q], n

On remarque tous de suite de p est bien plus petit que q . On peut donc facilement trouver les facteurs avec :

  • Pollard Rho
  • ECM factorization

On peut le vérifier avec un tool que j’ai écris : Facto4Ctf

On trouve : Alt text

Etape 2 :

Voici le code :

def challenge2():
    p = getPrime(1024)
    q = p + getRandomInteger(524)
    if q % 2 == 0: q += 1
    while not isPrime(q): q += 2
      n = p * q
    return [p, q], n

q = p + getRandomInteger(524) Nous indique que p et q vont être trés proche . Ainsi une attaque Fermat va être trés éfficace !

On peut ainsi re-tester avec Facto4Ctf :

Alt text

Voici le code pour une factorisation via l’attaque fermat:

def fermat(N):
	a = int(gmpy.root(N,2)[0])+1
	b = a*a -N
	c = int(gmpy.root(b,2)[0])
	not_square = (c*c != b)
	while not_square:
		a = a +1
		b = a*a -N
		c = int(gmpy.root(b,2)[0])
		not_square = (c*c != b)
	p = a-c
	q = q=N//p
	return [p,q]

Etape 3 :

def challenge3():
    small_primes = [n for n in range(2,10000) if isPrime(n)]
    def gen_smooth(N):
        r = 2
        while True:
            p = random.choice(small_primes)
            if (r * p).bit_length() > N:
                return r
            r *= p
    p = 1
    while not isPrime(p):
        p = gen_smooth(1024) + 1
    q = getPrime(1024)
    n = p * q
    return [p, q], n

Tous d’abord , le script stocke tous les nombres premiers allant de 2 à 10000 dans small_primes Puis , il va générer le nombre premier p comme un produit de cette liste et va ajouter 1

On peut donc écrire p comme : p = 2*k + 1 avec k : un produit de petits nombres premiers

Cette écriture nous à permis de comprendre l’attaque Pollard p-1 , grâce à laquelle en utilisant l’exponentiation modulaire : on retrouve un facteur de n

def pollard_p_1(n):
	small_primes = [n for n in range(2,10000) if isPrime(n)]
	x = 2
	for elt in small_primes:
		x*=elt
	for elt in small_primes:
		x*=elt
	for elt in small_primes:
		x*=elt

	q = GCD((pow(2,x,n)-1)%n,n)
	p = n//q

	return [p,q]

Le code final :

Voici l’exploit final pour avoir une version automatiser:

from pwn import *
from factordb.factordb import FactorDB

import gmpy

from sage.all import *
from Crypto.Util.number import isPrime,GCD

from tqdm import tqdm
from math import log

context.log_level = 'critical'

def ecm_factor(N):
	try:
		p = q = None
		p = ecm.find_factor(N)[0]
		q = N // p
		if(p*q != N or p==1 ):
			return None
		else:
			return [p,q]			
	except Exception as ex:
		print(ex)
		return None

def fermat(N):
	a = int(gmpy.root(N,2)[0])+1
	b = a*a -N
	c = int(gmpy.root(b,2)[0])
	not_square = (c*c != b)
	while not_square:
		a = a +1
		b = a*a -N
		c = int(gmpy.root(b,2)[0])
		not_square = (c*c != b)
	p = a-c
	q = q=N//p
	return [p,q]

def pollard_p_1(n):
	small_primes = [n for n in range(2,10000) if isPrime(n)]
	x = 2
	for elt in small_primes:
		x*=elt
	for elt in small_primes:
		x*=elt
	for elt in small_primes:
		x*=elt

	q = GCD((pow(2,x,n)-1)%n,n)
	p = n//q

	return [p,q]


def Challenge(proc,i,facto):
	print('\n\n'+'#'*100)
	print(' [Challenge %s] Getting N ...'%i)
	proc.recvuntil(b'n = ')
	n = proc.recvline().decode().strip()
	print(' [Challenge %s] N = %s'%(i,n))
	print(' [Challenge %s] Factoring using %s method ...'%(i,facto.__name__))
	proc.recvuntil(b'factors = ?')
	res = facto(int(n))
	print(' [Challenge %s] Factors found :'%i)
	print('		> %s'%res[0])
	print('		> %s'%res[1])
	if(res[0] > res[1]):
		return bytes('%s %s'%(res[1],res[0]),'utf-8')
	return bytes('%s %s'%(res[0],res[1]),'utf-8')

proc = remote('tjc.tf',31782)
method = [ecm_factor,fermat,pollard_p_1]
for i in range(1,4):
	proc.sendline(Challenge(proc,i,method[i-1]))

proc.interactive()

Et voici le résultat complet!

root@DESKTOP-HNQJECB: /c
➜   python3 factor_master.py


####################################################################################################
 [Challenge 1] Getting N ...
 [Challenge 1] N = 2049599421257441020570261939966635289544140750291257030231212311711316617526359824013006286571836978353304509480797344618693470124291819006261878268773417597779509550397776302225675954911019411929216419830971899167752724418508389272821125895324832114000483654152570947467200091506316819354994813752087546994721634692766749
 [Challenge 1] Factoring using ecm_factor method ...
 [Challenge 1] Factors found :
        > 17580819592703
        > 116581562676869551828139972476401081363945025691746696650245359275978066697366701647043298737353059992707608935796415715635914698839585872532036923957725556315874655515759553298878819923329294665520046801758416352795286548805471800612450037562178275129545071253268609411264372133157713694454077134180874470883


####################################################################################################
 [Challenge 2] Getting N ...
 [Challenge 2] N = 9297547962477056212001143695050955237572337905646594828890248495088555748318277828660857593007803605697228935865822511657039575850723659589816729063702376237800694547382589634772789490639155783913078716610181918503720512223840306234422205595680736488257716362985134854854815172064022375747998693327616780101119912400487544596714391932840955982661131665078029974287932890053723372472510682190207363741507697210733110537781652013670636218535989669590416979074653294707424278170640534430202354839510102964661513216667587602395311097374701532202643378733309842341194706780621765950892704790354072206330176695156025341559
 [Challenge 2] Factoring using fermat method ...
 [Challenge 2] Factors found :
        > 96423793549502377022485940486123952542789026709961294306340483235741723880389051328464283640634673097714545273681092828725587259441222369855034739461947733827588149250633602918129726244038050840351361307172347056404614749401040512035826268306118310527090689760985744142096250164754234704382420991811035680969
        > 96423793549502377022485940486123952542789026709961294306340483235741723880389051328464283640634673097714545273681092828725587259441222369855034739461995303468352869176326000501860768863145132449343351597329202611272973859285678277908082272807526827370736902494708249100996987317841390658189544420915583266111


####################################################################################################
 [Challenge 3] Getting N ...
 [Challenge 3] N = 144740334774233993681865242632285966435307772766157442849581288037995452984501188206610374158260334026048683086587471158988557400509928466391415415697879103145314312046118208977502636041377409063531401551420096803263897541265828617249275428308533614823068209952328310933029444890047093062077121535217683762599347222895626619254526683833641430414880880898421326366569768509453029302830378853726493607094410280974025012728472607525854261133698490322338846131355419382455968029431142426690463587617400304419810886194981319220521512849775877035226562131639772554504770369137875303472634153532608872895717806623942822573
 [Challenge 3] Factoring using pollard_p_1 method ...
 [Challenge 3] Factors found :
        > 155924691952388179915819801606749589085128764171104017163886680821650803405022993775470571181994307354963544947715597395284265077641225603124992786518816409085431662216897508326089619645181156027351404390771105789097685541148587130612823550543554647341895017016789226210275845498416410020562591097566818225907
        > 928270775859096485189599783992140792517974419829702003344755023732344925605303104148733578577046059920004257976566633925373309746129618414569233262895070375253303560972285525699332944628279692600123812258961632109502555620138730093932994443118092837125122104825930766782986592294822389784869309616612124639
 Wow.

Here's your flag:
tjctf{S0_y0u_r34lly_c4n_F4c7t0r_4ny7th1nG_c36f63cfe73c}