Hoy veremos cómo resolver el nuevo reto de criptografía de la plataforma “Una Al Mes”.

Introducción:

En esta ocasión, nos encontramos ante un reto de criptografía y tenemos que conseguir 3 flags.

Tan solo nos proporcionan un archivo “.py”, cuyo contenido es:

Space_Project_UAM.py

#============================================================================#
#============================SPACE TRIP===============================#
#============================================================================#

import hashlib
from cryptography.fernet import Fernet
import base64

# GLOBALS --v
arcane_loop_trial = True

planets = {
  "Mercurio": 0.24,
  "Venus": 0.62,
  "Marte": 1.88,
  "Júpiter": 11.86,
  "Saturno": 29.46,
  "Urano": 84.01,
  "Neptuno": 164.8,
  
}

def intro_trial():
    print("\n===============================================\n\
    Bienvenidos a este viaje espacial, SUBAN A BORDO !!!!\n")    
    print("Se encuentra en el centro de atención de viajes espaciales")
    print("Aqui podrá consultar las distintas tarifas \n\
relacionadas con la distancia a su destino. \n\
Recuerde que para acceder a su ticket necesita introducir su licencia\n\
=====================================================\n\n")

def menu_trial():
    print("___SPACE TRIP___\n\n\
Menu:\n\
(a) Calcular costo de viaje\n\
(b) [LOCKED] Acceder a ticket de viaje\n\
(c) Ingresar licencia \n\
(d) Salid del centro de atención de viajes espaciales")

    option = input("Seleccione la opción que más desea (a/b/c/d)? ")
    
    if not validar(option):
        print("\n\nOpción incorrecta!\n\n")
        return
    
    if option == "a":
        precio_viaje()
    elif option == "b":
        opcion_bloqueada()
    elif option == "c":
        introducir_licencia()
    elif option == "d":
        global arcane_loop_trial
        arcane_loop_trial = False
        print("Que tenga un buen día!")
    else:
        print("Ha seleccionado una opción incorrecta, por favor")

def validar(opcion_elegida):
    if opcion_elegida == "a" or \
       opcion_elegida == "b" or \
       opcion_elegida == "c" or \
       opcion_elegida == "d":
        return True
    else:
        return False

def precio_viaje():
  print("\n\n Sitios disponibles para viajar del sistema solar :")
  for planeta in planets:
    print(planeta)
    
    
  resultado = input("Seleccione un sitio que se encuentre disponible: ")

  if resultado in planets:
      dist = planets[resultado]
      precio = (dist **2)
      print("\n""El precio de viajar al planeta "+ resultado + " Situado a una distancia de "+str(dist)+ " años luz, sería de " + str(precio) \
 +" gemas del infinito\n\n")
  else:
      # TODO : 
      print("\nEl planeta seleccionado no se encuentra disponible\n\n")

def opcion_bloqueada():
    print("\n\nPara acceder a este sitio debe de registrar su licencia\n\n")

def introducir_licencia():
    print("\n Su licencia se encuentra cifrada en RSA")
    print("\n Datos disponibles:")
    print("\n N:2388359604017562360686986826224407467085141542110106297195474917317598533853482966573781022895301214038172036369449124672056785812196701442436301713256329682262800506348973244370343978930848590448632471683227298949837982596258881987542556516242078135641151110529441878952297040735067050915825910591044267338619727699025093233802557928242039526776443273229603331123837732704576287055048035853719637773386378484400138967119256462879704170644777435140519575930343073837331606656680431107878364011329736084042156051102552595028376108767986366643502871029624959943078823651061456756269940347667680087219115241717836903727876944071795483871598218654421875968136363745276590642798841955188030275484016418866459941888404372137056223485086390119726549111092550651040715892407647299855009875414855092225786762619999478029464571012275427683308915306292354974121999956919177496194811807488385022242758843660252461621608921888601112105332430021120341932414260104903029586353455582330541938999265036078858976696027946971")
    print("\n e: 3")
    print("\n c: 1540721424343799902606651655848933086271745472278165266240849486559556881783873287413652584507984944306200870022880146776214626060950164476558869019210122220116044284889929096084990678169089848831509075708420122306035373495840314113720152014011617499294596976326861255637499828853401492372193963031884595623110218888611592586981134397771959503322183258914008502055519902491582335028201338136992911379083206307454812940479912821366654550451867440100372095636509631453314789012598795454510232231466021273667090876872012316533222291192770766350631652145833625098465315630072886326825137446590457400355062225014677785718519750253736188120429855174472025330346688494949266124236925164422748262980925232326494719540341841616873866001441002292970154428056595601908567551539056028365120426102085844437653070298813380091882415786292133393507387022552046526817913424253789271549901462627897454016941811819805715856594343758485141860592261362250817672946612120186033077052168133301973361814764918267639746916442387411")
    print("\n pista: la clave contiene un padding, y se encuentra en formato UAM{}")
    user_key = input("\n Introduzca la clave de su licencia contenida dentro del formato UAM{}: ")
    user_key = user_key.strip()

    global bUsername_trial
    decrypt_full_version(user_key)
    
#    if check_key(user_key, bUsername_trial):
#        decrypt_full_version(user_key)
#    else:
#        print("\nKey is NOT VALID. Check your data entry.\n\n")

