Quoted from Jonathan Garrett, Insomniac Games
Ratchet and Clank: Up Your Arsenal was an online title that shipped without the ability to patch either code or data. Which was unfortunate.
The game downloads and displays an End User License Agreement each time it’s launched. This is an ascii string stored in a static buffer. This buffer is filled from the server without checking that the size is within the buffer’s capacity.
We exploited this fact to cause the EULA download to overflow the static buffer far enough to also overwrite a known global variable. This variable happened to be the function callback handler for a specific network packet. Once this handler was installed, we could send the network packet to cause a jump to the address in the overwritten global. The address was a pointer to some payload code that was stored earlier in the EULA data.
Valuable data existed between the real end of the EULA buffer and the overwritten global, so the first job of the payload code was to restore this trashed data. Once that was done things were back to normal and the actual patching work could be done.
One complication is that the EULA text is copied with strcpy. And strcpy ends when it finds a 0 byte (which is usually the end of the string). Our string contained code which often contains 0 bytes. So we mutated the compiled code such that it contained no zero bytes and had a carefully crafted piece of bootstrap asm to un-mutate it.
By the end, the hack looked like this:
- Send oversized EULA
- Overflow EULA buffer, miscellaneous data, callback handler pointer
- Send packet to trigger handler
- Game jumps to bootstrap code pointed to by handler
- Bootstrap decodes payload data
- Payload downloads and restores stomped miscellaneous data
- Patch executes
Takeaways: Include patching code in your shipped game, and don’t use unbounded strcpy.