exiv2 will propagate whatever XML namespace it reads first into all files it writes going forward, such that reading metadata of a file with bad namespace values like xmlns:xmp="http://ns.abobe.com/xap/1.0/" (abobe, with 2 bs) or xmlns:xmpMM="(ttp://ns.adobe.com/xap/1.0/mm/" ((ttp instead of http) will cause all future metadata writes of any file to contain the same data.
To see how it works:
make demoWhich will show something like this:
make demo
./poison.sh
./poison-xmp 10946045463_8fd1864543_poisoned.jpg 10946045463_8fd1864543_o.jpg output.xmp
# ... snip ...
grep -oE 'xmlns:(xmp|xmpMM)="[^"]+"' output.xmp
xmlns:xmp="http://ns.abobe.com/xap/1.0/"
xmlns:xmpMM="(ttp://ns.adobe.com/xap/1.0/mm/"
In short, that will download a known-good JPEG, create a poisoned copy with junk data in XML namespaces, build a program that calls the exiv2 library function readMetadata() on the corrupted copy, calls readMetadata() on the original pristine copy, and writes out the metadata for the pristine copy to an XMP file. The result will have the same corrupted data as the poisoned file.
We'll use NASA's Hyperwall Shows the Sea Surface Temperature from the US Department of State's Flickr page.
./poison.sh in this directory downloads that file, then overwrites two characters from the xmp and xmpMM XML namespaces:
printf '%s' 'b' | dd of="$poison" bs=1 seek=19023 count=1 conv=notrunc 2>/dev/null
printf '%s' '(' | dd of="$poison" bs=1 seek=19209 count=1 conv=notrunc 2>/dev/nullpoison-xmp.cpp in this directory will read metadata of first the poisoned and then the pristine file, then write the XMP for the pristine file.
The make demo target builds the C++ code and runs both of the above programs, then displays the xmp and xmpMM namespace of the output XMP file.