def decrypt_full_version(key_str):
    
    

    try:
            global encrypted
            key_base64 = base64.b64encode(key_str.encode())
            fernet = Fernet(key_base64)
            global decrypted
            decrypted = fernet.decrypt(encrypted)
            global arcane_loop_trial
            arcane_loop_trial = False
            global jump_into_full
            jump_into_full = True
                     

          
    except:
    	print("Error en el proceso")

def ui_flow():
    intro_trial()
    while arcane_loop_trial:
        menu_trial()

# Encrypted blob of full version
encrypted = \
b"""
gAAAAABijJyT-gFmc53LOUxkjHOOitfzmBw7Acq1G0ELe2qcH3vx2U65SdTIw18VKKyge7QgvpSIKnMoj9xHO02OIWvjxunwUprREKlKxcyDwTOYZjG5xu-Oplb7tmaPpkPvOSr72EflAe6o3CWEww5AUuyDbBeZdPZ3anWBft3QAGcB3wV5xKF8D5eELDWM6bFIwLcFEqIMNe85bdutg0fiKdEnpACbtSaYlI7l4mPV9sXXe-ycSHZfk6guhXrthpZnt17EBwS12kgAsnizBmY0n9_OUYJFiWqLt8U1NN4yJS7qRUqWUx3yTznPXODVewghLemGiCHZIxpb9Ftx_wo19FbB_c-xkTSU39wVE2AMoDmI1JyWib6w1MkT_GWcva0h9UXve7AgtBQdp7IVYkrGuIlevk3Ni-xUbISvt_w9WQfiJL8IW28jObwEKA_GaLmbVGQR31nJ9hlqsvwVMXMRN9oAsctW7vOQK_b5bN29Heb6JK3oVra_T-BkFribIA1o1vvW3rJndI3uvlKPlFDwEaF-nsOS0dl_HRpIiZgnFJK_XVGLhc7tL78wOVnvSHHe2psZlewdoB2IRBu6rG66AX-GtHbd56bmOzFOSAd5ydzJuwy14oe_FT-dQ7uJkHqPbae76hHd-bWEIiPQFapHR5YVIFIWiwLUwxRXFDEYUIVgsSZB6nSCX7KxCfY5oGHfW6qUBb8N1QTsMvCEzkgHPcGGg5uD7Tp7BSHR1kXB_kRjPxjO7Tg4gfgARYHKWhqeSs_cRVCvC--vhwER2KCtM3U98QNM7YQi0piNy0C0jpVmFZcd_N1raOUBkt2e-2-fEo1bFzjc6Korl5BpM45eo7FE8JQvi8uCf6PHqcRfh6V_iaBUZfT0kbS6zT7Cf_jEMfPjdyz63M0FtXyAMZlPX8GBFgNL9HnfWsWQTTSY-Nmpz8HsTPmc1G6LymAZC4PfkBnlq8_jxdzfZGO-c9HiuItCYkiTrLbX-XfZM8rmP5SAPQbVKtjvxacyHenhXomtTYFAlsY-nDFkHfpZH-ec3HY-6mH9lO59IT7g5iqIyCTwOlrN0Abv8qoYqGjboSdt3JhRLAfVnXJ7S2iWGEPbzA_ylqIugG-5_nEiWTDmepKyAFWNAtH7cdLUzSF2okmtd8Z7y4lZzSwrpavDarjE86yBJSfCmvqvLMHJLTCVzA8aJdahFOyssL5SaXtKbcJ1rT5nlalDjR7Op1yx_Z1Ae9am338aF1UENFiHWiTufNx4OxThxpYmJ8YA4_qlnKAoFfYQlMjYfF4JUjezS9qfheS_7L8gLwU7STvku7dwjfVbaEv-n7exiwl9Pfwk6u_ln7oiYjQwGcXQZMx6tQgYNWKZMBCkENWcX9yuhqOXxzq-CKrPYG3-Kl9yA7EHBLjs2GwbUKCVu6arm5ChCDEPB7TApcmyUWbGAosjp4bl-LoQCojgDFJmR-Uiialj9q9xRJadyIGQLY73WttyyPQU7I2YTyOnmQxcmQ0FYYNMbFlcvAt1zYc00rWb0mf-jjbvUqqnUS8cvWl0uw1jjY99NVEWaZ3_W8wpePcg2yThBOmCd8H5ye2uqDvz79Fo8JOyTsPs2NB4O53g4kqjQ1oQFMcwFHQh6xmNGixEy6FHS3fzg7kz8Ox3E6YI1TfUxPovEaBGtPeEVvh6J-LL6O7ruNxY3h65qJGlz6i9UifrqIpyn_FR7kUV9ZDRHYNZDY_8VRCa9Z3WS_OBRmyggYWlb2B8MgITe2ndk2BtUIDNHXdxRZ35p6xkGoaqX5OfMkhrR9GJ8wxoWf52V6n0U7Y-NRbpG5-eDAVtF0dt9aEIOhF_lvW8JduHTzBhHQGNg_uFYXB4B7ZHFoYfKfBEaXfpP8csEIWGBOXplE3nr5cDxdI5X2iAzxzb1gtWS3DimmAnmOjPcNBNcU2L28p_u9-OXnMgvoiLMcXqWhPK9Te889Gyst2RUA998cHOGFDUlnMMHdQacQNag-cdvOYUjn5c4L9rXygzTqVSRRsbKNds_2dWBwjAdLINyn0tvSQaFR9N03fUMruKSqhebIj4SXi26vo6E1etfYPujJEaHEqXUk_9hxCCD_npAWIJtkuoRIBKD32zqMXeRxkL4xb1BCar_m30bap8Q-hlA0_4z3hakzjtaYjyHgRXHzMVqknb104DPhDXojg1eKuq9CVr6YdQYa0MfUmedMd2WBmYYdSqIP8z2ZZ8A3VdFa97kkw8FaFtyLfMeeGD1AlIszTD7CVmcuy0rVwnjZY8aYdpTv1VsKpdsUToLbAjXVhRa76LjMOjLrLLTR-7SoPlWloux70SxXuQyec4XgC9NY7o_PqJe8I9HXu1rmmzxKp-2x3WYRUF9dNzqRYmsMhHn0w8WrwvLDBigri314lXjaHYSn9nFj-ajEvPq2S0j6RcGOLsD33eoswdiZuItIERC8O1ZAKuSZDRgbE3si5qkCNro_C1VrKasdIF9rQJh-dEHDZDE6Gdw8o5wS1wyTxYjkexvFExfe5c4iKcP3iTJySAuBI4_Ta4KS-sk-b16HQRCpEwQ5Pz7-eIldSRHZnrLJFafYOcIeHWBg-TnzH2v5bdxPexBQW4WedLAmOv3Yg5IHAGt91wga_kQ8JNeDcpWQ8fsa94v0VL2ULT5VbZLX7nWDRj3EQcMoi0Ct9JCa7GK_vDd1jYm9trL52T1pm9bHgtFfcTbUxytsW8Bj7r1rmn3GPfc__UmTl_POy3iSdWKyHBF4YUg0ds2W2NsZkNds3ZeNLQvhOq7PMcH5uz3e7e_4r7rWH9AMSAEcfQZymGWwxq8p3q5lDC8coA7Jbw9S2_lpgoW6YwWWUBkvfm7IIdfmbHvC2HJD1JLRq-nQ2Tq_KZon5aXF90huY-7XWSV0pkjt2eTonWN56shkC1OUkrLpJbxtls4NIwpQRA0zhmQHywCfE6Z7xDWylYofLzJeuV5PxvsFFYNO3lq1ApqNAcj4YA7WZ9SJEbx3O-kGBNUWpW3I8gpvJPxF7xvNIJrNv2aJaBCDkAQ87o7UEc--v_J_hj0qYcu_CMLpJ6pWz2-OuL62U4wSpk1cSGkyS42o5DK_UbtDq0Z-PRln7-Z6mR1_L5QlXO6QfXs2UZZWVYyMHuwDN0FL02-E93UFbDC22oUP088jrI19z07Gj3X7LdZYbXWcQBb6HUarYTjUgRcgUWydRur_QRcJChAG1VRnzPLHbI0C9k0y0vczlvSRWKiZDcO4bSV9cUX83BFg3UEbO3eJEALwKnpJypfcjCouvQ-xxa2LiGbpqy_xZAcg1suTtxO3Q1WOCEbPZ3XtfxdUK4gl1mQTzxdgjXnmuKojxG52wDdVg2XEINaf4XIpB1RJHSIwkuqNrBpjDd7MQKuEzs7BwAxK2ULDI5w8FaWpuKyCGHtpFJa3qUwToQJ9Cnnua2uUMhWkKtWUlM6-VTJsYbz4_Fs5RNEiV7kagAfq2AOvEElg6lXHkb67G8fzMjwhEToloFVRUrn_OkfU0ah0sSSnpEZ8QSbI20jyLCJN8Pw_PD4kKIiER1UwwR9ZPByzMtpqQfrFlUAZP3yQwnyaKWmCDze6tICbjeYTkOYilWZhLj6bNyXmQ1f-SZtCc1G0Utq6bQG_CV9cSiKIe_zN0KdEOuYKxdxMqnarWnMY-iXdSZO2fRkhK0oxOUlkWNoX5kb-VeNrzshmYm-TcDNKDOduR9CGCCWSPzjBYPvRYnZ78lADx2QMe4FDt4LCVuNHKYAjvImBy13q5xRECxcfWzRGejpOn_yc5N8krGzumNibW8sl9J9Yhg8JSnQH_B27rq1qHCR0Hy9Z_01aVO1ngYrYykV6hboyhgMlJdYbcXczQH5J4E8tGDaRfsyPpOozjk9F6ag5HahUW8B5RFU7Xchob_OXm3X1rncBVOIEkl5_n7KZrHi_npgnv0BwYQBj6K7CqYZGoNa4nThc8NVByITrEZdSpkZ_9-f_m2NOw2q4SWpLAV8YH3gC-wEgEM13Wb8gwjgfusP_IXkG7KkqSQ1J_zKS9MtotuBtrFnqxUmUBMgSJp45f94aC4JumjzRXPM3dPDOKm78LHRBh8oc-VbMWv6qJgh5gp144d6GAFp5dazaqDlk3Pf1yVAZJvs7lviI0TFSoPjIOP7rRdMggHkvX1WFTjujyV4k54e-BDwabXYHNJg9eLzs5VoJwkcMJ3XZPg6YbBLHgO_dcUShkVV14ZFyF1VWMMDCntQPqpQI5K5LbM21KMJONmkKqrkcJHoWBlS2u5-2xS1tqhXNz51vq18bZGNrKej16BYvtL7LzK2q4n_UNwNa8zLY7a0s7afjTpcuXIU5hsoGtZKwbD7v3dfUDuVfpM7eICUEKWSsIjHSUSHcUZDqetjuQuO_quKhvSKs1wnGnI_Tz2Gt_ERjpuOaQCzp5fPFlBj4axbufLoWoP2otsISJwzQyO_R8bsHYK8EfgT6BHwtQz2D7pNWhLqBJt7z0G1OYozdj1Gd7nrfhq_arihEDVhbqzESwHdu6YXQQMgJnAz8qTCRH4QI4igmen9nm5gcSUmdCXBh6fR5cEP7gb8I3lTDyYF7rUc3XAir-xjV4ipZHJ-b6x-BP-CHemqvzaDuf6BobhPtLme0DhkfVYID1WINXcZCbe1GdGkqnlp9YAP6cJcGqGPydjuOuH6EZwUd5BFSol-9EwmV3gAtJDXS7B0Tgccsz68jxjiJapmLSI2FypwTX5oyIl339QDhXR8Y5yRpdcpYbkndUbmGrKp0K_xR8w45mWGBeOhwVZ1LVcULCNoORuse2oB6iKplLZviNult2U4DGo4ZUtuVgWWdzg7umMVEKBA-hgkSxDvdDFV5kIzLNJYpWWEFPVMnUS6dmbQIIWYgHcdlUyfbydt1KPR_d46rFGe5cZ1bDihUmdGaEXtmQXaQ5Ogn-cJNTBufG1ZPbdcFsJpu2sogLWbpwmSlsDqvlbSBNKwwFzeD2wgrY3DibYm2ULXLlxEA140KV2HjZ8HA_i85eUvJ6rGHgliMMoJWCB3rjN0FlCU2CxcNYf1eOYJTKMWv9cScQGNY8m-VXJ76Ee59c3frP7gCL_Swf5c40uwWlYgyPIZCZXaO9y6hyDISf7fmVSPUQ16zcztyVbioQjD2WcMDhqAW_sVdumuxHsue0KENhuDDnXVKMlGc2syVqHSwryHza0totX6oxB6aJ_hPWfENdZUOyoZl_Lpivj_vAT8qo2nHDgmLD-bSU_-o0I78WAE4dNvpUjyEkxAhOZO1RF1ufW6C0R9qeBKGKma1lPrhl5HsEu6WnmZiDm08XVms2P6hd9E_nmX5R-zaUYRMPjK1nXQFP0YtiToichC7LXS9fewt_LKbwXFv7IcZDu3ftAMk8Ulcxb6htIKObNxGgImyuuveyEPAN7MBS5ee_cpo5VoAW601JKRxIREMqd-JN6DTNl7zOhfYSi1B__LDtGmPe1woqBtEVQk-kLbx8mSvFxBD4C2jeo-kmTXI7VSKAOfqkVvcRsowuO9593t34c0E2frVxAMw4a3z00FNYT9YuABKAbU85NAzQockoRxYCc4wTJJTHtC9j7MX2jGIM9RB_K0cczOvvLzDvUsj0rb_BE4OJRJ3uWJlHFrHIMmGRGnlkzBDnoa8J03MhJImWvkjEWBdEba79v5Oy7FNTP-cpa8G7jrx2wmmGdoDeb-RmdBVvSxsmVJcUj0K0kuOfOowzDiDy8hYRzi3LY3VE3KnqnNEL9WKPOYifKX54ZTl2NmdWI8lqqzDjJU9vd4zPgOVn5_iApaUURc75sUadDib2uahYmwVytUz8TBP_ZP5vLKarSQE83kfNmLePU_1KNBq07-TsBWgJlKqDMgJTcUhKX6X-rEwhx_1sY8Dt2uk3KSi4lWn85FlMakpQ75doaE2gTS5XH6EtcqC4w0wiKZ2VRGulcM9ZRpvdqvoe8_7Yp5tdj98zIiVO6Ne4j4s_DJ9hHtn2PqsdVNviySvGt9xalvh_t-P65Irs3JMEaEGys1AtsaUrx7EYVVv-FlW7iGeZhL-ln5Z-ydwP8RxHet_feNLfCBMUuMPjm3HeYw4uspgWfffOymCLtTZM44XPWhRxJupJUJgOhHOigFNQ4YF9nwM9mRkVoqaTsSo1EW1lysVwhvSKNqfrJG8Kcvo05rbYIrrzQf6LP-YP_vtLLiWIvU8tF3rv7f6GWvBlK8teenwoz5peDUAYiWFT48uJ3UjyP5jLyNbHktjjTF2Nhe9Jup2lQLr5bFNoFDS0vWYS3lcJ7exipW7Ra_7i0_GHuGyvnauAq8MHqvlNzMPUrW4Jc514I3I2R1SRFUcfOk3QHUsgkdLVldTOd7nddE6TJ8WPqSPQ7ge_lnJ3bx6UgvYL3WYzPf6l7oLjUZqxrvmaNWFKhgA-LBjHIjpnTugLa3e7RR_SCch6SAqip_x3ZtSuIb9_dXtsws38sn3010Yh_aYjYx1M028f_EMHPxWAie5nzxLL3LsZ3aRKRZQ1RygCzLepO2-sO269jtsqZmYbFMEbCj0g45j8LOdQop8uaYbeYFRWxuO908P5SH5-LDtOQ_cfFTCBTWIhX5jNZtxQndhNRIIT4s-E6l2g3_vI20uQewMPmb_YvFeu3PVxGynOnLiOJcAflRSxTlbV2Mf_snzcppPwdzT0uk-bnpQHDFau2jgKLDqwY9vVUGzBdGIy4MgQVM2_fqXJbnQi2vAZetNC2KARttK1G_HTwv_mFtQmxE3JFH1p9SDKpPd-gmdEKJ5vYRDQz2g9ZI6VDJJqssnvTmPqH3YxwQcEb2DU7XZwzXNSb1cqbLO7-WTO_a-8Zzyw-P9TqfPvhA6GbCKHziO4lsO_LIMSV4qF091YZF7wXRTiFP1LRMhF4bYt7u6VLzKvf25aoNYVY5QHh6dsbb4i-I5Nwynsufab-qn4KdfJOkWJI7XkEquxdurb3A_QXGJB_v3hyHzOXdkq8EZRYenTU14jDyx0co6XuRFCTCh71_IYkqKa774UiiWn8gO_KyjFIYgJTeTF5DSJ_ZTcbMdblPB-aqbk8XNppGV8fE9h8qRGx6frp5hmWv2bbMDNaPIe1Z6mSz87ubNdAiFaZR5uEN-ocBR3BD7Y_ncpcyo8jT2l40VEvy5Lx3oDELBJVcgA3u5YIl7dchuc-jr33Oyygc-HBAG5VzQ5JLap9hVNQdXBBwdOZwDy2lJn0JgUKq-Z0ZDwKmJMQEiM0u3R4IHTZoiLZRqyaU6lYKKqDlkaUdn68AHqx2GBYmO06Z1RiYi694xnBr6wcn-gElaXQ2xtyy57CPmRC68I68DJSqDUXc9V1xAGd8EtH76n5BKOZfOQzPp8gTF854WLnpsCmtIRPmWNb0OruFjCC5g4Pe4Yx-FlElJyu0xSyqDhusHgFwbzDrEm64yqaPDbrE9OYeq-swpEppgWoINjoGkhmtiJQgNcN_dse0mF7jUQpVwrEFljgNP6B9LXBFnW7mHraycf2htkVD4gvoReAjZv7mCtsY1MT50bQO8R31hvRb44XXYdxXgxQWtuWVyzjcWRgY-YMdjmg-cp7WyGdixV_9GbzYlNwJjBYPaQu2rX8RKy1KbG7kG_bZ0UfyhATu_GJuplzpNnthkMiNiJB6UHXqYBuJb5SNcbUaUaEwIZCLAY6ZzaWgS_Jmxi-82P2oo4GHRIPTPVlj2Q8sLsfX4VEWrzHpSX-37NlqXNFlrGNd8MRCpsdpwGv5CzWSeAHhYV7emXtRF-4AfVg9TB0UKpuEnwzCa2RbZYrsoMa_wK_zqV7CjzlcJPHzz6__chqF3mOAx8yZ0Oap3SOE1Qaz-ctc5hkUzPwcNZ-okOMfNQ4S-qinCrDYPBdXVj5wj1b_u2jnARG6LLitaLdnlhB3uXEhJ7t1WT4bhDzNBRMyK3m6hj_EQqYl4Kqcp1CugZSs1fxuXV5g2nbPjsbZa-fVQWZ0fo8gRUbKRlUkibIx-6otsj6gyoK3z1cNEsOxSDYKHE73O_0CCaHR0JxRq8Y-dE6ZNKCrEmHskL-hPmqqJu04kyPJFknWFyPKO7MOBbH5WGf6cFvlsOSPSUBbX62RdN7tDYjjtjDHnuPi9czSXl69croO7p30yNeBshCieCcSCiiXgWooTXzko8CVfcTnjFNBlrHih43Ak3AJ1oKZkciYWXK3PsXoqC6QIdSMGR08_PNXE7YdClqwQAjr9ciPUWIpqbgmOKeJL3RHf6zyt7fXp7md8aooQv9eZtcLR6ZyQSQtDQBbjjTdOxbPI-_WPz0l_ZDSHLfOkK9Dad-lh50PA4lcy3YuVP_FX6fMCA8OTlUdgXI_sI-YOG51Jc3x9FXwhPwRDsLwCGvECFJ28SOkY_HpWdWK-FMP4HxvXhyYs_vD8JiDruYxmZAl0tpmOeRcyrCghcaJyGKXw8GwdH1wsRjF9VfmlD8_mVlSfTujPr2BGP-8_poxmbLktM0MIh8T5wUondYAhIcHCy3t1GSn6zDTOdrsN3-tIVh-3nlVC6yEcSEUCMAJ6CxzGOGJ1-FvpP2HbuG1XVTgzsIddjZWYMamYDduZR-TnpjU1O_Jc0_wYOcv6JyBK1Pr0LtGmK6XAwLACBp8PxzcBOZwN9x5IdvuHUIdGU4NVuCNYkltK-H-rNCCJ7Nmph8vfny4NO-1ho08Ju8UlgW79wJyBYBBh9yTiawhaE001iwI7Ttsd1beRIxLtL4St6r6_fCrJ1XaarLTbmlvFNhxbe3IE0Hfw1wFt1vGR_zfAq52hev8DdKYjHXKqmKZpLe8cnl1hvhjlLktNj9TZpL0FXTp5HOF0PPcoIKveI4Eqf5-CGB5JvnWVkoGAvJ2Ues_YLj6i3fTn53GPn93rUfwLxWD8kesEz0hcX6xqpJEpVFiEZ0gvcyQlS-wteuErcr0W_37nqcD9BnrZl94IrXHp7IVpUigpX0YHcSdNOyhh8Bam9u85ct__oA4kVGSEKnPHR8jI_rTp6rmoGx1k9fuRmO6K4zauC_uhSiH8ycJtjTBmimJ6rj9upEUdT7ICqhcD6qP32rB7UhgRy1sOg1qEju9LEyBHn-sInkdYzVxMi_OyoYNJynUWAwLzLHEq4qGtERwyEj_XPuAAe1PQbVEj0YP8YNCeZwK-OOgWYRLLEwPCgF5FxoKdzNm4kOev43AR5gtbwFP9PIJD12wci7jNtToJe-YYnhcR2ohEHwjyzQNBV3C5cCl6XBUoCa1v2BSHqRc_N5OaY_qqGL058fAMxiKxtTu93EBPigxgsVDH_sXQ1QrSU-Jkn-iTEolFjvEhrlCl1f3KMMBg==
"""

