1

My situation is something similar to this... I have a game I am currently developing in Java and I have taken a couple steps to secure the data (such as using encryption when saving local files). However one thing I was recommended by a friend is to obfuscate the code to make it confusing, and un-readable so that if someone did decide to open it up - it would be mostly useless to them.

My question breaks down into a few parts... First and foremost, as a general thought is this actually going to make it less likely for people to break/steal/copy my game, or will the impact of obfuscated code be negligible? Second, if it is worth doing - Is there any sort of performance impact?

Edit - I am mainly looking to secure the code against cheating in-game since a number of files on the client side could be manipulated to give an unfair advantage. Securing the actual binary files is an option I will have to look into at a later date; for now I am just looking at making it so the code base itself cannot be easily extracted and possibly changed.

Sh4d0wsPlyr
  • 948
  • 12
  • 28
  • 1
    Anyone with enough time and motivation can de-obfuscate the code (see Minecraft), but it's a challenge and may deter less-motivated people. It should have a negligible performance impact since it's just renaming variables and methods. – Colonel Thirty Two Jun 05 '15 at 14:42
  • I found reference in this post - http://stackoverflow.com/questions/12088/do-you-obfuscate-your-commercial-java-code?rq=1 It looks as if it can have performance impacts if you choose the wrong program to obfuscate. – Sh4d0wsPlyr Jun 05 '15 at 14:43
  • Well, it also depends on how much you want to obfuscate. Simple variable/method renaming shouldn't affect performance, but if it changes the actual code (ex. breaks strings into character arrays and use their ascii values) then it may have a hit. – Colonel Thirty Two Jun 05 '15 at 14:44
  • I have not used this for a while but perhaps compiling to a binary with gcj is also an option. Even this binary can be reverse engineered but the result is much more unreadable than decompiled Java bytecode. But be warned gcjed exes are quite big – Marged Jun 05 '15 at 14:50
  • under which license you are publishing your code? If you are not providing source codes, only thing which you really provide are binary files, and this is enough for majority cases. You could also use some tool to rename all packages, but i don't think it is very usefull. If you want secure game not code that is completly different story, – user902383 Jun 05 '15 at 14:53
  • Currently no license - However I would like to protect it for the time being. There is a chance after the project is finished, I might open source it but that would be a different story. – Sh4d0wsPlyr Jun 05 '15 at 15:16

2 Answers2

3

First of all, sorry for the amount of text I wrote.

Secondly, I totally agree with the answer to the question you linked to:
Stay away from code-flow-altering "obfuscators".
(I'd call them "scramblers", but that would be a case for English.)

Thirdly, very strictly speaking, pure obfuscation (as in class & member renaming) usually generates much shorter names (see Minecraft with it's a, b, ...) than you chose, so because the class files are shorter, loading classes might be just a tiny bit faster, and because it takes less time to compare shorter strings, member lookups will be a tiny bit faster as well, maybe resulting in a tiny performance improvement on non-static method calls.
However, the improvement is most likely going to be negligible, and if the JVM does any form of lookup caching, I wouldn't expect any performance improvement at all.
However, with only class and member renaming, I wouldn't expect the performance to drop either.

As for whether it's gonna stop people from doing evil... maybe a little.
Very lazy programmers and newbies will certainly be scared away.
And then it depends on how much someone can gain by cracking your code.
If a hacker can personally gain something from cracking your game (i.e. speedhack), I'd say there's a much bigger chance of it happening than if it's a paid game that he can make run without a license or something.
And it also depends on how much code there is and how much you need to change.
If you have around 25 classes or less, I think for a somewhat advanced developer, it wouldn't really be hard.
But an application of the size of Minecraft is a different story.
But taking Minecraft as an example, I eventually learned to find my way through the obfuscated code, as the deobfuscation lists would take longer and longer to be generated after every release and I just wanted to keep my mods up-to-date.
Making a bold claim, I'd say for me it wouldn't be much harder to crack an obfuscated java application than to crack it non-obfuscated, and I'm certainly not the only one.

Also, some obfuscators choose names completely randomly, thus releasing an update might have totally different names.
One might think that would set hackers back, but once you have a rough idea of which class stands for what in one release, you can easily find that class again in the next one by searching for strings and imported classes or members of such, and from there you can make the connection to other obfuscated classes.
(For example, in Minecraft I always started with the crafting manager, because it had the unique "###" Strings, and since it heavily used blocks and items, I could find many class right away from there.)

But you actually have one thing truly on your side: name collision.
Again with Minecraft, I realised that some files couldn't just be compiled again - not due to invalid code generated by the decompiler, but simply because a was used as a class name and a field name, the field took precedence (otherwise I could've used a and this.a - note that this only works if your obfuscator removes the package and places all classes at the top level!), and so there was no way of referencing the class other than by reflection, which was what I ended up doing in some cases. In other cases (where performance was an issue), I created sort of a "fake" class with a different name that I could compile against, and then tampered with the generated bytecode to change the name back.
So while it is still possible, it certainly is a lot of effort to go through.
If I had to work around hundreds of collisions, I would most likely have given up pretty soon.

Also, I learned that, at least with Oracle's Java implementation, versions 6 to 8, "invalid" names in the bytecode don't seem to be a problem, at least not to some extent.
In one of my projects I needed to create bytecode at runtime and I needed the generated class to contain a method with a name that would not collide with any other method that class might contain, so my first try was to use an invalid character (*) as its name, it so far (it has been out for 2 years) I haven't received any error report about a JVM rejecting it.
I don't know if there's an obfuscator out there that supports invalid names, but with a such, you could certainly generate code that would not only look horrible when decompiled, but which would be not even anywhere near compilable. I imagine something like

Some thing = field.method().whatever.array[index];

turning into:

! ? = &.%().+.*[/];

Looks neat, doesn't it? And I'm sure the compiler will love it. *evil grin*
(But even if it works, I can't recommend it, because it's just not really good practise.)

At that level, your code will still be crackable, but probably not a great deal more than machine code, so you should be sort of safe.


TL;DR

  • Stay away from code-flow-altering cruft.
  • Lots of classes = additional layer of obscurity.
  • Lots of classes = higher chance for name collision.
  • If the reward is high enough, someone will always crack it.
Community
  • 1
  • 1
Siguza
  • 21,155
  • 6
  • 52
  • 89
  • Seems reasonable and well thought out. Good to have an opinion that is also based on practical experience. Thanks for the TL;DR as well, I am sure that would help people with the long read! – Sh4d0wsPlyr Jun 05 '15 at 17:00
0

Obfuscation of code is most easily done automatically via a dedicated tool such as Proguard.

According to previous discussion, using ProGuard will have a negligible performance impact on your code.

Armand
  • 23,463
  • 20
  • 90
  • 119