Dynamic Default.png files on the iPhone
Saturday, November 8th, 2008John Gruber writes:
I’ve seen third-party iPhone developers complaining that this trick is only available to Apple; they want to use it too. The technical reason why they can’t is that because application bundles are cryptographically signed, you can’t modify the contents of the application bundle (by, in this case, changing the default.png resource file) without breaking the digital signature. Apple could enable this feature for signed applications by providing for a way to specify a dynamic default.png that exists outside the application bundle, somewhere in the application’s private Library folder.
With a bit of hackery, it turns out that you can actually create dynamic Default.png files that don’t cause problems. Here’s a demo of it in action:
This is possible because OS X’s codesign binary (I’ve had far too many run-ins with it while writing the offline Wikipedia browser), used to sign and verify bundles, doesn’t traverse symlinks:
$ codesign -vv Rememberer.app
Rememberer.app: valid on disk
$ touch Rememberer.app/test
$ codesign -vv Rememberer.app
Rememberer.app: a sealed resource is missing or invalid
/Users/patrick/Projects/Rememberer/build/Debug-iphoneos/Rememberer.app/test: resource added
$ rm Rememberer.app/test
$ codesign -vv Rememberer.app
Rememberer.app: valid on disk
$ ls -l Rememberer.app/randomfile
lrwxr-xr-x 1 patrick staff 24 8 Nov 17:21 Rememberer.app/randomfile -> ../Documents/randomfile
$ dd if=/dev/random of=Documents/randomfile count=1
1+0 records in
1+0 records out
512 bytes transferred in 0.000095 secs (5382165 bytes/sec)
$ codesign -vv Rememberer.app
Rememberer.app: valid on disk
This is somewhat understandable; the symlink itself doesn’t change. But if “randomfile” is instead something like “Default.png”, the OS will happily load it from the default path in the application bundle—and follow the symlink—even though the file is actually stored in an area (Documents) that’s dynamically modifiable.
I’m guessing that Apple will consider this a bug, and fix it in some future version of the OS. If that happens, though, the downside will probably be nothing worse than losing your dynamic Default.png.
To get it to work in Xcode, you can just add a Run Script phase to the Target:
ln -sf ../Documents/Default.png $TARGET_BUILD_DIR/$CONTENTS_FOLDER_PATH
Here’s the Xcode project for the above demo. (Code is public domain.)
Update (Nov 19): TechCrunch pointed out some wider implications of this vulnerability. Although the article was met with some skepticism, they’re basically right. There’s a good summary of the situation on the McAfee Avert Labs Blog.