# Enter main loop
ui_flow()

if jump_into_full:
    exec(decrypted)

Primera flag:

Bajo mi punto de vista, conseguir la primera flag es más complicado que conseguir el resto. Las siguientes flags son más directas.

Para esta parte tenemos que analizar la función introducir_licencia:

introducir_licencia.py

def introducir_licencia():
    print("\n Su licencia se encuentra cifrada en RSA")
    print("\n Datos disponibles:")
    print("\n N:2388359604017562360686986826224407467085141542110106297195474917317598533853482966573781022895301214038172036369449124672056785812196701442436301713256329682262800506348973244370343978930848590448632471683227298949837982596258881987542556516242078135641151110529441878952297040735067050915825910591044267338619727699025093233802557928242039526776443273229603331123837732704576287055048035853719637773386378484400138967119256462879704170644777435140519575930343073837331606656680431107878364011329736084042156051102552595028376108767986366643502871029624959943078823651061456756269940347667680087219115241717836903727876944071795483871598218654421875968136363745276590642798841955188030275484016418866459941888404372137056223485086390119726549111092550651040715892407647299855009875414855092225786762619999478029464571012275427683308915306292354974121999956919177496194811807488385022242758843660252461621608921888601112105332430021120341932414260104903029586353455582330541938999265036078858976696027946971")
    print("\n e: 3")
    print("\n c: 1540721424343799902606651655848933086271745472278165266240849486559556881783873287413652584507984944306200870022880146776214626060950164476558869019210122220116044284889929096084990678169089848831509075708420122306035373495840314113720152014011617499294596976326861255637499828853401492372193963031884595623110218888611592586981134397771959503322183258914008502055519902491582335028201338136992911379083206307454812940479912821366654550451867440100372095636509631453314789012598795454510232231466021273667090876872012316533222291192770766350631652145833625098465315630072886326825137446590457400355062225014677785718519750253736188120429855174472025330346688494949266124236925164422748262980925232326494719540341841616873866001441002292970154428056595601908567551539056028365120426102085844437653070298813380091882415786292133393507387022552046526817913424253789271549901462627897454016941811819805715856594343758485141860592261362250817672946612120186033077052168133301973361814764918267639746916442387411")
    print("\n pista: la clave contiene un padding, y se encuentra en formato UAM{}")
    user_key = input("\n Introduzca la clave de su licencia contenida dentro del formato UAM{}: ")
    user_key = user_key.strip()

    global bUsername_trial
    decrypt_full_version(user_key)
    
