ConcernedCarpet
ConcernedCarpet

Reputation: 33

Buffer overflow successful, but it shouldn't be?

This is my program, with a vulnerable char buffer, name[400].

void greeting(char *temp1,char *temp2)
{
    char name[400];
    strcpy(name,temp2);
    printf("Hello %s %s\n", temp1, name);
}

int main(int argc,char *argv[])
{
    greeting(argv[1],argv[2]);
    return 0;
}

Compiled as follows on Linux (64-bit) with ASLR disabled:

gcc -m32 -ggdb -fno-stack-protector -mpreferred-stack-boundary=2 -z execstack -o buffer buffer.c

(gdb) run Mr `perl -e 'print "A" x 400'`
Hello Mr AAAAAAA.... (truncated)
Program received signal SIGSEGV, Segmentation fault.
0x41414141 in ?? ()

(gdb) info reg eip ebp
eip            0x41414141
ebp            0x41414141

I'm assuming here that a null byte is added, resulting in the overflow, but what I don't understand is how the EIP can be 0x41414141 with only a 1 byte overflow?

EDIT: After more probing with gdb, there is no null byte added, and there is no overflow at all when only 400 bytes are entered. So how does my EIP end up pointing to my buffer contents without any overflow? I'm assuming that the absense of a null byte causes problems for printf().

Upvotes: 3

Views: 274

Answers (1)

Zach Riggle
Zach Riggle

Reputation: 3095

C string are NUL terminated, so you end up with a 1-byte overflow with a value of zero (NUL).

The one-byte NUL overflow modifies the saved value of $ebp to point lower on the stack than it should. This results in restoring an incorrect value into $esp, and control of $eip.

Take specific note of the value of ebp. After the call, the value of $ebp is still the same, but the value it points to (the value which main will restore off the stack) has been adjusted, and points into the middle of our controlled buffer.

When greeting returns into main, nothing happens. However, when main restores the stack frame with a leave instruction, the stack pointer $esp is set into the middle of our controlled buffer. When the ret instruction is executed, we have control over $eip.

Note that I've used a cyclic pattern generated by pwntools rather than the standard AAAAA since we can use it to calculate offsets. For example 'aaaa' => 0, 'aaab' => 1, 'aaba' => 2.

Before Strcpy

EBP: 0xffffc6e8 --> 0xffffc6f8 --> 0x0 
ESP: 0xffffc54c --> 0xffffc558 --> 0xffffc5c8 --> 0xf63d4e2e 
EIP: 0x8048466 (<greeting+25>:  call   0x8048320 <strcpy@plt>)

After Strcpy

EBP: 0xffffc6e8 --> 0xffffc600 ("raabsaabtaabuaabvaabwaabxaabyaab"...)
ESP: 0xffffc54c --> 0xffffc558 ("aaaabaaacaaadaaaeaaafaaagaaahaaa"...)
EIP: 0x804846b (<greeting+30>:  lea    eax,[ebp-0x190])

Before leave in main

EBP: 0xffffc600 ("raabsaabtaabuaabvaabwaabxaabyaab"...)
ESP: 0xffffc6f0 --> 0xffffc9bb ("Mister")
EIP: 0x80484b1 (<main+39>:      leave)

After leave in main

EBP: 0x62616172 (b'raab')
ESP: 0xffffc604 ("saabtaabuaabvaabwaabxaabyaabzaac"...)
EIP: 0x80484b2 (<main+40>:      ret)

At ret in main

EBP: 0x62616172 (b'raab')
ESP: 0xffffc608 ("taabuaabvaabwaabxaabyaabzaacbaac"...)
EIP: 0x62616173 (b'saab')

Upvotes: 2

Related Questions