Vulnerabilities

Tuesday, November 19, 2013

CSCAMP CTF Quals 2013 - Crypto 400 - [Team SegFault]

We were given two files for the challenge - public key and encrypted message. Reading the public key with openssl we got
[ctf@renorobert 400]$ openssl rsa -in public.pem -pubin -text -noout 
Public-Key: (768 bit)
Modulus:
    00:ca:d9:84:55:7c:97:e0:39:43:1a:22:6a:d7:27:
    f0:c6:d4:3e:f3:d4:18:46:9f:1b:37:50:49:b2:29:
    84:3e:e9:f8:3b:1f:97:73:8a:c2:74:f5:f6:1f:40:
    1f:21:f1:91:3e:4b:64:bb:31:b5:5a:38:d3:98:c0:
    df:ed:00:b1:39:2f:08:89:71:1c:44:b3:59:e7:97:
    6c:61:7f:cc:73:4f:06:e3:e9:5c:26:47:60:91:b5:
    2f:46:2e:79:41:3d:b5
Exponent: 65537 (0x10001)
[ctf@renorobert 400]$ openssl rsa -in public.pem -pubin -text -noout | grep '^ ' | tr -dc '[0-9a-f]'
00cad984557c97e039431a226ad727f0c6d43ef3d418469f1b375049b229843ee9f83b1f97738ac274f5f61f401f21f1913e4b64bb31b55a38d398c0dfed00b1392f0889711c44b359e7976c617fcc734f06e3e95c26476091b52f462e79413db5
Its a RSA-768 and the N value is already factorized. Factors are available publicly
p = 33478071698956898786044169848212690817704794983713768568912431388982883793878002287614711652531743087737814467999489
q = 36746043666799590428244633799627952632279158164343087642676032283815739666511279233373417143396810270092798736308917
Generate private key for p and q values and decrypt the file
sage: p = 33478071698956898786044169848212690817704794983713768568912431388982883793878002287614711652531743087737814467999489
sage: q = 36746043666799590428244633799627952632279158164343087642676032283815739666511279233373417143396810270092798736308917
sage: phi_n = (p-1) * (q-1)
sage: e = 65537
sage: d = inverse_mod(e, phi_n)
sage: d
703813872109751212728960868893055483396831478279095442779477323396386489876250832944220079595968592852532432488202250497425262918616760886811596907743384527001944888359578241816763079495533278518938372814827410628647251148091159553
>>> from Crypto.PublicKey import RSA
>>> keypair = RSA.generate(1024)
>>> keypair.n = 1230186684530117755130494958384962720772853569595334792197322452151726400507263657518745202199786469389956474942774063845925192557326303453731548268507917026122142913461670429214311602221240479274737794080665351419597459856902143413
>>> keypair.e = 65537
>>> keypair.d = 703813872109751212728960868893055483396831478279095442779477323396386489876250832944220079595968592852532432488202250497425262918616760886811596907743384527001944888359578241816763079495533278518938372814827410628647251148091159553
>>> keypair.p = 33478071698956898786044169848212690817704794983713768568912431388982883793878002287614711652531743087737814467999489
>>> keypair.q = 36746043666799590428244633799627952632279158164343087642676032283815739666511279233373417143396810270092798736308917
>>> private = open('private.pem', 'w')
>>> private.write(keypair.exportKey())
>>> private.close()
[ctf@renorobert 400]$ openssl rsautl -decrypt -in message.enc -out /dev/tty -inkey private.pem
F4ct0r!zaTi0N
Flag for the challenge is F4ct0r!zaTi0N

2 comments:

  1. Just wanted to ask about the creation of the key you have use the RSA.generate(1024) command when I use it expects another argument ie a random generator function. Could I ask if you were using pycrypto for this and if so how you were able to get it to use only one argument.

    ReplyDelete
    Replies
    1. Yes, I used PyCrypto version 2.6.0 for this and it worked with one argument.
      >>> from Crypto.PublicKey import RSA
      >>> keypair = RSA.generate(1024)
      >>> dir(keypair)
      ['__doc__', '__eq__', '__getattr__', '__getstate__', '__init__', '__module__', '__ne__', '__repr__', '__setstate__', '_blind', '_decrypt', '_encrypt', '_randfunc', '_sign', '_unblind', '_verify', 'blind', 'can_blind', 'can_encrypt', 'can_sign', 'decrypt', 'encrypt', 'exportKey', 'has_private', 'implementation', 'key', 'keydata', 'publickey', 'sign', 'size', 'unblind', 'validate', 'verify']

      Not sure why its not working for you :(

      Delete