#    if check_key(user_key, bUsername_trial):
#        decrypt_full_version(user_key)
#    else:
#        print("\nKey is NOT VALID. Check your data entry.\n\n")

Se nos proporciona el valor de e, n y c y nos pide una key.

A priori, podemos pensar que para descifrar c yobtener lakeypodemos abusar del valor tan pequeño que tiene el exponente ey que esto no va a darnos dolores de cabeza, pero no es así ?.

Si intentamos hacer la raíz cúbica de c, veremos que no obtenemos nada con sentido.

Es en este momento cuando me fijé en la pista que se nos proporciona en el código:

pista: la clave contiene un padding, y se encuentra en formato UAM{}

El padding se está aplicando directamente a m, es decir, al plaintext que se cifra. Es importante saber que solo podemos hacer la raíz cúbica de c si c < n, pero si le aplicas padding a m puede que c ≥ n. En este último caso, podemos conseguir el plaintext de la siguiente forma:

para un k perteneciente a Z

Por tanto, tenemos que ir incrementando el valor de c añadiendo múltiplos de n. Además, podemos saber que hemos conseguido el plaintext correcto, ya que, en ese caso, al cifrar el plaintext obtenido tendremos el mismo ciphertext que se nos da. Veámoslo mejor con el solver:

Space_Project_UAM_solver1.py

