[Hackvens 2024][Write Up – Reverse] Armazing

Reconnaissance

Le binaire « armazing » qui est fourni est un exécutable linux aarch64.

L’objectif est de trouver le mot de passe pour déchiffrer le flag.

La fonction main

La fonction main

  • (1) La première partie demande un mot de passe en premier argument et vérifie que sa longueur est de taille 32.
  • (2) Ensuite, une fonction est appelée sur les caractères deux à deux, et une vérification est faite par rapport à un bloc de données en mémoire (DAT_00412100).
  • (3) Enfin, si toutes les conditions sont remplies (les 16 valid_checks), le flag est déchiffré depuis un bloc de données en mémoire (DAT_00412140), puis est affiché.

Penchons nous sur la fonction check:

La fonction check

La fonction check

  • La variable globale counter est incrémentée à chaque passage de boucle.
  • Une variable locale (carry) est calculée avec des opérations de xor, shift et de et.
  • La valeur de retour (carry) dépend d’une valeur calculée par la fonction FUN_00400ab8.

Enfin, dans FUN_00400ab8:

La fonction FUN_00400ab8

La fonction FUN_00400ab8

  • On remarque qu’à la première itération, counter vaut 1, et comme sa valeur est remise à 0 à la fin de la fonction, sa valeur sera toujours de 1 au moment de la condition.
  • La valeur est donc constante, et dépend du bloc de données DAT_00412058.

La vulnérabilité

Comme les tests de vérification sont effectués sur deux bytes par deux bytes, il est possible de bruteforce les 256*256 possibilités sur les 32 checks.

Le script de solution

to_compare = b'''\x1aV\xdd\xed\xd6\xbb\xf8\xc0[\\3k\xd64\x89-RE\x96\x1e\xa7,\xb2"\x05\xcc\xd1\x1d;\x0b\xbc>\x8c\x04\xb1\xa7\x02\x0b\xc0\xa83r+\xec<p\x0es}\xdb\xe9\x01\xab\xaa\xf5\xe4\x945p\x9eV\xa2\x12'''
to_compare = [int.from_bytes(to_compare[4*i:4*(i+1)],'little') for i in range(len(to_compare)//4)]

datas = b'''\xd4\xc3\xb2\xa1\x8c}n_-\x1c\x0b\x9akZO>xV4\x12\xef\xcd\xab\x90\x09\xba\xdc\xfe\xe0\xach$\xdf\x9bW\x13\xdd\xcc\xbb\xaaD3"\x11\x88wfU\xcc\xbb\xaa\x99\xcc\xdd\xee\xffUD3"\x99\x88wf\xef\xbe\xad\xde\xb5\x00k\xb1\xbe\xba\xfe\xca\x0d\xf0\xad\x8b\xde\xc0\xad\x0b\x01\xef\xcd\xab\x07;\x1d\xac\x80p`PM<+\x1a\x8bzo^.\x1d\x0c\x9bl]N?:\x1d\xad\xab\x90xV42Tv\x984\x12\xdc\xfe\xab\x89gE#\x01\xef\xcd\xef\xcd\xab\x89gE#\x01\xef\xcd\xab\x89xV4\x12\x102Tv\x98\xba\xdc\xfe\xad\xfb\xca\xde\xfe\xca\xef\xbe\x1aV\xdd\xed\xd6\xbb\xf8\xc0[\\3k\xd64\x89-RE\x96\x1e\xa7 ,\xb2"\x05\xcc\xd1\x1d;\x0b\xbc>\x8c\x04\xb1\xa7\x02\x0b\xc0\xa83r+\xec<p\x0es}\xdb\xe9\x01\xab\xaa\xf5\xe4\x945p\x9eV\xa2\x12'''
datas = [int.from_bytes(datas[4*i:4*(i+1)],'little') for i in range(len(datas)//4)]

def FUN_00400ab8():
    return datas[1+0xf]^datas[(1+10)*2] ^ datas[0x1a+2] ^ 0x34a51bf2

def calc_next(x):
    carry = 0xffffffff
    val = FUN_00400ab8()
    for i in x:
        carry ^= i
            for j in range(7, -1, -1):
                carry = (carry >> 1) ^ (val & -(carry&1))

    return (-carry-1)% 0x100000000

res = b''
for p in to_compare:
    for i in range(256):
    for j in range(256):
        z = calc_next(bytes([i,j]))
        if(z == p):
            res += bytes([i, j])

print(res)

 

Ce qui nous donne la valeur ‘7$FqR#5wdx!LnPz8&mT9Uj@3XkH^Vo2r’.
Lorsqu’on le met en argument du programme, on obtient alors le flag:


Le flag

Le flag

HACKVENS{CrC32_1nt0_rC4_@aRch64}

BDENNEUINGÉNIEUR SÉCURITÉYolo

Add a comment

*Please complete all fields correctly