So it appears if I use “%11x” for one of the stack pops, it’s just the right amount. You can actually calculate this value using a calculator, but I’ve found myself usually just brute forcing it with multiple guesses.
So let’s work on the next 2 bytes. From several of the books and papers listed in the previous challenge, I found out how to handle this. You just start appending more data, with a junk buffer, and possibly some spacing, and it will continue in a similar fashion. You then just increment the byte you want to overwrite, going upwards in the memory space, so you don’t overwrite the space you already wrote the first time.
To feel out for how many stack pops we’d have to do, I experimented, and spammed an additional 15 after setting up the start of the next byte of “target”:
Now pay attention here. You’ll see after 8 stack pops, you have “41414b4e.41414141”. The first byte has some junk from a previous memory address. Since we can only pass 4 “A”s, we’ll need to buffer this a bit with additional junk bytes. To test that out, we can do:
Awesome again! We overwrote the next 2 bytes! But wait a minute. It overwrote “8e”, and we want to get “55”. There is nothing that we can add to “8e” to get “55”, as it’s larger. We can’t subtract, so this poses an issue. However, there’s nothing saying that we can’t overwrite 4 bytes instead of just 2. We could simply add to “8e” until we get “255”, since the next 4 bytes needed are “0255”. I played around with some math, and found that I could do exactly that!
This is convenient for us, because now we don’t have to do 4 separate overwrites, we can skip the third one, moving directly to the fourth. For this last pair, we will need to write “01”. Off the bat, with such a low number, I knew that we’d have to do something similar, since there’s no way we would ever be writing 0 characters in printf. We would just have to raise it to “101”, and the first “1” would get cut off into a virtual la-la land.
Again, let’s find the length of stack addresses to pop, by spamming 15 “%x”:
Alright, so it’s giving “8c”, and we need to get to “101”. That’s roughly 117 bytes difference. I started tinkering from there, and found that it needed 125 extra characters.
user@protostar:/opt/protostar/bin$ echo `perl -e 'print "\xf4\x96\x04\x08%x%x%x%x%x%x%x%x%x%x%11x%nJUNKJU\xf5\x96\x04\x08%x%x%x%x%x%x%x%463x%nJUN\xf7\x96\x04\x08%x%x%x%x%x%125x%n"'` | ./format3
you have modified the target :)
Awesome! We actually were able to overwrite an arbitrary value in memory to a specific value of our desire. Think of the implications of this. I was solving it, and afterwards read about a very new string format vulnerability in “sudo”. More information can be read here. These are real-world applications, and these bugs are found in the wild. It really blows my mind.