import gmpy
from Crypto.Util.number import long_to_bytes

n = 2388359604017562360686986826224407467085141542110106297195474917317598533853482966573781022895301214038172036369449124672056785812196701442436301713256329682262800506348973244370343978930848590448632471683227298949837982596258881987542556516242078135641151110529441878952297040735067050915825910591044267338619727699025093233802557928242039526776443273229603331123837732704576287055048035853719637773386378484400138967119256462879704170644777435140519575930343073837331606656680431107878364011329736084042156051102552595028376108767986366643502871029624959943078823651061456756269940347667680087219115241717836903727876944071795483871598218654421875968136363745276590642798841955188030275484016418866459941888404372137056223485086390119726549111092550651040715892407647299855009875414855092225786762619999478029464571012275427683308915306292354974121999956919177496194811807488385022242758843660252461621608921888601112105332430021120341932414260104903029586353455582330541938999265036078858976696027946971
c1 = 1540721424343799902606651655848933086271745472278165266240849486559556881783873287413652584507984944306200870022880146776214626060950164476558869019210122220116044284889929096084990678169089848831509075708420122306035373495840314113720152014011617499294596976326861255637499828853401492372193963031884595623110218888611592586981134397771959503322183258914008502055519902491582335028201338136992911379083206307454812940479912821366654550451867440100372095636509631453314789012598795454510232231466021273667090876872012316533222291192770766350631652145833625098465315630072886326825137446590457400355062225014677785718519750253736188120429855174472025330346688494949266124236925164422748262980925232326494719540341841616873866001441002292970154428056595601908567551539056028365120426102085844437653070298813380091882415786292133393507387022552046526817913424253789271549901462627897454016941811819805715856594343758485141860592261362250817672946612120186033077052168133301973361814764918267639746916442387411
c = c1
m = gmpy.root(c, 3)[0]

