UP | HOME

x86

crackmes.one (jeffli6789)


Le binaire a été écrit en ASM, il y a de fortes chances que le décompilateur Ghidra n'y arrive pas. Je vais profiter de ça pour utiliser Radare2.

Au début, le programme appelle la fonction scanf, on remarque qu'il prend en entrée %d, un nombre. Une adresse mémoire est ensuite chargée ainsi que l'adresse à plus 0xa0.

lea rdi, [0x00000924]           ; %d dans la mémoire
lea rsi, [var_4h]               ; l'adresse mémoire où stocker le retour utilisateur
call sym.imp.__isoc99_scanf
;; ...
lea rax, [0x00201025]
mov edx, dword [var_4h]
lea rsi, [rax + 0xa0]
jmp addr_0x704
;; ...

Il y a une boucle, où le nombre précédemment entré est check bit par bit et, si c'est un 0 ou un 1, va changer l'emplacement mémoire précédemment chargé avec 0x2d ou 0x05. À la fin de la boucle, section..x86 est appelé. Son adresse est 0x201020, soit l'adresse manipulée moins 0x05. En regardant la première ligne, on voit que ça charge un nombre dans un registre, la suite est un tas d'instructions incohérentes.

.addr_0x6f8:    
        mov byte [rax], 5
        add rax, 5
        cmp rsi, rax
        je addr_0x71b
.addr_0x704:
        mov ecx, edx
        sar edx, 1
        and ecx, 1
        test ecx, ecx
        jne addr_0x6f8
        mov byte [rax], 0x2d
        add rax, 5
        cmp rsi, rax
        jne addr_0x704
.addr_0x71b:
        ;; ...
        call section..x86       ; adresse 0x00201020

En faisant de l'analyse dynamique, une fois la boucle finie, la zone mémoire est rempli de add et sub sur le registre eax. Un check est fait ensuite sur le registre avant de retourner dans la fonction main. C'est ce check qui va permettre de trouver le bon flag.

Il faut donc faire une équation avec une valeur en entrée, des valeurs à soustraire ou additioner et une valeur de sortie. Il faut donc avoir le bon calcul pour pouvoir finir ce crackme.

mov eax, 0x3df2f794
sub eax, 0x52ae22f2
add eax, 0xbf409bcc
add eax, 0x46417dc1
sub eax, 0x25f7d9a1
sub eax, 0xef83a7ce
add eax, 0x2dd63e8e
sub eax, 0x584a1ec5
sub eax, 0x8e58e1df
add eax, 0xf2705f70
add eax, 0x2e94ef1e
sub eax, 0x3ca9e080
add eax, 0xa617b5df
sub eax, 0x29ae9c3d
sub eax, 0x7461ed52
sub eax, 0x7125faac
add eax, 0x65dfffd6
add eax, 0x97f1f41c
add eax, 0x6f4e0648
sub eax, 0xd803e5d0
sub eax, 0xf358f0eb
sub eax, 0xbc3b30c7
add eax, 0x585685f8
sub eax, 0x2a9cc47c
sub eax, 0x7f03d175
sub eax, 0xc1d942ae
sub eax, 0x174c7d4f
sub eax, 0xb7d004f0
sub eax, 0xbec8b077
sub eax, 0x8ce8eaa2
sub eax, 0x2510e330
sub eax, 0x4aed0eee
sub eax, 0x4043cd91
cmp eax, 0x7a612770
sete al
nop
nop
ret

A noter que ces nombres sont aléatoires.

utilise rapidement le décompilateur scanf, emplacement mémoire -> changer le type pour string et scanf "%d" donc récupérer un nombre

on va tenter un peu radare2 pour prendre en main l'outil https://www.megabeets.net/a-journey-into-radare-2-part-1/

edx -> le buffer rax -> adresse mémoire rsi -> le pointer + 0xa0 (160)

boucle : ecx <- edx edx >> 1 ecx & 1 check si ecx = 0 met 5 dans *rax sinon met 0x2d dans *rax rax+5

rabin2 -I file : information sur le fichier

r2 file

i aaa fs fs <flag> * = pour retourner à la première section f -> les affiche axt @@ str.* => trouve les références à toutes les adresses de str (@@ est un for récursif) s pour seek aka se déplacer dans le binaire s main afl pour afficher les appels de fonctions pdf pour afficher le code désassemblé VV affiche des graphs V mode visuel, p pour switch entre les modes, ; pour mettre un commentaire m pour marquer, ' pour retourner au marquage

db 0xaddr / symbole ood dc dr afficher les registres pdf montre le breakpoint et ou on se trouve

Author: rick

Email: rick@gnous.eu

Created: 2024-12-29 dim. 00:18

Validate