Fair Warning: this week’s post is going to be pretty technical and will talk directly to developers. The post assumes that the reader has created their own project in Xcode, or at least knows how to build a project in Xcode and knows what the results of the build process are.
Should you be worried that I know exactly what your bundle contains? Does it bother you that I can use your files directly without your knowledge? How about this one: would you be ok with me taking your files and creating a clone of your app? This might come as a surprise to you, but unless you do something about it, there is nothing stopping someone from doing all of these things to your app. TODAY!
Bundle Organization
As I’m sure you all know by now, app bundles are shipped as a .ipa file. This is just a .zip file that’s renamed to .ipa as part of Apple’s process for iOS development. In simple terms, when you add a resource file to your Xcode project, it automatically gets included in the bundle (as you would expect). Some developers make the effort to organize their bundles into subfolders; say a folder for audio, which might have its own subfolders for music and sound effects. Another example might be graphic files split up into characters or locations or whatever.
Other developers don’t seem to care about a file tree and put everything into the root folder of their bundle. There is no real “right” way to organize your bundle contents; I suppose you should use whatever level of organization and complexity you’re comfortable with. (My personal preference is to organize the bundle so that the root folder is tidy. I’ll talk more about this in a future post, but for now I’ll leave it at that.)
Bundle Contents
The contents of your bundle, that is, the actual files your app needs in order to run properly, is really what I want to talk about this week.
The files your app needs is obviously dependent on the kind of app you’re creating. Games, for example, usually have several different kinds of files: graphics, audio, level data, and so on. (It’s more convenient for me to talk about games, but the principles apply to virtually any iOS app.)
Graphics are usually .png or .jpg. Audio files can be anything from .wav to .m4a to .mp3. Level data is usually something along the lines of a .xml file. I’m not suggesting that these are the only kinds of files you can have, I’m just sighting some examples.
The Content Problem
All of this sounds like pretty standard stuff right? If you need some graphics, more often than not you’ll use a .png (or several of them). Need some audio? No problem, just use a few .m4a files. The problem with this is that all of your files can be viewed offline by anyone whenever they want to. Sure, there is a build setting to compress PNG files (and I’m not sure if this causes them to be not-immediately viewable or not, can anyone shed some light on that?) but that’s not enough to stop someone from viewing them. Don’t believe me? Take a look at my first post about the Wired app. I pulled the various flavors of the front cover directly from the bundle; those aren’t screen grabs or doctored or modified in any way. Pretty scary!
Take .xml files as another example. That’s a human-readable format; it’s just a text file. Anyone who looks can see how your data is structured.
It boils down to this thought: if you have created a proprietary game (or engine or app) wouldn’t you want to keep it proprietary? If the thought of someone like me (a developer, or, to put it bluntly, your competition) waltzing through your data at-will makes you uncomfortable, there are some things you can do to prevent preying eyes looking through your stuff.
Some Solutions
One thing you can do is to not use ‘open’ formats and create your own. This takes time to get up and running properly because you have to spend time up front to create a converter and then a loader/parser. One of the benefits to creating your own format is that you are in complete control of it and you can change it as often as you need to, whenever you need to, instead of relying on someone else to make the changes you request. The other side of that coin is that the author of the open conversion tool you’re using could change something out from under you, forcing you to either live with using an older version, side-stepping any issues caused by upgrading the tool, or spending time finding another tool.
Another thing you can do is to compress your files. Granted, .png files are already compressed, but the idea here is to obscure the data. Compressing has the added benefit of making your bundle size smaller once it’s installed. (The download size difference is probably negligible because the bundle is already a .zip file.)
Taking the compressed files idea even further, you can group your compressed files together in a bigger file. This makes it more difficult for people to view them properly because they now have to somehow separate and extract the files. They can’t do that until they analyze the group to see what it contains.
For .xml files, you can ‘bin-ize’ them, that is, you can use a tool to convert the (very large) text files into binary representations. Various tools exist to do this, such as xml2bin (I’m sure there are others), or you can create your own if you can afford to spend the time. One thing worth mentioning here is that if your .xml files are complex, such as leaves are derived from other leaves, I’m not sure how binary converters handle that. We don’t use .xml files (for various reasons, some are talked about in this post) so I don’t know how easy or hard the binary conversion process is. I’m just stating here that options do exist for converting text-based .xml files into something more difficult to read/analyze.
Conclusions
Hopefully I have piqued your interest in wanting to hide your data. The thought of someone seeing how I have implemented something, or even worse, them using my content in their own app is a big concern for me, so I make it really tough for inquisitive eyes to figure out what I’m doing. If you want an example, I invite you to download Polyhedra Lite. It’s free and you can see how I handled the data hiding issue.
How about you? How do you hide your data? Is it even a concern for you? Why or why not? I’d love to hear what you think!













