Writeup by IT-Evix for CQFD

crypto network

September 10, 2024

You need to find the flag hidden in this network capture.

The file given is a network capture.When opening the network capture, we notice HTTP communications as well as TLSv1.2 packets.

To investigate more, we click on Analyze > Expert Information:

image

Here we see that 3 TLS packets are described as Server hello, Certificate, Server Key Exchange, Server hello done. So we know there is a certificate exchange but firstly, we will filter these packets:

ssl.handshake.type == 11

Which gives us:

image 1

So we right click on the certificate line and Export Packet Bytes... for the 3 packets. Next, we check what these certificates are associated with:

pub1.der:

image 2

pub2.der:

image 3

pub3.der:

image 4

Here, the certificates that interest us are those of the hosts iluvprimes.com and cryptoftw.fr because the one from the anssi does not seem to be our target (www.anssi.eu).

After that, we use openssl to retrieve the public keys of the certificate of iluvprimes.com and cryptoftw.fr.

$ openssl x509 -inform DER -in pub1.der -pubkey -noout > pub1.key
$ openssl x509 -inform DER -in pub2.der -pubkey -noout > pub3.key

Let’s take a closer look at these public keys. We know they are RSA because it is written in the packet and in the certificate information :

image 5

$ openssl rsa -pubin -in pub1.key -text -noout

image 6

$ openssl rsa -pubin -in pub3.key -text -noout

image 7

Now that we know what the public keys correspond to, we do some research to find out what attack can be used.

We find the common factor attack which corresponds to looking for a common factor by taking advantage of the difficulty for certain systems to generate large random numbers. We create a script for this attack:

import math
from Crypto.PublicKey import RSA
from Crypto.Util.number import inverse

# Load public key from file
def load_public_key(file_path):
    with open(file_path, 'rb') as f:
        public_key = RSA.import_key(f.read())
    return public_key

# Extract public modulus and exponent
def extract_modulus_exponent(public_key):
    modulus = public_key.n  # Modulus
    exponent = public_key.e  # Public exponent
    return modulus, exponent

# Load public keys
public_key_1 = load_public_key('./pub1.key')
public_key_2 = load_public_key('./pub3.key')

# Extract modules and exponents
modulus1, exponent1 = extract_modulus_exponent(public_key_1)
modulus2, exponent2 = extract_modulus_exponent(public_key_2)

# Show modules and exhibitors
print(f"Modulus 1: {modulus1}")
print(f"Exponent 1: {exponent1}")
print(f"Modulus 2: {modulus2}")
print(f"Exponent 2: {exponent2}")

# Calculate the common factor (gcd) between modulus1 and modulus2
p = math.gcd(modulus1, modulus2)

# Check if p is non-trivial
if p == 1:
    print("No common factor between the two modulus.")
else:
    print(f"Common factor found: p = {p}")

# Calculate the second prime factors q1 and q2
q1 = modulus1 // p
q2 = modulus2 // p

# Show factors q1 and q2
print("q1:", q1)
print("q2:", q2)

# Function to generate RSA private key from parameters
def generate_private_key(n, p, q, e):
    phi_n = (p - 1) * (q - 1)
    d = inverse(e, phi_n)
    key = RSA.construct((n, e, d, p, q))
    return key

# Generate private keys for both modules
privkey1 = generate_private_key(modulus1, p, q1, exponent1)
privkey2 = generate_private_key(modulus2, p, q2, exponent2)

# Save private keys in PEM files
with open("priv1.key", "wb") as f:
    f.write(privkey1.export_key())

with open("priv3.key", "wb") as f:
    f.write(privkey2.export_key())

print("Private keys saved as 'priv1.key' and 'priv3.key'")
$ python3 common_factors.py
Modulus 1: 18053343927187441108441676210352812208841821342176375072626907832579120529616542004286898021310125324177396453091146242892059023480248994812385743745829080533443709021801626752988504702779717383968935903480999751947593336274820105521875042566841237938309494595847368546040134225853055300125071970318904115478019359346905077910568516541409230598529104099513308295900154736804341485288504384483587566258326282352342852431455293545691814140471361311559581606313563521176326293297059267560469065513610526391626949122116277529307127764052525170569813954351374019777288115175379547188764678814330441682477499584967168160179
Exponent 1: 65537
Modulus 2: 12862272562103424721436654564272304657609534482185665387600821410880521595524480937003540764964868094076026072506938788276319781278760050706594940055306345783111506068623090529020904720840323597550392798019777140032752947813309214536936857545104051608274551357465157572571547853159799500153864387715109447611346236295086674020094149039310293386230081483725119888010418464290176729751485892981968533726813150894269074250237445299088035980653939821337253721972102525176865299992319914895220563812837475572503917276817276445943174224296660112124422839613356296081387438965212164340903794474969142246462653812069150064113
Exponent 2: 65537
Facteur commun trouvé: p = 102309582252265727725340345451462353412917609251698470327358369038596447497782878994409403649899367357603426088862355403689989422161491768264328621320078645274330159165477896764608597302037237479418618729362585728029980211269117774589439387986392752717360615171973810177719407580656540183624752965381895742303
q1: 176457996697446541797078410681787975133044515403509374804191105369011520443365030282337656325217135953227384636548119123621186869405770201501319516665267152735988889608562764690464368640847985329674996378162898832997914646190946704515696039119406636883505009715464637237568076162984205812746062622257115842093
q2: 125719138705784123981847760107353155221882767209282696996965365992026982759758663118724123157393002768533176626973097645949189824701082982581701050294390522480835951921853654312282010346776587123903192192907425920069889168729347508276355649273626333244122472994469367988621590243736589293453607998476471300271
Private keys saved as 'priv1.key' and 'priv3.key'

We then have two new files priv1.key and priv3.key which are the private keys for the hosts that interest us. We integrate them into Wireshark in the Edit > Preferences > Protocols > TLS > RSA key list tab. Then we click on the plus sign and add the file path to a private key and the same for the second.

Capture_dcran_du_2024-09-10_20-04-13

We filter the positive responses from these servers this time :

image 8

Finally we follow the TLS flows of each of these packets :

image 9

Just read the flag which is in two parts.