Search code examples
linuxbashshellshellcode

Shell launched from shellcode immediatly stop upon launching


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


Solution

  • 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;
    }