[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.
- (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 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:
- 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