while (pow(m,3,n) != c1):
    print("c = {}".format(c))
    c += n
    m = gmpy.root(c, 3)[0]

print(long_to_bytes(m))

Tal y como se puede apreciar, el padding al que se referían consistía en una serie de espacios al inicio de la flag.

Segunda flag

Teniendo la primera flag podemos seguir con la ejecución del programa.

El programa nos pide la key que hemos obtenido y llama a la función decrypt_full_version pasando como argumento la key introducida. Si nos fijamos bien, en la función decrypt_full_versionse llama aFernetpasándole la key en base64:

Es importante saber que Fernet espera como key un valor de 32 caracteres, que es justamente la longitud de la cadena que hay entre {}. Por tanto, debemos proporcionar ese valor para continuar:

Seleccionamos la opción b y se nos muestra la información para obtener la siguiente flag:

Space_Project_UAM2.py

Vaya !!!

Necesitamos un segundo factor de autenticación

 Para acceder necesita resolver el siguiente problema:

n1: 17824662063931350214223386810814852301249515497497139812902163502913781924494611383559346606809815236390210116817784675436123817314832624239657588495739923029371893435842952633535768082946372752199420527479895241774646728166830063698600428670873489541441038897760730320294745670668053915562174940630507138294534347731116571076461922963834100132973236843497044086332284604129786238315376752921033613925923455396251665685832824666952007264503312922306586584664237974009954961856288489437483125273510945425456410783438852350972373785999603984625001762658969945048955998467179256971330663798743101126043605183291761793679

