Reverse - JeanLouis
Analyse
En ouvrant le binaire dans Ghidra et après avoir renommé les variables, on tombe sur une sorte de memcpy
d’un shellcode qui sera xorĂ© avec une clĂ© statique ensuite par le programme.
Figure 1: Copie du shellcode et XOR de celui-ci.
SHELLCODE = "4F274DEB5442071D4F075746544F530743424F42074A484F425D074B4F624953559F232727279C26272727AEC69D3F272727EAA79F242727279C27272727AA6B03C79D37272727EAA7AEE8AD30A7D56AA7DD3928A2CC27272760AD30A7D548A7DD1C28A2FB27272760AD30A7D553A7DD1B28A2EA27272760AD30A7D543A7DD0228A29927272760AD30A7D542A7DD0128A28827272760AD30A7D557A7DD1C28A28727272760AD30A7D546A7DD3D28A2B627272760AD30A7D554A7DD0D28A2A527272760AD30A7D554A7DD31525060AD30A7D542A7DD3B524B60AD30A7D514A7DD71524660AD30A7D514A7DD6D527160AD30A7D545A7DD20526C60AD30A7D546A7DD75526760AD30A7D543A7DD70521260AD30A7D543A7DD3E520D604F0E0E2D274F0042071D4F074D48524F654E42499F232727279C26272727AEC69D28272727EAA7CC1D4D2D4F090909094F544209094F075746544F530743424F54074A484F5251464E4F6A4627279F232727279C26272727AEC69D07272727EAA7CC279F262727279C27272727EAA700"
SHELLCODE = bytes.fromhex(SHELLCODE)
final_shellcode = bytearray(len(SHELLCODE))
for k in range(0, 0x18b):
final_shellcode[k] = SHELLCODE[k] ^ 0x27
print(bytes(final_shellcode))
Il suffit de prendre le shellcode en mémoire de le copier et de placer la valeur hexa dans un site comme defuse.ca pour retrouver les instructions.
Une fois les instructions en notre possesion, on peut les mettre dans un fichier afin de les compiler :
BITS 32
section .text
global _start
_start:
push 0x73cc6a00
and [edx],bh
push 0x73617020
push 0x65642074
push 0x6f6d2065
push 0x6c207a65
push 0x72746e45
mov eax,0x4
mov ebx,0x1
mov ecx,esp
mov edx,0x18
int 0x80
mov eax,0x3
mov ebx,0x0
lea ecx,[esp-0x20]
mov edx,0x10
int 0x80
mov edi,ecx
mov dl,[edi]
xor dl,0x4d
cmp dl,0x1e
jne 0x144
inc edi
mov dl,[edi]
xor dl,0x6f
cmp dl,0x3b
jne 0x144
inc edi
mov dl,[edi]
xor dl,0x74
cmp dl,0x3c
jne 0x144
inc edi
mov dl,[edi]
xor dl,0x64
cmp dl,0x25
jne 0x144
inc edi
mov dl,[edi]
xor dl,0x65
cmp dl,0x26
jne 0x144
inc edi
mov dl,[edi]
xor dl,0x70
cmp dl,0x3b
jne 0x144
inc edi
mov dl,[edi]
xor dl,0x61
cmp dl,0x1a
jne 0x144
inc edi
mov dl,[edi]
xor dl,0x73
cmp dl,0x2a
jne 0x144
inc edi
mov dl,[edi]
xor dl,0x73
cmp dl,0x16
jne 0x144
inc edi
mov dl,[edi]
xor dl,0x65
cmp dl,0x1c
jne 0x144
inc edi
mov dl,[edi]
xor dl,0x33
cmp dl,0x56
jne 0x144
inc edi
mov dl,[edi]
xor dl,0x33
cmp dl,0x4a
jne 0x144
inc edi
mov dl,[edi]
xor dl,0x62
cmp dl,0x7
jne 0x144
inc edi
mov dl,[edi]
xor dl,0x61
cmp dl,0x52
jne 0x144
inc edi
mov dl,[edi]
xor dl,0x64
cmp dl,0x57
jne 0x144
inc edi
mov dl,[edi]
xor dl,0x64
cmp dl,0x19
jne 0x144
inc edi
push 0xa2929
push 0x3a206527
push 0x756f6a20
push 0x6e656942
mov eax,0x4
mov ebx,0x1
mov ecx,esp
mov edx,0xf
int 0x80
jmp 0x17e
push 0xa
push 0x2e2e2e2e
push 0x2e2e6573
push 0x73617020
push 0x65642074
push 0x6f6d2073
push 0x69617675
push 0x614d
mov eax,0x4
mov ebx,0x1
mov ecx,esp
mov edx,0x20
int 0x80
jmp 0x17e
mov eax,0x1
mov ebx,0x0
int 0x80
daa
Une fois compilĂ© Ă l’aide de la commande nasm -f elf32 shellcode.asm -o shellcode.o && ld -i elf_i386 shellcode.o -o shellcode
.
On peut de nouveau l’envoyer dans Ghidra pour comprendre ce qu’il fait.
Bien évidemment la condition saute au yeux et permet de récupérer le flag.
Figure 2: Condition de vérification du flag.
flag: STHACK{Yeyeye33}
Reverse - ghozt
Analyse
L’ARM est un langage avec lequel je suis beaucoup moins bon.
Pour ce challenge après avoir dĂ©couvert la fonction qui permet de faire la vĂ©rification du flag, j’ai dĂ©cidĂ© de le bruteforcer car je ne voulais pas reverse la fonction permettant de faire le calcul sur la chaĂ®ne passĂ© en argument car trop longue et chiante.
Dans un premier temps, le binaire récupère notre entré utilisateur print quelques messages et encode notre input.
Figure 1: Read, Puts, Encode.
Une fois ces actions effectués, le flag encodé est placé sur la stack et comparé avec notre input caractère par caractère.
Figure 2: Set encoded flag et check du flag avec notre input.
Si on regarde le code assembleur de cette fonction on remarque l’instruction cmp r2,r3
qui compare deux registres entre eux. Je vais pouvoir lancer un gdb-multiarch
et placer un breakpoint sur cette instruction pour checker Ă chaque fois mon input avec celui du flag.
Figure 3: Code assembleur de la boucle de vérification.
Bruteforce goes brrrrrrrrrrrrrrru
Pour le bruteforce, je vais lancer dans un chall le programme avec qemu
et je vais lui mettre le flag -g
qui permet de debug le binaire Ă l’aide de gdb
en remote.
Maintenant, il ne reste plus qu’Ă boucler caractère par caractère et vĂ©rifier la sortie de gdb
pour s’assurer que les registres sont Ă©gaux.
Voici le code python:
import subprocess
FLAG_LENGTH = 32
FLAG = ""
OLD_R3 = ""
char = -1
while char != FLAG_LENGTH:
guess = 32
char += 1
while guess != 126:
with open("/tmp/armflag", "w") as f:
f.write(FLAG + chr(guess))
CMD = [
"gdb-multiarch",
"--ex", "target remote:8090",
"--ex", "b *0x000107cc",
]
for k in range(len(FLAG) + 1):
CMD.append("--ex")
CMD.append("c")
CMD.extend(["--ex", "i r", "--ex", "q"])
process = subprocess.Popen(CMD, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
output = process.stdout.read()
for line in output.splitlines():
if line.startswith(b"r2"):
r2 = line
if line.startswith(b"r3"):
r3 = line
if OLD_R3 == r3:
continue
elif r2[2:] == r3[2:]:
print(r2)
print(r3)
FLAG += (chr(guess) if len(FLAG) == 0 else chr(guess-1))
print(f"Flag: {FLAG}")
OLD_R3 = ""
break
else:
OLD_R3 = r3
guess += 1
# while true; do cat /tmp/armflag | qemu-arm-static -g 8090 ./armfull; done
Pour chaque caractère, il va lancer la commande gdb-multiarch
, se connecter sur le binaire target remote:8090
placer un breakpoint sur 0x000107cc
continuer l’exĂ©cution du programme tant qu’on connait le caractère et lorsque qu’on ne le connait pas on regarde les registres i r
pour faire notre comparaison ensuite et on quitte q
.
Petit Ă petit le flag se dessine sur notre terminal.
Pour obtenir:
flag: STHARMK{th1s_1s_t00_3asy_F0R_M3}
Pwn
Analyse
Ce chall est typiquement le genre de chall qui n’est pas regardĂ© car il vaut beaucoup de point et pourtant qui est simple au point ou tout le monde pourrait le faire.
Une fois le binaire rĂ©cupĂ©rĂ© sur le système distant, on peut l’ouvrir dans ghidra pour comprendre son fonctionnement.
Dans un premier temps, le binaire va récupérer notre choix puis va exécuter une fonction dynamique en fonction de cela.
Figure 1: Choix de l’utilisateur.
La liste des fonctions est la suivante:
Figure 2: Liste des fonctions possible en fonction du choix.
Path to flag
En regardant de plus près la fonction choice_auth
, on remarque qu’il va regarder si des utilisateurs ont Ă©tĂ© enregistrĂ© dans le programme, si c’est le cas, alors le programme demande un nom d’utilisateur et un mot de passe et les vĂ©rifie avec le compte admin. Si les identifiants sont bon alors le flag est affichĂ© sinon un message d’erreur est affichĂ©.
Figure 3: Code de la fonction choice_auth
.
Le fichier contenant le mot de passe du compte admin et guest Ă©tant lisible pour arriver jusqu’au flag, rien de plus simple.
Il suffit de se laisser guider par le programme.
pleutre@dog:~$ cat admin.pw
flag{mA1l0c_1s_e4syY}
pleutre@dog:~$ ./dog
[1] - Add user
[2] - List available users
[3] - Delete user
[4] - Log in
[5] - Exit
.····[?] Choice
ˇ·-> 1
.····[+] Username
ˇ·-> admin
Successfully added user 'admin'.
[1] - Add user
[2] - List available users
[3] - Delete user
[4] - Log in
[5] - Exit
.····[?] Choice
ˇ·-> 1
.····[+] Username
ˇ·-> guest
Successfully added user 'guest'.
[1] - Add user
[2] - List available users
[3] - Delete user
[4] - Log in
[5] - Exit
.····[?] Choice
ˇ·-> 2
[ADDED] admin: Unbreakable password.
[ADDED] guest: Weak password.
[1] - Add user
[2] - List available users
[3] - Delete user
[4] - Log in
[5] - Exit
.····[?] Choice
ˇ·-> 4
.····[!] Username
ˇ·-> admin
.····[!] Password
ˇ·-> flag{mA1l0c_1s_e4syY}
Successfully logged in as 'admin'.
ri3n_n3_Se_P4s5e_C0mm3_pRevU
Je ne pense pas que ce soit comme ça qu’il fallait rĂ©soudre ce challenge. Typiquement au vu du nom du mot de passe admin cela aurait du ressembler Ă un double free
mais tant pis pour le créateur du challenge (Hackday devrait prendre de la graine).
flag: ri3n_n3_Se_P4s5e_C0mm3_pRevU