Ir al contenido

Armaxis

Autor
Santiago Chavarro

Código
#

Tenemos el archivo del servidor al cual podemos acceder con la IP y el puerto dado por hack the box:

from Crypto.Util.number import isPrime, long_to_bytes, getPrime
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
from random import randint
from hashlib import sha256

from secret import FLAG


class DH:

    def __init__(self):
        self.gen_params()

    def gen_params(self):
        self.r = getPrime(512)

        while True:
            self.q = getPrime(42)
            self.p = (2 * self.q * self.r) + 1
            if isPrime(self.p):
                break

        while True:
            self.h = getPrime(42)
            self.g = pow(self.h, 2 * self.r, self.p)
            if self.g != 1:
                break

        self.a = randint(2, self.p - 2)
        self.b = randint(2, self.p - 2)

        self.A, self.B = pow(self.g, self.a, self.p), pow(self.g, self.b, self.p)
        self.ss = pow(self.A, self.b, self.p)

    def encrypt(self, flag_part):
        key = sha256(long_to_bytes(self.ss)).digest()[:16]
        cipher = AES.new(key, AES.MODE_ECB)
        ct = cipher.encrypt(pad(flag_part, 16)).hex()
        return f"encrypted = {ct}"

    def get_params(self):
        return f"p = {self.p}\ng = {self.g}\nA = {self.A}\nB = {self.B}"


def menu():
    print("\nChoose as you please\n")
    print("1. Get parameters")
    print("2. Reset parameters!! This can take some time")
    print("3. Get Flag")

    option = input("\n> ")
    return option


def main():
    dh = DH()

    while True:
        choice = int(menu())
        if choice == 1:
            print(dh.get_params())
        elif choice == 2:
            dh.gen_params()
        elif choice == 3:
            print(dh.encrypt(FLAG))
        else:
            print('See you later.')
            exit(1)


if __name__ == "__main__":
    main()

Reto
#

Del servidor podemos obtener los siguientes datos:

  • p
  • g
  • A
  • B
  • Y el mensaje o la flag cifrada

Además tenemos que la flag se cifra usando AES en el modo ECB por lo que no utiliza IV y siempre que cifre con la misma clave y mensaje cifrara lo mismo por lo que si tenemos la clave podremos recuperar la flag.

Según el código tenemos que la clave es ss que es generado usando la siguiente formula:

$$ ss = A ^ b \ %\ p $$

Para resolverlo tenemos que conseguir b ya que los otros datos ya los tenemos, buscando un poco encontré que se trata de un problema llamado logaritmo discreto, en python tenemos una librería para resolver este tipo de problemas:

(function) def discrete_log(
    n: Any,
    a: Any,
    b: Any,
    order: ... = None,
    prime_order: ... = None
) -> int

Compute the discrete logarithm of a to the base b modulo n.

Solución
#

from sympy import factorint
from sympy.ntheory.residue_ntheory import discrete_log
from Cryptodome.Cipher import AES
from Cryptodome.Util.Padding import unpad
from Crypto.Util.number import long_to_bytes
from hashlib import sha256

p = 59702555363140365331221654367749202594684333032653445501600946953015480391016276040925683077716904592873209440311716988833274523783610980994223127214220800208471343487
g = 28607077544811228815959291844142045756225848738120397478772468003446598863446354933589570289508591077174331427234175726954660251792899436433628822273951414414283265286
A = 40128858578334550784152606754547996995101433425312177936319008861285712829228083206324801229162121952523492000002546147948532844880866252831360023464564459187935260314
B = 36869696607134213037764766496699729672230301311065576696978853896383514877746237126437066067741173150436635504714236708512081363150395196544387116017253252746350804843

b = discrete_log(p, B, g)

ss = pow(A, b, p)

print(f"key = {ss}")

key = sha256(long_to_bytes(ss)).digest()[:16]

ciphertext_bytes = bytes.fromhex("c409c9789e3ef6c74893c0a21b771f37e0b4e2cb73248445574bb4c7379789d492682ec789ff8c1fe3b3cae6ab236ead")

cipher = AES.new(key, AES.MODE_ECB)

flag_part = unpad(cipher.decrypt(ciphertext_bytes), 16)
print(flag_part.decode())

Referencias
#