Direct Parameter Access
In the previous tutorial, I demonstrated how to use %x format specifiers to print values of the top of the stack and ultimately write to an arbitrary location in memory. In this case, it is not possible to input an arbitrarily long string as the code now limits the string to size buffer. However, the code still makes the mistake of passing the string directly into printf via a pointer rather than using printf(“%s”, string_ptr).
Direct parameter access works by using the $ sign specifier of the format string. For example, %n$d would access the nth parameter and display it as a decimal number. To use our’s as an example you could do something like:
./format1 `python -c ‘print “\x38\x96\x04\x08BBBBB%125\$n”‘`
as a potential solution for format1. Indeed I gave it a shot and came up with this:
You may have noticed I used python instead of perl. For whatever reason I noticed that perl does not quite print the %n format string specifier correctly, but python does. I’m not sure why this is and I haven’t investigated, but it didn’t work when I tried the perl syntax. This does the exact same thing as our format 1 solution except it does it more eloquently. Instead of having a bunch of %xs it just offsets by 125 in this case.
At this point we simply apply the technique to format2. Because format2 is reading our input in from stdin we can use a pipe to deliver the input. Now it just so happens I’m using Hacking the Art of Exploitation as a guide to figure these out and I expect whoever wrote protostar was as well because this is almost verbatim out of the book. My first guess was the following:
Now you can see we are accurately retrieving the correct value from the stack using our direct parameter access technique. Now all we have to do is change it to work with the correct address. I used objdump -t format2 | grep target to snag the address of the target variable. The address is 0x080496e4. So next I tried:
Now you can see that target was indeed changed… but not to the correct value. Indeed, we need a value of 64. Recall that the %n operator prints the number of bytes that have occurred up to this point. We can leverage this to change the value by padding our input. We can do this by using a %60d before our format string specifier, which just prints 60 characters of garbage.
And there you have it. Hope this helps.