-
-
Notifications
You must be signed in to change notification settings - Fork 98
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Provide obfuscators support for C# #1407
Comments
Uh, you know Unity's code can be deobfuscated? I know at least one project offhand that does it, trivially, one-click and you get the code... |
Well, nothing is unhackable. But to my understanding, it is much easier to modify a pure C# assembly than to modify a native binary. |
Don't confuse deobfuscation with decompilation. Yes, Unity builds (even IL2CPP builds) can be decompiled easily. However, this is where obfuscation comes into play. Classes, Fields, Method names etc. will be renamed to random characters or something similar, making the decompiled code a lot harder to read. There are also obfuscators available for Unity which will add fake code into classes, making it even more confusing for anyone who is trying to reverse engineer it. In Godot I tried to obfuscate the exported C# assembly with Obfuscar in a few different ways, with no success. In Unity on the other hand we have multiple third party assets to do the job for us, including Obfuscar. It's free, open source, and yes, it has Unity support. I also want to make this clear before someone brings this up again: I know that obfuscating game code won't make it safe from cheaters. I know that anything stored/running locally can be decompiled and modified sooner or later. This request is not about making Godot games totally cheat-proof, this is about adding a minimum of security against anyone trying to take a closer look at the game code, and against anyone who is trying to write simple cheats by modifying the .NET assembly or by using reflection. Anyone who ever made cheats or mods for .NET games before probably agrees with me that heavy obfuscation can be a massive pain in the ***. Especially if every new build/game update randomizes all method and class names again, and adds different fake code everywhere. Another sidenote: I'm mostly talking about competetive multiplayer/MMO games here. Of course such games are protected against cheating pretty well already if everything is server-based, but there is no need to let any random curious person take a clear look at the game or network logic if it can be prevented by reasonable countermeasures. |
Is there a way to at least add a post build step to the C# binaries? |
Not that I know of. |
That option only works for GDScript. It doesn't affect C# or GDNative. Note that the |
Yes, but can we create a same feature like this for C# library? |
C# obfuscation should be left to third-party tools which will do a better job at it. All Godot could do is call one of these tools when exporting the project (in a way similar to rcedit), but nobody knows how to call them yet. |
C# assembly was loaded from data, so we can encrypt data, and decrypt data when load: |
@kienvn Just a side note: encryption doesn't offer much protection. The key is in the executable and the algorithm is open source, so it is easy to decrypt and get the full original source code back. If Godot is big enough, I guess at some point there could even be tools for it to decrypt Godot games one click. |
IIRC (correct me if I'm wrong) Unity's IL2CPP feature also brings a lot of performance gains and can make deployment significantly easier for certain platforms. I'd be very interested in seeing a feature like this come to Godot. Maybe worth making a different proposal over? |
Godot's C# integration will change significantly in 4.x, so it may be too early to know whether it's feasible yet. |
Probably not worth it. While IL2CPP is about 3-5x faster than Mono, it's also quite equal to the performance of .NET Core/.NET 5 standalone applications, so it most likely would make more sense to implement .NET 6 directly instead of creating a complicated AOT compiler just for performance gains. (A proposal for .NET Core support exists already: #793) Also keep in mind that this wouldn't really fix this proposal, as IL2CPP builds still include a big load of metadata so methods can be found by string at runtime, be it for events, reflection or whatever. So doing it exactly like Unity won't fix this issue. The best option still is proper obfuscator support in my opinion. I've tried to obfuscate the DLL manually in Godot 3.4rc1 in a few different ways again, but no luck. As soon as field or method names change in the DLL, the C# scripts will break without any error or warning. It's pretty sad because Godots Webassembly way to do C# in the Browser is much better than Unity's double-compiled WebGL mess. But as long as any random person out there can download the .pck files of web exports containing all the game assets and C# scripts in clear text, we simply can't use this engine. It's like inviting everyone to write cheats or server emulators for your game. That's just not acceptable for us, especially since it could be prevented quite easily with an automated obfuscator workflow. |
I managed to obfuscate the DLL in Godot 3.4.4. I used godotpcktool 1.7 to unpack. I obfuscated mygame.dll with maximum obfuscation settings in most cases using RedGate SmartAssembly (I'm not affiliated with this product). Optionally, I removed mygame.pdb which supposedly contained debug symbols and then repacked. In my C# scripts, I made sure that all the functions that handle signals are |
It looks like Obfuscar is working fine with Godot 4.0 on a .NET 6 build. I've tested private & public class, field and method renames, including exported fields and signal methods. A few more notes:
Sure, this isn't perfect yet, but way better than the unreliable (reflection-based?) Mono version from before. I've also seen that NativeAOT support is under consideration for the future. I'm not sure how much metadata is included in NativeAOT builds, but I hope that we could get some official obfuscation implementation as hook/build step, so we can post-process the DLL in any way we want before it's getting compiled by NativeAOT. That way it would be similar to Unity with IL2CPP. (Build C# DLL -> obfuscate/post-process -> NativeAOT->native code with obfuscated/nonsense metadata) If you want to test Obfuscar yourself, remember to skip the GodotPlugins* namespace as mentioned above. Here is a config snippet for it: I haven't tested other obfuscators (with fake code injection) yet, but I assume that they will work just fine like Obfuscar, at least if they can be configured properly. |
Describe the project you are working on:
Any C# / Mono project
Describe the problem or limitation you are having in your project:
Currently nothing is done to obfuscate the C# assemblies on export with Godot Mono. This means it is easy to recovery the full source code of the game for anyone with a C# decompiler.
Of course this hurts commercial projects, since they get easy to crack.
Describe the feature / enhancement and how it helps to overcome the problem or limitation:
There are some C# obfuscators out there, which try to solve (or at least improve) the problem.
(for example https://www.obfuscar.com/)
The feature request is to Godot to support applying an obfuscator on game export.
Describe how your proposal will work, with code, pseudocode, mockups, and/or diagrams:
Godot will the the obfuscator program on the C# assembly when the user exports the game.
If this enhancement will not be used often, can it be worked around with a few lines of script?:
I don't think so.
Is there a reason why this should be core and not an add-on in the asset library?:
Many users are complaining about it and want to better protect their game resources (and scripts) for commercial projects. See:
godotengine/godot#24716
Alternative
An even better way to solve this problem and better protect the source code would be to convert C# to C++ and compile it to a native binary, just like Unity does (https://docs.unity3d.com/Manual/IL2CPP.html).
This will protect the code much better and is much harder to reverse engineer.
But it also may be harder to implement in Godot.
The text was updated successfully, but these errors were encountered: