Sunday, June 22, 2014

Exploit Exercises - Protostar - Stack 0

Upon reviewing the source code provided here , you are left with a few observations. 


1. The declaration of variables modified  and buffer, require's space to be allocated in memory.
2. modified is initialized to 0, which means 32 bits or 4 bytes of memory allocated to modified will store the binary representation of the decimal value 32.
3. gets() function is used to load the buffer.

According to cplusplus.com , gets() is used to read characters from the standard input (stdin) and stores them as a C string until a newline character or the EOF is reached. The problem with gets() begins with the fact that it does not know the size of the array that it is filling with the characters from stdin. Gets() only requires a pointer to an array as a parameter. Due to this feature, gets() will perform the task of reading characters and storing them in the array without regard to whether or not it reads more characters than the array was defined to hold. The consequence of writing more characters into the array than the array can effectively hold means that gets() will overwrite data in adjacent memory locations.

4. The if statement checks whether or not modified = 0.

Retrieving the "flag" in this exercise requires us to find a way to cause modified  to not equal 0. We can do this with a buffer overflow.

But first, let me take a selfie...I mean let's take a look at the assembly code for the stack0 executable. I viewed the assembly code 2 ways

1. command: objdump -d /opt/protostar/bin/stack0
2. IdaPro

I personally use Ida, since it's easier on the eyes, and presents the assembly code in a manner that is soothing to the eyes. To do this I used sftp to pull the files off of my guest VM onto my host machine.  Within Cygwin, I simply used sftp -P 3024 users@127.0.0.1 (where 3024 is an arbitrary value I chose when I needed to set up port forwarding so that I could ssh into my guest machine from my host machine), and transferred all of the .exe's to my host machine using the command : gets -r /opt/protostar/bin .

 Here is what the code looks like in Ida:


So, my rough interpretation of the disassembled code above is:

Once EBP is pushed onto the stack and points to the base of the stack. Then ESP value is operated on to ensure it is "aligned" to proper location in memory (a location address divisible by the word size, in this case 4 bytes is the word size and since each memory location holds 1 byte then a proper location in memory must be divisible by 4 i.e. 0x??0, 0x??4, 0x??8, etc.). The stack pointer grows down by 0x60 locations, in order to store the the 32-bit binary representation of the int value that modified represents, which is modified =0, and the 64*(size of char) = (64*1 bytes) = 64 bytes of space is allocated for variable buffer.  Register EAX is used to indicate where the head of buffer begins, which is 0x1C addresses higher than where the stack pointer currently points. Note that,  64 bytes after the head of the buffer, is where the binary representation of modified resides. Register EAX is also used to check wheter or not the 32-bit value at [ESP+x5C] still equals the binary representation of the integer value = 0. If it is the a jump occurs and the user will be asked to try "Try again", if it isn't then the user will be notified that they have successfully changed the modified variable.


Note: We know that an int variable requires 32 bits of storage, and each char element in the array requires 8 bits of storage. And Assuming that we are dealing with byte-addressable memory, then each memory location stores 1 byte.

Note: My interpreation and Visual representation of memory: I assume that ESP originally points to 0x80, then after subtracting 0x60, it points to 0x20. The 64-byte char buffer is stored at 0x3C, and the 4-byte int value is stored at 0x7C

x1F





























0































x20



























x3C


x40































x60



























x7C


x80































xA0

Solution:
Since we now the errors that can occur with using gets(), we can exploit it by inputting more than 64 characters in stdin. This will ensure that the location where modified =0  is stored is overwriting and will no longer equal 0. Let's play around with the buffer a little:




Viola!

No comments:

Post a Comment