I was curious about this so I did a bit of digging.
There are a couple of patches to do this that never made it into rsync, if you fancy compiling from source. Although both are old so they may not still work. This one specifically adds a --fat-filenames option and this one for a --tr option.
These questions also cover something similar - Rsyncing files with special characters to USB FAT32 and https://askubuntu.com/questions/11634/how-can-i-substitute-colons-when-i-rsync-on-a-usb-key. The best bet is probably rdiff-backup which does the substitution, but I can't see any options to have any control over it. There are some other good ideas too though.
A rough idea for a script that would delete and recreate the files each time, if there are not too many, would be something like:
[sudo] updatedb # doing this as root will update the system database
locate -r '^/full/path/to/source/.*[?<>\\:*|\"]' |
sed 's\^/full/path/to/source/\\' >bad_names
rsync --delete --exclude-from=bad_names -av source/ target
cd source
<bad_names pax -rw -s '/[?<>\\:*|\"]/_/gp' target
locate would be faster than find if the database is reasonably up to date.
Finally you could just do this so that the files don't cause any more problems (at least the currently existing ones):
find source/ -regex '[?<>\\:*|\"]' -exec rename 's/'[?<>\\:*|\"]'/_/g' {} +
I would recommend trying that with rename -n first though in case something goes wrong.