n2: 17460577025417532617145065037522684719407212829127451193876716400196816451636430831743273489268207759853471132779546752834413623537793912793243812987259466151761228452196854582811181807331843291280738156817866981931271729145201226943579856417184407304033533100808047053336224549884935791510122547487389856804128285266553747962197617004719267537827108328539484564367891730008842618178044124246682603653614368491934722999483505794204154388663752989138088424922985942599433814759715253917667843057739090927990433558072887522997800471142027386754437727690122530332561092903112609343096885413214207313020041427777416836713

n3: 19114115977732462701709687019902486937265612420334195715080797324907548368977075060698379696844613238474174655637002859494277633539823803694788625199412189504047299862787677238571557745235955402842143068069196101309866614792992094693162184772586974368956295124443272755898820570613890603947101529357476017518645136618906447433181071918544531652127075189503179140301462754620053974156552468411421074335786969199496555935064048045710530822473363892607723160785400638903937101974117782322313128438097540590522784580157463985226829290798397701018877754144380300784917111841349513391737293839942174090204466464441015492703

n4: 15680798551643988657227725199725012596795476788443067644763327604090511762090190479406955886477193871047341493066942394066713967749566032658288400768708478341188709773196419875727016823917358484802065657425968279639244589186765648041473389736294238890134959149156339523848000619170500615417270307174902991451802589702742104898640491331399313066713005239533220591758448459212465699731809196452098191187437776390331912957335192003925860873345418433583557156541796722390972745247097857595266619755507337406241346213908727239306423754384980052987581645674239898136379044720051607822563712811867075155274128421366838519583

c: 10931058306942089020672057700581464428272909160353174713420959992035643910409437837187988347774125974665123119596431537155658853351159062468188944273070821066937237766435849750062631870599237918419915582762855108175779466748532994055347749365575084502626428185068686508679344635119892041843950322009250685069064283921279309138421372296737657744514129020131720923828146884007481363881729475896383613849306362295706529335684081107062687862374744078331843219193260330138477840191131061097362730166647002540441817773187701136784352161143486235686385064948492946913439739470641841610262898366469961158456034571552582618844

e: 65537

Las relaciones entre las distintas n son

n1 = p * q

n2 = r * q

n3 = p * r

n4 = r * t

El encriptado se ha hecho de la siguiente forma: 

c = pow(pow(pow(pow(m,e,n1),e,n2),e,n3),e,n4)

Este reto es bastante trivial porque las distintas n comparten primos, por ello podemos ir obteniéndolos. Esto podemos hacerlo mediante el máximo común divisor.

Dado que la t solo se encuentra presente en n4, cuando obtengamosr podremos dividir n4 por r y conseguir t. El pseudocódigo es el siguiente:

pseudocodeUAM.py

q = mcd(n1,n2)
r = mcd(n2,n3)
p = mcd(n1,n3)
t = n4 // r

El cifrado de m se lleva a cabo mediante el siguiente fragmento:

