I was reading up in the docs about multiplayer. I realized that Network.Instantiate can be called from the server and clients. So that means, the clients can instantiate anything that they want to the server. Now, if someone were to decompile a copy of a game (I’ve seen it done before) and recompile it with a few modifications, they could be spawning bullets at the speed of light. Is there any way to “cancel” a Network.Instantiate call to the server? If not, this is a really bad problem. I may be missing something though as I don’t think Unity would be this careless as to have a function like this wide open. Is there a boolean that needs to be set like, “Network.serverHasFullControl = 1;”?
decompiling, injecting custom code, and recompiling would be significantly more complex than just decompiling a unity game. If people are targeting your game like that, you’re probably a millionaire.
If you are really worried about it, you can have the server check in OnNetworkInstantiate() who the owner of the newly instantiated object is, and if it’s ever not him, send an RPC to everyone to destroy it.
First off, nobody would bother to hack your game unless it was at least fairly good, and has regular players - so i would recommend not worrying too much about it to begin with.
But you raise a valid point. What you need is to get the server to verify what the player does. The server has to check that the newly spawned bullet was spawned at a fair interval compared to the last bullet the client spawned. The server has to check that the speed at which the client moves the player corresponds to what the player is allowed to, and that the events the client triggers are within range / permission of the player and client.
Unfortunately this boils down to such a specific problem that you have to code all this manually - there’s not an “off the shelf” solution for Unity to serve you.
I guess that could be a solution, but then there’d be a potential bunch of creating and destroying (lag-ville). And yes, a game would only be targeted if it actually had a good amount of players. I’m just thinking far ahead into the future of what could possibly go wrong. A client having freedom to pretty much instantiate anything he wants would be really, really bad in the hands of the wrong person.
Do Network.Instantiate calls transmit like this:
Client>Server>All Clients
or
Client>AllClientsAndServer
If it’s the former, there should be a way to intercept and cancel calls before they even get to the clients. Like a OnRPCRecieved function that you could overwrite. That way, you could intercept and examine anything that comes in and delete it if it’s bad. I’m somewhat surprised that Unity has InitializeSecurity(), but they leave something like this wide open.
Client>AllClientsAndServer is an allowed way of calling functions. Under the hood Unity will be doing Client>Server>All Clients though.
The problem is that it is an issue specific to the solution itself and not something with networking security.
I couldn’t find any way to disable Client>AllClientsAndServer communication, so here’s one way to get around it:
You could order all clients to ignore calls from other clients by looking in NetworkMessageInfo provided on all RPC calls. Something like if(MessageWasSendByServer(info)) return;
The question remains if the NetworkMessageInfo can be forged, though.
You’ve discovered the problem with letting the client be responsible for anything in a multiplayer game. The minute you start to trust the client, your game is hackable. You can do many clever things to make it harder to hack, but you can’t prevent it 100%.
I know what you mean by “its not part of networking security”, but it really is. I mean, if someone can just decompile the game, stick in a keybind for Network.instantiate(Missle), he’s got it made. There’s no way to intercept let alone pre-process these calls. Your solution seems pretty good though.
I’ve known trusting a client in online games is a bad idea, but I’m just not sure how to stop it in Unity. There’s no way to stop Network.instantiate calls. You can’t overwrite the function (I believe) to edit and put in your own checks. I mean, the best you can do right now is check after the call is received and the object is created.
I’ve never decompiled anything, but I was looking at a topic a few months ago about using a piece of software (I think it was called Reactor or something) to decompile Unity games. In the topic, they were trying to see if they could obfuscate the code enough so they couldn’t decompile it anymore. Each time, though, the guy with the decompiler seemed to be able to do it with ease.
Using the solution above that was given by Zigs, I’ve come up with a complete solution.
First, implement all RPCs so they only go to the server. Next, make the RPCs, that when received by the server, get sent to all the clients. So any time a client tries to send RPCs, the clients will ignore it and the server can judge if it’s good or not before sending it off to the clients. It would increase bandwidth usage on the server, but it would work pretty well. What do you guys think?
decompiling a unity game just gives access to peek at code. It doesn’t give them a tidy package of scenes, project metadata, files and assets to be able to open in the unity editor and compile a new build. That feat would be just about as difficult as doing it to Call of Duty. This is a non-issue.
Also, I’m pretty sure your solution would involve rewriting part of the engine to add those checks in. You could use uLink, which has an authoritative server toggle, which will automatically throw out RPC calls by clients with targets other than the server.
I know it wouldn’t be easy, as none of the variables would have any names and it would be just a giant mass of code, but in theory it would still be possible, right? Not too long ago I didn’t know that there were applications that could change variables in memory (such as health). I know that wouldn’t apply to a properly-written online game, but what I’m saying is that people come up with these various malicious tools. So who knows what they have/are working on.
I kinda thought that’s what zigs said in his solution, but yours looks perfect. Even if the hacker did manage to put some calls using the normal Unity Network.instantiate, they’d be ignored due to the fact that the server would be using uLink, not the regular Unity Network API. They’d be forced to try to hack using uLink functions, but would fail due to that little checkbox you mentioned!
Not much more than a decompiler / assembly - and as you mention, memory injections. The problem on their side is the same problem as the one on your side: The security is so solution specific that there can’t just be a tool to solve it.
uLink does seem like a better idea than homebrewing everything. Again, no library would be able to solve all of your worries - but I’d say go for it.
The best solution: create an external library which gets loaded at gamestart, and then will compare clients files with a list of authorized files (md5 of files on the server for example) to prevent an user from modifying them.
This anticheat can work like punkbuster do, checking files, checking running process (to prevent using common tools sich as hackengine), checking openGL files (to prevent driver cheats), and finaly create an unique ID per computer, so that you can track players, computers, and ban them.
It’s an very huge project, because you’ve to maintaining cheats and players database, research on new cheats, updating often code to prevent hacking the anticheat directly… Maybe resolve false positives, etc…
I’m working on this type of solution, but it’s in a too early state to do anything with it…
Easy to hack. Just hack that DLL to always say, “Yup, they’re the same!” If you return the MD5s to the server, just hack the DLL to return data from a list, or from backup copies of the files, instead of the hacked files.