Tuesday, October 22, 2013

Reverse Engineering Unity Games

Hi. Today I will be writing about my efforts regarding reverse engineering unity games. As you may have read in a previous post, I have recently lost all my project files in a horrific idiot hard drive reformatting disaster. I was able to get my final builds back from some people I had sent it to... and actually, it just occurred to me yesterday that I had sent Unity QA a repro project for echobox that had almost all of the final source in it (except for the visualization portions and the level design), but they have yet to reply about sending me the project.

A bug or a feature?

So it turns out that reverse engineering Unity games is actually quite possible, and even somewhat easy. Is this a feature or a bug? In my case, I have a legitimate reason to reverse engineer as much code as possible from my game executables, because it will save me a ton of work trying to rebuild what I've lost. For others, I imagine this is somewhat of a headache. There is an extensive forum post about this, but that's mostly useful for back up information.

There are two tools that I used in the reverse engineering process:
A sketchy Unity asset unpacker, and .NET Reflector. The asset unpacker just takes your sharedassets0.assets file and spits out all the files in it, which is for the most part undecipherable garbage, but some of it is helpful. .NET Reflector is a magical program written by timeless space wizards that takes .NET assemblies and turns them into C# code.

So there are a few major categories of assets in a unity project that one might want to recover:
  • Art/models
  • Scenes, gameobjects, and prefabs
  • Scripts
  • Shaders
  • Compute shaders
  • Other things?
I will discuss each of these and their recoverabilities.

Art and Models

Echobox didn't actually have any custom models made for it, everything in the level is made from primitives and megafiers (a procedural mesh modification plug-in), so I didn't import any mesh assets. The same is true for textures. The asset unpacker supposedly will recover models and textures, but unity converts them to a weird format. I would rate texture recovery to be about 4 reindeer skulls (the arbitrary unit of measurement for asset recoverability), and models to be 3 reindeer skulls.

Scenes, gameobjects, and prefabs

Nope, as far as I can tell, there is no way to get this stuff back. The asset unpacker exports a lot of stuff which may or may not be prefabs, but they aren't named, and most of them are actually empty files, so I have no idea how to get back any of these things. Zero reindeer skulls.

Scripts

Ding ding ding. You can get these back! The .NET Reflector allows you to pretty much get all your script source code back. There is some compiler garbage left in for things like coroutines and also some weird stuff for structs, but otherwise, you get all your code. Class variables even keep their names, local variables get renamed to things like vector1, vector2, float1. If you understand the general structure of your code, this is by far the most recoverable portion of your project. I suppose that if you didn't write it in C#, it might be harder, but whatever. 32 reindeer skulls.

Shaders

Shaders come out of the asset unpacker, and they are actually not garbage, kind of. They have the usual unity shaderlab stuff about passes, subshaders, blending types and stuff, and then it's followed by a big string that looks like "aalkjapsaaaaajajaaakaalbbaaabacaaaaaaaaacbacbaaa..." for about 100 lines. I expect that this is the gpu/dx11 bytecode for your shader. This might be a little bit different for other platforms, or Unity in non-dx11/hlsl mode, so I don't know. The shader will actually work in Unity, I think, but you can't really make changes to it. I don't know how to reverse engineer the bytecode, and I can't even find a resource on what the big string actually is. It is valid ASCII, so I don't think that it's actually bytecode, or you'd get a lot of garbage too, so there is something going on here. I don't know. I bet Aras would know. I don't know if Unity can officially condone or support reverse engineering, even if it's for legitimate purposes. "aaaabbabaacaacabaccaaa" reindeer skulls.

Compute shaders

These don't even show up in the assets? I don't know where they're included in a unity project. I've dug through the binaries, and didn't even see words that would correspond to important things that are in compute shaders. So they must be compiled somewhere in a way that makes them something. Zero reindeer skulls.

Other Things?

Animations, mecanim state machines, terrains, sounds, I don't know, because none of these things showed up in the unity assets unpacker in any identifiable way. And also I didn't actually have any mecanims,  terrains or sound files in my game. ?? reindeer skulls.


Hyper Echobox recovery progress


I'm at about 60% now. Here's the github, you're welcome to try it out if you'd like. Propagation and raymarching are back, but voxelization of scene is not working because RWTexture writes are not supported in pixel shaders from camera drawing (I have posted some things on the forums about this). Also the visualization isn't tuned, it's just the old boring red and green again. And it's super not flexible. By that, I mean, it is hardcoded to be a certain size and also only work in a cube centered around <128,128,128>. I figure I should be ready for the presentation. A few more days and I'll have it back to where it was, at least from a technology standpoint.

Thanks for reading! Comments and questions are appreciated.