c = pow(pow(pow(pow(m,e,n1),e,n2),e,n3),e,n4)

Teniendo los primos es sencillo descrifrarlo, tan solo tenemos que ir descifrando desde fuera hacia dentro, es decir, comenzamos fijándonos en el primer pow:

pow(*pow(pow(pow(m,e,n1),e,n2),e,n3),*e,n4)

Se eleva pow(pow(pow(m,e,n1),e,n2),e,n3) a e (mod n4). Esta es la primera parte que tenemos que descifrar. Sabemos que n4 = r * t y teniendo los primos podemos calcular d y descifrarlo:

ct4 = rsa_decrypt(r,t,n4,c,e)

Tras descifrar esta parte, conseguiremos lo que he denominado ct4.

El siguiente fragmento a descifrar es:

pow(pow(pow(m,e,n1),e,n2),e,n3)

Los dos primeros pow corresponden a ct4, por tanto, se eleva ct4 a e (mod n3). Para descifrarlo seguimos el mismo proceso que antes:

ct3 = rsa_decrypt(p,r,n3,ct4,e)

Seguimos así hasta llegar al final y obtener el valor de m. El script final es:

Space_Project_UAM_solver2.py

from Crypto.Util.number import long_to_bytes

def egcd(a, b):
    x,y, u,v = 0,1, 1,0
    while a != 0:
        q, r = b//a, b%a
        m, n = x-u*q, y-v*q
        b,a, x,y, u,v = a,r, u,v, m,n
        gcd = b
    return gcd, x, y

def mcd(a, b):
   if a < b:
     a, b = b, a
   while b != 0:
     temp = a % b
     a = b
     b = temp
   return a

def rsa_decrypt(prime1, prime2, n, c, e):
    
    phi = (prime1 - 1) * (prime2 - 1)
    # inverso de e modulo phi --> d
    gcd, a, b = egcd(e, phi)
    d = a
    # texto plano
    return pow(c, d, n)

n1=17824662063931350214223386810814852301249515497497139812902163502913781924494611383559346606809815236390210116817784675436123817314832624239657588495739923029371893435842952633535768082946372752199420527479895241774646728166830063698600428670873489541441038897760730320294745670668053915562174940630507138294534347731116571076461922963834100132973236843497044086332284604129786238315376752921033613925923455396251665685832824666952007264503312922306586584664237974009954961856288489437483125273510945425456410783438852350972373785999603984625001762658969945048955998467179256971330663798743101126043605183291761793679
n2=17460577025417532617145065037522684719407212829127451193876716400196816451636430831743273489268207759853471132779546752834413623537793912793243812987259466151761228452196854582811181807331843291280738156817866981931271729145201226943579856417184407304033533100808047053336224549884935791510122547487389856804128285266553747962197617004719267537827108328539484564367891730008842618178044124246682603653614368491934722999483505794204154388663752989138088424922985942599433814759715253917667843057739090927990433558072887522997800471142027386754437727690122530332561092903112609343096885413214207313020041427777416836713
n3=19114115977732462701709687019902486937265612420334195715080797324907548368977075060698379696844613238474174655637002859494277633539823803694788625199412189504047299862787677238571557745235955402842143068069196101309866614792992094693162184772586974368956295124443272755898820570613890603947101529357476017518645136618906447433181071918544531652127075189503179140301462754620053974156552468411421074335786969199496555935064048045710530822473363892607723160785400638903937101974117782322313128438097540590522784580157463985226829290798397701018877754144380300784917111841349513391737293839942174090204466464441015492703
n4 = 15680798551643988657227725199725012596795476788443067644763327604090511762090190479406955886477193871047341493066942394066713967749566032658288400768708478341188709773196419875727016823917358484802065657425968279639244589186765648041473389736294238890134959149156339523848000619170500615417270307174902991451802589702742104898640491331399313066713005239533220591758448459212465699731809196452098191187437776390331912957335192003925860873345418433583557156541796722390972745247097857595266619755507337406241346213908727239306423754384980052987581645674239898136379044720051607822563712811867075155274128421366838519583
c = 10931058306942089020672057700581464428272909160353174713420959992035643910409437837187988347774125974665123119596431537155658853351159062468188944273070821066937237766435849750062631870599237918419915582762855108175779466748532994055347749365575084502626428185068686508679344635119892041843950322009250685069064283921279309138421372296737657744514129020131720923828146884007481363881729475896383613849306362295706529335684081107062687862374744078331843219193260330138477840191131061097362730166647002540441817773187701136784352161143486235686385064948492946913439739470641841610262898366469961158456034571552582618844

q = mcd(n1,n2)
r = mcd(n2,n3)
p = mcd(n1,n3)
t = n4 // r
e = 65537
print("p = " + str(p))
print("q = " + str(q))
print("r = " + str(r))
print("t = " + str(t))

ct4 = rsa_decrypt(r,t,n4,c,e)
ct3 = rsa_decrypt(p,r,n3,ct4,e)
ct2 = rsa_decrypt(r,q,n2,ct3,e)
pt = rsa_decrypt(p,q,n1,ct2,e)

print(long_to_bytes(pt).strip())

Tercera flag

Teniendo la segunda flag, podemos introducirla en el código y continuar con la ejecución. Nada más introducirla, el programa escupe la tercera flag:

Con esto terminamos. Ha sido un reto muy entretenido. Muchas gracias a la gente de Hispasec por desarrollarlo.

Espero que os haya gustado y, lo más importante, que hayáis aprendido

DiegoAltF4