Level 4: Nitroglycerin (10 pts Extra Credit)

If you have completed the first four levels, you have earned 100 points.  You have mastered the principles of the runtime stack operation, and you have gained firsthand experience with buffer overflow attacks.  We consider this a satisfactory mastery of the material.  You are welcome to stop right now. 

The next level is for those who want to push themselves beyond our baseline expectations for the course, and who want to face a challenge in designing buffer overflow attacks that arises in real life.  This part of the assignment only counts 10 points, even though it requires a fair amount of work to do, so don’t do it just for the points. 

From one run to another, especially by different users, the exact stack positions used by a given procedure will vary.  One reason for this variation is that the values of all environment variables are placed near the base of the stack when a program starts executing.  Environment variables are stored as strings, requiring different amounts of storage depending on their values.  Thus, the stack space allocated for a given user depends on the settings of his or her environment variables.  Stack positions also differ when running a program under gdb, since gdb uses stack space for some of its own state. 

In the code that calls getbuf, we have incorporated features that stabilize the stack, so that the position of getbuf’s stack frame will be consistent between runs.  This made it possible for you to write an exploit string knowing the exact starting address of buf and the exact saved value of %ebp.  If you tried to use such an exploit on a normal program, you would find that it works some times, but it causes segmentation faults at other times.  Hence the name “dynamite”—an explosive developed by Alfred Nobel that contains stabilizing elements to make it less prone to unexpected explosions. 

For this level, we have gone the opposite direction, making the stack positions even less stable than they normally are.  Hence the name “nitroglycerin”—an explosive that is notoriously unstable. 

When you run bufbomb with the command line flag “-n,” it will run in “Nitro” mode.  Rather than calling the function getbuf, the program calls a slightly different function getbufn:

  int getbufn()
  {
      char buf[KABOOM_BUFFER_SIZE];
      Gets(buf);
      return 1;
  }

This function is similar to getbuf, except that it has a buffer of 512 characters.  You will need this additional space to create a reliable exploit.  The code that calls getbufn first allocates a random amount of storage on the stack (using library function alloca) that ranges between 0 and 255 bytes.  Thus, if you were to sample the value of %ebp during two successive executions of getbufn, you would find they differ by as much as [-127, 127] bytes. 

In addition, when run in Nitro mode, bufbomb requires you to supply your string 5 times, and it will execute getbufn 5 times, each with a different stack offset.  Your exploit string must make it return your cookie each of these times. 

Your task is identical to the task for the Dynamite level.  Once again, your job for this level is to supply an exploit string that will cause getbufn to return your cookie back to test, rather than the value 1.  You can see in the code for test that this will cause the program to go “KABOOM!”  Your exploit code should set your cookie as the return value, restore any corrupted state, push the correct return location on the stack, and execute a ret instruction to really return to test

Some Advice:

  • You can use the program hex2raw to send multiple copies of your exploit string.  If you have a single copy in the file exploit.txt, then you can use the following command:
        unix> cat exploit.txt | hex2raw -n | bufbomb -n -u bovik
    You must use the same string for all 5 executions of getbufn.  Otherwise it will fail the testing code used by our grading server. 
  • The trick is to make use of the nop instruction.  It is encoded with a single byte (code 0x90).  You can place a long sequence of these at the beginning of your exploit code so that your code will work correctly if the initial jump lands anywhere within the sequence. 
  • You will need to restore the saved value of %ebp in a way that is insensitive to variations in stack positions. 


Back to the assignment page


Last Change: [an error occurred while processing this directive] / Michael Scott's email address