Interesting. I actually feel very much the opposite: Let people browse through my files all they want. If someone really wants to, it doesn’t matter if they’re obfuscated or not. They still don’t have the rights to use them though. So that has never been a concern for me. If anything, I love to use as many standard formats as possible to keep things simple (but of course, that’s balanced with my desire to do a straight read into memory without any parsing).
What I’ve done in the past (but have been too lazy to do in the iPhone) is create my own, large bundle files so I can read sequentially from one file instead of having many open/close. I wonder if that makes much of a difference on the iPhone though. It was clearly a huge win on CDs/DVDs and even hard drives, but iPhone? Did you measure that?
However, I’m curious about your first point about organizing the assets in the ipa file. As far as I know, if you use the XCode build system, it will flatten out any asset hierarchy that you have. That’s annoying because files have to be unique (and if they aren’t, you get no warnings). How do you preserve the directory structure?
Thanks for the thought-provoking article!
Hi Noel, thanks for the feedback!
What you’ve done in the past for disc-based platforms is exactly what I’m doing for iPhone. The seek times are non-existent, even on the earliest iDevices.
The way to build with a resource tree is to create a new Copy Files build phase to your Target. You specify the folder name to create and then you can drag whatever resource files you want put in that folder (in the ipa) over to it. Just make sure that you remove them from the main resource root or you’ll duplicate the files in the ipa: once in the root and once again where you intended. I’ve made that mistake more than once. :)
That makes sense about seek times being non-existant on iDevices. After all, the ipa file is already a bundle file!
Thanks for the tip on the copy files build phase. I’ll look into it, although I suspect that since I haven’t been dying to keep things hierarchical, I’ll go with the path of least resistance (which for 1-2 month dev cycles, it’s crucial).
Great post, one point that you didin’t touch but I think it’s not less important:
What if you are using some kind of scripting to init Classes in your app?, or even to control GameEntity behaviour?, If you use some kind of scripting language, this could lead to potential “remote code execution” ( maybe not that bad, but think about it… )
I have been thinking about putting my content in a password protected zip file. Sure , if an attacker want’s to access it, he will in the end, but at least there’s an obstruction there. (They did that in crysis, it doesn’t take a lot of effort and keeps the casual pseudo hacker away. )
I would really like to know about what Noel asked too.
Thanks for the read :-)
Thanks!
If you mean something like LUA scripts, those are just like any other file in your bundle, so they can be accessed/read/whatever just like any other file. The thing to keep in mind is if the parser can handle it being ‘read in’ from memory instead of from a file. If that’s not an issue, then you should be fine.
I think a password protected zip-within-a-zip (ipa) is overkill. There are other ways to protect your files that are much less cumbersome. Have a look at Polyhedra Lite as an example. If you have time, browse the bundle and check out the data file (there’s only one). That’s not password protected but I do make it difficult for others to figure out what the contents are (except the strings, those are too short to compress well).
Sharing infos…most iPhone developers are small 1-2 teams….is a must! It’s what indies should do.
iPhone dev is no rocket science.
The assets are (C) protected anyway. So a great developer will allways respect (C). So don’t worry showing png files.
I certainly understand the necessity to learn from others and welcome sharing ideas and open discussions. I hadn’t thought about people might also be learning by what others are doing (via their bundles). Thanks for sharing!
However, even though most developers respect the work of others, some aren’t so honest and will blatantly use and modify files that aren’t theirs.
I suppose being small is a double-edged sword; sure, the community is great, but some developers might say that their targets are too small to do anything about copyright infringement and do it knowing full well that they’re not going to be called-out. I’m of the opinion to not give them a chance to rip me off and I’ll use other avenues to share knowledge (like this blog and developer conference sessions, etc.)
Hm, ok so hiding is sometimes usefull.
I also saw some apps that’s just one file.
I am sure they did not compiled the assets into the app.
Maybe they used a kind of ramdisk filesystem.
Again, two comments from a slightly leftfield standpoint. First, for hacks, ensure the icon is never ‘hidden’ (if that’s even possible)—quite a few writers dig through ipa files to get icons for reviews. Secondly, as a user, I rather like the standard file formats for games with great soundtracks. Make a copy, extract the MP3s to iTunes, and bop away. (And, yeah, probably against the strict of the law, but I think nuts to that if I’m not copying said files for anyone else.)
The icon can’t be hidden (beyond the normal compressed png setting when the app is built) and have it still usable/approved by the App Store, so those are safe. They’re publicly accessible via the App Store browser preview anyway so even if they were hidden, they could still be obtained with reasonable ease.
Regarding the audio getting pulled though, as a developer, I do have a problem with that because it prevents me from releasing a soundtrack album (or single or whatever) for purchase. So in order to be able to do that, I either need to hide the audio, or release the soundtrack that is a quite different version (remixes, long plays or what-have-you) that is compelling enough for customers to want to purchase.
I have to say, this is something I considered doing for Hexius, but really the PNGs and WAVs would not be much use to someone else (unless they were considering using unlicensed assets in their own games).
I didn’t do this in the end, but Hexius is a very code driven game, so there isn’t much in the way of XML content in the bundle.
I think one thing to be very careful of though is to ensure XML cannot be edited so that people can fake score postings.
I always salt and obfuscate any data that would allow anyone to tamper with how the game works, or any score related data that is stored locally.
Remember that on iPhone, you should also apply this to anything you store in a PLIST file, and that includes [NSUserDefaults standardUserDefaults].
The average user won’t be able to get at this data, but anyone with a jailbroken phone could save their game progress, or set a score whilst offline, edit the data, then restart the game and post a faked high score etc.