I am working on io-wargames for fun right now, level3:
I do understand why there is a stack-overflow in this code (strlen(argv[1])
), but what I don't understand is why it overflows the function pointer functionpointer
.
functionpointer
is declared before char buffer[50];
on the stack so How comes it overwrites it ???
Here is the main vulnerable code:
int main(int argc, char **argv, char **envp)
{
void (*functionpointer)(void) = bad;
char buffer[50];
if(argc != 2 || strlen(argv[1]) < 4)
return 0;
memcpy(buffer, argv[1], strlen(argv[1]));
memset(buffer, 0, strlen(argv[1]) - 4);
printf("This is exciting we're going to %p\n", functionpointer);
functionpointer();
return 0;
}
Here is the shell exploits the stackoverflow:
level3@io:~$ /levels/level03 11111111
This is exciting we're going to 0x80484a4
I'm so sorry, you're at 0x80484a4 and you want to be at 0x8048474
level3@io:~$ /levels/level03 111111111111111111111111111111111111111111111111111111111111111111111111111111111
This is exciting we're going to 0x31313100
Segmentation fault
Here is the objump -d
of the executable:
080484c8 <main>:
80484c8: 55 push %ebp
80484c9: 89 e5 mov %esp,%ebp
80484cb: 83 ec 78 sub $0x78,%esp
80484ce: 83 e4 f0 and $0xfffffff0,%esp
80484d1: b8 00 00 00 00 mov $0x0,%eax
80484d6: 29 c4 sub %eax,%esp
80484d8: c7 45 f4 a4 84 04 08 movl $0x80484a4,-0xc(%ebp)
80484df: 83 7d 08 02 cmpl $0x2,0x8(%ebp)
80484e3: 75 17 jne 80484fc <main+0x34>
80484e5: 8b 45 0c mov 0xc(%ebp),%eax
80484e8: 83 c0 04 add $0x4,%eax
80484eb: 8b 00 mov (%eax),%eax
80484ed: 89 04 24 mov %eax,(%esp)
80484f0: e8 a7 fe ff ff call 804839c <strlen@plt>
80484f5: 83 f8 03 cmp $0x3,%eax
80484f8: 76 02 jbe 80484fc <main+0x34>
80484fa: eb 09 jmp 8048505 <main+0x3d>
80484fc: c7 45 a4 00 00 00 00 movl $0x0,-0x5c(%ebp)
8048503: eb 74 jmp 8048579 <main+0xb1>
8048505: 8b 45 0c mov 0xc(%ebp),%eax
8048508: 83 c0 04 add $0x4,%eax
804850b: 8b 00 mov (%eax),%eax
804850d: 89 04 24 mov %eax,(%esp)
8048510: e8 87 fe ff ff call 804839c <strlen@plt>
8048515: 89 44 24 08 mov %eax,0x8(%esp)
8048519: 8b 45 0c mov 0xc(%ebp),%eax
804851c: 83 c0 04 add $0x4,%eax
804851f: 8b 00 mov (%eax),%eax
8048521: 89 44 24 04 mov %eax,0x4(%esp)
8048525: 8d 45 a8 lea -0x58(%ebp),%eax
8048528: 89 04 24 mov %eax,(%esp)
804852b: e8 5c fe ff ff call 804838c <memcpy@plt>
8048530: 8b 45 0c mov 0xc(%ebp),%eax
8048533: 83 c0 04 add $0x4,%eax
8048536: 8b 00 mov (%eax),%eax
8048538: 89 04 24 mov %eax,(%esp)
804853b: e8 5c fe ff ff call 804839c <strlen@plt>
8048540: 83 e8 04 sub $0x4,%eax
8048543: 89 44 24 08 mov %eax,0x8(%esp)
8048547: c7 44 24 04 00 00 00 movl $0x0,0x4(%esp)
804854e: 00
804854f: 8d 45 a8 lea -0x58(%ebp),%eax
8048552: 89 04 24 mov %eax,(%esp)
8048555: e8 02 fe ff ff call 804835c <memset@plt>
804855a: 8b 45 f4 mov -0xc(%ebp),%eax
804855d: 89 44 24 04 mov %eax,0x4(%esp)
8048561: c7 04 24 c0 86 04 08 movl $0x80486c0,(%esp)
8048568: e8 3f fe ff ff call 80483ac <printf@plt>
804856d: 8b 45 f4 mov -0xc(%ebp),%eax
8048570: ff d0 call *%eax
8048572: c7 45 a4 00 00 00 00 movl $0x0,-0x5c(%ebp)
8048579: 8b 45 a4 mov -0x5c(%ebp),%eax
804857c: c9 leave
804857d: c3 ret
804857e: 90 nop
804857f: 90 nop
I see that the complier reserved in the main's prolog function frame 0x78
bytes for the local main function variables.