Jump to content
  • Advertisement
Ocarinha

C++ How to package the assets of a game and allow only the engine to be able to read?

Recommended Posts

I'm developing an engine for a 2D game in C ++ and for some days I've been looking for a way to protect the images and audio of my future game. I know there is no 100% protection and that someone would be able to open these files, but I mean the regular user who just installed the game, prevent it from modifying the sprites, change the sound, overwrite the xml files with game map data.

I downloaded some games made in Unity and noticed that a .assets extension is used, in Diablo 2 it is used .ma0, .mpq, .data, in FEZ .pak, in Super Meat Boy only a .tp file. In other words, you can not open and edit any of these files in a text editor or unzip with winrar, they offer a minimum level of protection. How is this done? Do I have to create my own binary file format or is there any program that makes it easier to work?

Share this post


Link to post
Share on other sites
Advertisement

The absolute easiest thing to do is to use an archive library like PhysFS to read files like those, maybe with password protection enabled, although it's limited to some common formats that people will generally know how to work with. You could go in and make a modified version of one of the formats that is similar but different enough to require different parsing, though now you'll need to make a tool to output that too. Another option would be to layer some encryption into the files inside the package, and that can range from simple to complex.

Share this post


Link to post
Share on other sites

 

But using PhysicsFS I could create a zip, but with another extension (my_file.xyz) preventing it from being opened by winzip for example, or that the user would change to the original name (my_file.zip) and open it?

Share this post


Link to post
Share on other sites

PhysFS is just a library for reading archives, it doesn't create them. It doesn't care about file extensions but anyone who looks at your file in a hexeditor or right click open it with 7zip will instantly know if it's zip, 7z, iso, etc.

It also only (AFAIK) handles passwords for zips with "Traditional PKWARE Encryption" but you need to put "$your_password" at the end of the path you give to PHYSFS_openRead which is annoying to do and documentation doesn't even mention that.

The last version of PhysFS is also badly busted on Windows 10 (fails to initialize and doesn't set any PHYSFS error code) so you need to take code from their Mercurial when building it, not the latest stable release from 2017: http://icculus.org/pipermail/physfs/2018-October/thread.html

You could also write own custom file format and code to work with that or implement/use one of: PHYSFS_Archiver, PHYSFS_Io, PHYSFS_mountHandle with encrypted zip storing the actual archive (I'm not sure how well it'll perform), PHYSFS_mountMemory (for small files).

But in any case a determined hacker would still find out how you store and/or decrypt it and dig your key out of your exe. Even real commercial DRM gets cracked all the time and extractors or at least format descriptions exist for most any semi-common bundle format. Security through obscurity is most that you can get.

Edit: I'd honestly say to just use a zip or 7z with reasonable settings (non-solid archive with reasonable compression level), rename it to hide its extension from total casual observer who doesn't know what a hex editor is and don't worry about it that much. For when you develop your game you can use a loose folder for convenience and only pack it all up for distribution or when making content patches (that's the point of PhysFS).

Edited by FRex
final recommendation added

Share this post


Link to post
Share on other sites
1 hour ago, Ocarinha said:

 

But using PhysicsFS I could create a zip, but with another extension (my_file.xyz) preventing it from being opened by winzip for example, or that the user would change to the original name (my_file.zip) and open it?

The easiest way to have your own pseudo-encryption is to have the output from whatever packaging library you use to go through your own decryption process before its delivered to the actual data using-code.

Effectively what you have is on build the files being encrypted and then added to a package (which can be an absolutelly standard format, such as ZIP, 7z or TAR). On the runtime side, the encrypted files are read from the package and then decrypted before being passed to whatever will use those assets.

Since you're not looking to be protected from proper hackers/crackers (a much bigger can of worms), your encryption and decryption can simply be a bitwise-XOR of the bytes of the input stream (encrypted or decrypted, it works the same both ways) with the bytes of a key. The key will of course have to be part of the application runtime either compiled in or as non-encrypted data (which is why this kind of encryption would not resist a proper hacker/cracker).

Edited by Aceticon

Share this post


Link to post
Share on other sites

Yes, if xor is fine then that's a great and simple idea actually, just wrap around whatever reading from file function you use to add xoring read buffer with your key to it. Set key to all 0s to disable it when developing the game (so you can use and edit plain files).

Share this post


Link to post
Share on other sites

A little late but if you want something more custom, you can do as I have done and write your own library format e.g. asset store. The technology base is just a file that contains some header that has an ID (32 bit hash of the asset name in my case) and an index that points to where in the file the asset is placed to. My version also allowes directories and some more advanced things.

Then you copy the asset into your file at the position written in header and you have your own package format. My packager does a little fiddling to minimize spaces between assets because I have my format chunked into 64k blocks. This way I can map the file to memory and read multiple sections at once in a multithreaded environment.

Why am I telling about this? Because I also added some protection level to the format. Assets as same as the whole header can be encrypted after packing using AES algorithm and/or be signed by an ECC based data signing algorithm. The package gets rejected by the engine when the sign dosent match or the engine crashes when the decrypted data block is broken.

This is almost safe because changing of a single bit in the file leads to a validation or decryption failure. This could protect your game also against low/mid-level hacking/modding depending on where your decryption keys come from.

To prevent further dicussions: Yes, anything could be broken later and almost game protection technology but we could make that as hard as possible :)

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!