Crack the Power writeup

Descripción

We received an encrypted message. The modulus is built from primes large enough that factoring them isn’t an option, at least not today. See if you can make sense of the numbers and reveal the flag.

Download the message.

Crack the Power writeup

Al descargar y abrir el mensaje veremos el siguiente contenido:

Tenemos tres variables, n, e y c, lo cual nos da a entender que el cifrado es RSA. Cada una de ellas se corresponde con lo siguiente:

El cifrado se realiza de la siguiente forma:

C = M^e mod n

Y el descifrado para obtener el mensaje en claro (M) de esta:

M = C^d mod n

Como no tenemos d, no podemos utilizar el procedimiento habitual de descifrado. Sin embargo, dado que e es pequeño, podemos comprobar si M^e<n. Si se cumple, el módulo no tiene ningún efecto y podemos recuperar M calculando la raíz e-ésima de c. Para ello, antes tenemos que realizar dos comprobaciones:

Ambas comprobaciones las realizaremos con el siguiente código:

import gmpy2

#Contenido del archivo
n = 410664186165191791402826020648772079727855370225121168329489558023676206903110917122249911944501914058167574154300515578639528319920053023867482073692484985287827372248686968550452147219495058219737726533198589146788106207104006141113375574066854852611259725786317821883172497842657985257908701482139090568993822965683214349918502719101583356882168338270447984584381812927858227415072514189838197665563968909219013964220237934124402478909876364171409578837503118525132848891505287317986848688438750873278654357181872934401664809196436196103395671068981692006881025785118124735403009761732676194557783341186696317289217601680762240946756099165359859285900990663149297784065325172930606950668533524438921457116354261722563783316401034088432522913099965625002265981169229586378601077820521982226216733874547440407450338648780337291742094848216093949046938054996321130253196977418170117347647315719448397122004966163394965123751185910309725139116961163368621449406198577849587926254211380551265442088456309106778455980283046226445371066856262215933615411567261989837352437927401685169541910706297673710978352664847844643089079402646094504545790754030992062817610552755382423490304761138904591244735268207666957111641348148546651263055711
e = 20
c = 640637430810406857500566702096274079868087131935153057078985716461078483409793615804311883296591203324452249008450521032645267345512046769994383635285244380705157432625570066632528925314552900669814963219369331313157534607620352061314683496525883016843153241425770911702563380247302073740850825452371063276867610414725164654421304873071774234683226777641240092032528116047489137507373500064099947304524782898265669628686091404044097235795818651902023996906668123465373292221934136216954999213086853380479136606214034827032162211811911299453884553459883192781319337391984912950371275232374262114220706295073924345743106413419931715570201067076471272561731959500262271837841417300230554359594018424813861589485400512131504027368400263321851762034719595379735999122340323973277638235482616225404363214027767922993075345559200374830345517529445328472713066257434684134913873359589576414681791333170123047390862933633440111883394760439698156048278154619895786259579727797488066274962774692244105308866923365722966155030681035814505674226605348055192323888099731031683511808581367884577911318683020417249790405911629045010877656025044271667195964670746001

m, exact = gmpy2.iroot(c, e)


#Comprobaciones previas
print("El módulo nunca se llega a usar (M^e < n):", pow(m, e) < n)
print("Es una raíz exacta (M^e=c):", exact)

Al ejecutar el archivo obtendremos el siguiente resultado:

El módulo nunca se llega a usar (M^e < n): True
Es una raíz exacta (M^e=c): True

Con lo cual, podemos descartar el módulo de la ecuación, obteniendo la siguiente:

C = M^e

Ahora despejar M se vuelve mucho más sencillo:

M = e √ c

Y en este caso, tenemos tanto e como c, por lo que podemos construir el siguiente programa en python que nos devuelva el contenido del mensaje sin encriptar. El problema es que lo obtendremos como un entero, por lo que será necesario codificarlo a UTF-8:

import gmpy2

#Contenido del archivo
n = 410664186165191791402826020648772079727855370225121168329489558023676206903110917122249911944501914058167574154300515578639528319920053023867482073692484985287827372248686968550452147219495058219737726533198589146788106207104006141113375574066854852611259725786317821883172497842657985257908701482139090568993822965683214349918502719101583356882168338270447984584381812927858227415072514189838197665563968909219013964220237934124402478909876364171409578837503118525132848891505287317986848688438750873278654357181872934401664809196436196103395671068981692006881025785118124735403009761732676194557783341186696317289217601680762240946756099165359859285900990663149297784065325172930606950668533524438921457116354261722563783316401034088432522913099965625002265981169229586378601077820521982226216733874547440407450338648780337291742094848216093949046938054996321130253196977418170117347647315719448397122004966163394965123751185910309725139116961163368621449406198577849587926254211380551265442088456309106778455980283046226445371066856262215933615411567261989837352437927401685169541910706297673710978352664847844643089079402646094504545790754030992062817610552755382423490304761138904591244735268207666957111641348148546651263055711
e = 20
c = 640637430810406857500566702096274079868087131935153057078985716461078483409793615804311883296591203324452249008450521032645267345512046769994383635285244380705157432625570066632528925314552900669814963219369331313157534607620352061314683496525883016843153241425770911702563380247302073740850825452371063276867610414725164654421304873071774234683226777641240092032528116047489137507373500064099947304524782898265669628686091404044097235795818651902023996906668123465373292221934136216954999213086853380479136606214034827032162211811911299453884553459883192781319337391984912950371275232374262114220706295073924345743106413419931715570201067076471272561731959500262271837841417300230554359594018424813861589485400512131504027368400263321851762034719595379735999122340323973277638235482616225404363214027767922993075345559200374830345517529445328472713066257434684134913873359589576414681791333170123047390862933633440111883394760439698156048278154619895786259579727797488066274962774692244105308866923365722966155030681035814505674226605348055192323888099731031683511808581367884577911318683020417249790405911629045010877656025044271667195964670746001

m, exact = gmpy2.iroot(c, e)


#Comprobaciones previas
print("El módulo nunca se llega a usar (m^e < n):", pow(m, e) < n)
print("Es una raíz exacta (hno hay padding):", exact)


if exact:
    m_bytes = int(m).to_bytes((int(m).bit_length() + 7) // 8, byteorder="big")
    mensaje = m_bytes.decode("utf-8")
    print(mensaje)

Obteniendo así la flag y completando el CTF.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *