Angus
Angus

Reputation: 12621

Bufferoverflow on stack

I was going through the security issues in C. I could not understand the below code of how it corrupts the stack,

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

int chk_perm(){
        printf("\n Check Perm \n");
        return 2;
}
int main(int argc,char* argv[]){
        int fg;
        char filename[16];

        if(argc != 2){
                fprintf(stderr,"Usage : %s filename\n",argv[0]);
                exit(1);
        }

        fg = chk_perm();
        strcpy(filename,argv[1]);
        if(fg == 0xdeadbeef){
                //execute as root or deposit million dollars in bank account
        }
        else{
                //execute as a normal user , deduct $10 from an account
        }

        return 0;
}

The argv[1] passed may change the value of fg. Its said, that corruption will happen, if argv[1] passed is an entire binary that can cause undesired results can be passed as an argument along with return address.

I could not understand , how the strcpy corrupts the stack check_perm such that the value of the fg gets changed.

My assumption about the program,

When program starts executing, It creates a stack for the main function and put its arguments,return address,local variables onto the stack.So int fg will occupy 4 bytes (08567500 loc)of the stack and filename[16] will occupy next 16 bytes(08567504). Even if the filename is overflowing more than 16 bytes it may corrupt if any local variable was present after it.

So how does the fg gets corrupted due to strcpy(filename,argv[1]);

Upvotes: 1

Views: 151

Answers (3)

lurker
lurker

Reputation: 58224

As others have pointed out, you are writing past the filename buffer. When you do, the next item in line on the stack is the fg variable, so it will get bytes written to it if the input file name is more than 15 characters long (and then one more byte is included: the zero terminator).

You need to either make filename big enough to hold whatever a user might give you for argv[1], or prevent copying too many bytes. But it's best to allocate the space you need in this case:

char filename[PATH_MAX+1];

If you want to do it dynamically:

char *filename;

if ( !(filename = malloc(strlen(argv[1]) + 1))) ) {
    ... (failure leg)
}

Limiting the file name length to 16 bytes (actually 15 plus zero terminator) is extremely impractical for the user, especially since they may provide a full path name for the file parameter. Using a function like strncpy risks truncating the user's file name and either generating a file open error or, worse, opening the wrong file.

Upvotes: 1

NPE
NPE

Reputation: 500177

If on your architecture the stack grows downwards (as is commonly the case), fg will occupy memory immediately after filename. This means that when you write past filename, you smash fg.

Upvotes: 3

Charlie Burns
Charlie Burns

Reputation: 7044

fg is on the stack. So is filename. When you strcpy() something to filename that is larger than 16 it will overwrite fg.

Upvotes: 2

Related Questions